def prepare_func_def(module_name: str, class_name: Optional[str], fdef: FuncDef, mapper: Mapper) -> FuncDecl: kind = FUNC_STATICMETHOD if fdef.is_static else ( FUNC_CLASSMETHOD if fdef.is_class else FUNC_NORMAL) decl = FuncDecl(fdef.name, class_name, module_name, mapper.fdef_to_sig(fdef), kind) mapper.func_to_decl[fdef] = decl return decl
def prepare_class_def(path: str, module_name: str, cdef: ClassDef, errors: Errors, mapper: Mapper) -> None: ir = mapper.type_to_ir[cdef.info] info = cdef.info attrs = get_mypyc_attrs(cdef) if attrs.get("allow_interpreted_subclasses") is True: ir.allow_interpreted_subclasses = True if attrs.get("serializable") is True: # Supports copy.copy and pickle (including subclasses) ir._serializable = True # We sort the table for determinism here on Python 3.5 for name, node in sorted(info.names.items()): # Currently all plugin generated methods are dummies and not included. if node.plugin_generated: continue if isinstance(node.node, Var): assert node.node.type, "Class member %s missing type" % name if not node.node.is_classvar and name not in ('__slots__', '__deletable__'): ir.attributes[name] = mapper.type_to_rtype(node.node.type) elif isinstance(node.node, (FuncDef, Decorator)): prepare_method_def(ir, module_name, cdef, mapper, node.node) elif isinstance(node.node, OverloadedFuncDef): # Handle case for property with both a getter and a setter if node.node.is_property: if is_valid_multipart_property_def(node.node): for item in node.node.items: prepare_method_def(ir, module_name, cdef, mapper, item) else: errors.error("Unsupported property decorator semantics", path, cdef.line) # Handle case for regular function overload else: assert node.node.impl prepare_method_def(ir, module_name, cdef, mapper, node.node.impl) # Check for subclassing from builtin types for cls in info.mro: # Special case exceptions and dicts # XXX: How do we handle *other* things?? if cls.fullname == 'builtins.BaseException': ir.builtin_base = 'PyBaseExceptionObject' elif cls.fullname == 'builtins.dict': ir.builtin_base = 'PyDictObject' elif cls.fullname.startswith('builtins.'): if not can_subclass_builtin(cls.fullname): # Note that if we try to subclass a C extension class that # isn't in builtins, bad things will happen and we won't # catch it here! But this should catch a lot of the most # common pitfalls. errors.error("Inheriting from most builtin types is unimplemented", path, cdef.line) if ir.builtin_base: ir.attributes.clear() # Set up a constructor decl init_node = cdef.info['__init__'].node if not ir.is_trait and not ir.builtin_base and isinstance(init_node, FuncDef): init_sig = mapper.fdef_to_sig(init_node) defining_ir = mapper.type_to_ir.get(init_node.info) # If there is a nontrivial __init__ that wasn't defined in an # extension class, we need to make the constructor take *args, # **kwargs so it can call tp_init. if ((defining_ir is None or not defining_ir.is_ext_class or cdef.info['__init__'].plugin_generated) and init_node.info.fullname != 'builtins.object'): init_sig = FuncSignature( [init_sig.args[0], RuntimeArg("args", tuple_rprimitive, ARG_STAR), RuntimeArg("kwargs", dict_rprimitive, ARG_STAR2)], init_sig.ret_type) ctor_sig = FuncSignature(init_sig.args[1:], RInstance(ir)) ir.ctor = FuncDecl(cdef.name, None, module_name, ctor_sig) mapper.func_to_decl[cdef.info] = ir.ctor # Set up the parent class bases = [mapper.type_to_ir[base.type] for base in info.bases if base.type in mapper.type_to_ir] if not all(c.is_trait for c in bases[1:]): errors.error("Non-trait bases must appear first in parent list", path, cdef.line) ir.traits = [c for c in bases if c.is_trait] mro = [] base_mro = [] for cls in info.mro: if cls not in mapper.type_to_ir: if cls.fullname != 'builtins.object': ir.inherits_python = True continue base_ir = mapper.type_to_ir[cls] if not base_ir.is_trait: base_mro.append(base_ir) mro.append(base_ir) if cls.defn.removed_base_type_exprs or not base_ir.is_ext_class: ir.inherits_python = True base_idx = 1 if not ir.is_trait else 0 if len(base_mro) > base_idx: ir.base = base_mro[base_idx] ir.mro = mro ir.base_mro = base_mro for base in bases: if base.children is not None: base.children.append(ir) if is_dataclass(cdef): ir.is_augmented = True