Esempio n. 1
0
    def finalize(self, ir: ClassIR) -> None:
        """Generate code to finish instantiating a dataclass.

        This works by replacing all of the attributes on the class
        (which will be descriptors) with whatever they would be in a
        non-extension class, calling dataclass, then switching them back.

        The resulting class is an extension class and instances of it do not
        have a __dict__ (unless something else requires it).
        All methods written explicitly in the source are compiled and
        may be called through the vtable while the methods generated
        by dataclasses are interpreted and may not be.

        (If we just called dataclass without doing this, it would think that all
        of the descriptors for our attributes are default values and generate an
        incorrect constructor. We need to do the switch so that dataclass gets the
        appropriate defaults.)
        """
        super().finalize(ir)
        assert self.type_obj
        add_dunders_to_non_ext_dict(self.builder, self.non_ext, self.cdef.line,
                                    self.add_annotations_to_dict)
        dec = self.builder.accept(
            next(d for d in self.cdef.decorators if is_dataclass_decorator(d)))
        self.builder.call_c(
            dataclass_sleight_of_hand,
            [dec, self.type_obj, self.non_ext.dict, self.non_ext.anns],
            self.cdef.line)
Esempio n. 2
0
def dataclass_finalize(
        builder: IRBuilder, cdef: ClassDef, non_ext: NonExtClassInfo, type_obj: Value) -> None:
    """Generate code to finish instantiating a dataclass.

    This works by replacing all of the attributes on the class
    (which will be descriptors) with whatever they would be in a
    non-extension class, calling dataclass, then switching them back.

    The resulting class is an extension class and instances of it do not
    have a __dict__ (unless something else requires it).
    All methods written explicitly in the source are compiled and
    may be called through the vtable while the methods generated
    by dataclasses are interpreted and may not be.

    (If we just called dataclass without doing this, it would think that all
    of the descriptors for our attributes are default values and generate an
    incorrect constructor. We need to do the switch so that dataclass gets the
    appropriate defaults.)
    """
    finish_non_ext_dict(builder, non_ext, cdef.line)
    dec = builder.accept(next(d for d in cdef.decorators if is_dataclass_decorator(d)))
    builder.call_c(
        dataclass_sleight_of_hand, [dec, type_obj, non_ext.dict, non_ext.anns], cdef.line)