def transform_type_info(context: mypy.plugin.ClassDefContext, proto_type_node: TypeInfo, attribute_type_node: TypeInfo, init: bool) -> TypeInfo: transformed_info: TypeInfo = context.cls.info # Get the list of proto_type class members that are not dunders or private names = [ name for name in proto_type_node.names if not name.startswith('_') ] transformedNames = [] for name in names: proto_node = proto_type_node.names[name] # SymbolTableNode if isinstance(proto_node.node, FuncDef): # Ignore methods continue transformedNames.append(name) copied_node = proto_node.copy() # SymbolTableNode copied_node.node = copy.copy(proto_node.node) # Var copied_node.node._fullname = "{}.{}".format(transformed_info.fullname, copied_node.node.name) copied_node.plugin_generated = True try: nestedTypeInfo = typeInfoByProtoTypeName.get( proto_node.node.type.type.fullname, None) except AttributeError: nestedTypeInfo = None if isinstance(proto_node.node.type, mypy.types.AnyType): # AnyType is not a transformable class anyway. pass else: print("Warning: Failed to check fullname of {}: {}".format( name, proto_node.node.type)) if nestedTypeInfo is not None: # This member's type has been transformed. copied_node.node.type = \ mypy.types.Instance(nestedTypeInfo, []) else: if attribute_type_node.is_generic(): typeArgs = [proto_node.node.type] else: typeArgs = [] copied_node.node.type = \ mypy.types.Instance(attribute_type_node, typeArgs) transformed_info.names[name] = copied_node protoTypeInstance = mypy.types.Instance(proto_type_node, []) if init: argument = Argument( Var(proto_type_node.name.lower(), protoTypeInstance), protoTypeInstance, None, ARG_POS) add_method_to_class(context.api, context.cls, "__init__", [ argument, ], mypy.types.NoneType()) add_method_to_class(context.api, context.cls, "GetProtoType", [], protoTypeInstance) # Now that the class is built, update the info for name in transformedNames: transformed_info.names[name].node.info = transformed_info return transformed_info