Пример #1
0
def add_new_class_for_module(module: MypyFile, name: str,
                             bases: List[Instance],
                             fields: 'OrderedDict[str, MypyType]') -> TypeInfo:
    new_class_unique_name = checker.gen_unique_name(name, module.names)

    # make new class expression
    classdef = ClassDef(new_class_unique_name, Block([]))
    classdef.fullname = module.fullname() + '.' + new_class_unique_name

    # make new TypeInfo
    new_typeinfo = TypeInfo(SymbolTable(), classdef, module.fullname())
    new_typeinfo.bases = bases
    calculate_mro(new_typeinfo)
    new_typeinfo.calculate_metaclass_type()

    def add_field_to_new_typeinfo(var: Var,
                                  is_initialized_in_class: bool = False,
                                  is_property: bool = False) -> None:
        var.info = new_typeinfo
        var.is_initialized_in_class = is_initialized_in_class
        var.is_property = is_property
        var._fullname = new_typeinfo.fullname() + '.' + var.name()
        new_typeinfo.names[var.name()] = SymbolTableNode(MDEF, var)

    # add fields
    var_items = [Var(item, typ) for item, typ in fields.items()]
    for var_item in var_items:
        add_field_to_new_typeinfo(var_item, is_property=True)

    classdef.info = new_typeinfo
    module.names[new_class_unique_name] = SymbolTableNode(
        GDEF, new_typeinfo, plugin_generated=True)
    return new_typeinfo
Пример #2
0
def _dynamic_class_hook(ctx: DynamicClassDefContext) -> None:
    """Generate a declarative Base class when the declarative_base() function
    is encountered."""

    _add_globals(ctx)

    cls = ClassDef(ctx.name, Block([]))
    cls.fullname = ctx.api.qualified_name(ctx.name)

    info = TypeInfo(SymbolTable(), cls, ctx.api.cur_mod_id)
    cls.info = info
    _set_declarative_metaclass(ctx.api, cls)

    cls_arg = util.get_callexpr_kwarg(ctx.call, "cls", expr_types=(NameExpr, ))
    if cls_arg is not None and isinstance(cls_arg.node, TypeInfo):
        util.set_is_base(cls_arg.node)
        decl_class.scan_declarative_assignments_and_apply_types(
            cls_arg.node.defn, ctx.api, is_mixin_scan=True)
        info.bases = [Instance(cls_arg.node, [])]
    else:
        obj = ctx.api.named_type(names.NAMED_TYPE_BUILTINS_OBJECT)

        info.bases = [obj]

    try:
        calculate_mro(info)
    except MroError:
        util.fail(ctx.api, "Not able to calculate MRO for declarative base",
                  ctx.call)
        obj = ctx.api.named_type(names.NAMED_TYPE_BUILTINS_OBJECT)
        info.bases = [obj]
        info.fallback_to_any = True

    ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info))
    util.set_is_base(info)
Пример #3
0
    def analyze_namedtuple_classdef(self, defn: ClassDef, is_stub_file: bool
                                    ) -> Tuple[bool, Optional[TypeInfo]]:
        """Analyze if given class definition can be a named tuple definition.

        Return a tuple where first item indicates whether this can possibly be a named tuple,
        and the second item is the corresponding TypeInfo (may be None if not ready and should be
        deferred).
        """
        for base_expr in defn.base_type_exprs:
            if isinstance(base_expr, RefExpr):
                self.api.accept(base_expr)
                if base_expr.fullname == 'typing.NamedTuple':
                    result = self.check_namedtuple_classdef(defn, is_stub_file)
                    if result is None:
                        # This is a valid named tuple, but some types are incomplete.
                        return True, None
                    items, types, default_items = result
                    info = self.build_namedtuple_typeinfo(
                        defn.name, items, types, default_items, defn.line)
                    defn.info = info
                    defn.analyzed = NamedTupleExpr(info, is_typed=True)
                    defn.analyzed.line = defn.line
                    defn.analyzed.column = defn.column
                    # All done: this is a valid named tuple with all types known.
                    return True, info
        # This can't be a valid named tuple.
        return False, None
Пример #4
0
    def make_type_info(self,
                       name: str,
                       is_abstract: bool = False,
                       mro: List[TypeInfo] = None,
                       bases: List[Instance] = None,
                       typevars: List[str] = None) -> TypeInfo:
        """Make a TypeInfo suitable for use in unit tests."""

        class_def = ClassDef(name, Block([]), None, [])
        class_def.fullname = name

        if typevars:
            v = []  # type: List[TypeVarDef]
            id = 1
            for n in typevars:
                v.append(TypeVarDef(n, id, None, self.oi))
                id += 1
            class_def.type_vars = v

        info = TypeInfo(SymbolTable(), class_def)
        if mro is None:
            mro = []
            if name != 'builtins.object':
                mro.append(self.oi)
        info.mro = [info] + mro
        if bases is None:
            if mro:
                # By default, assume that there is a single non-generic base.
                bases = [Instance(mro[0], [])]
            else:
                bases = []
        info.bases = bases

        return info
Пример #5
0
def make_type_info(name: str,
                   is_abstract: bool = False,
                   mro: List[TypeInfo] = None,
                   bases: List[Instance] = None,
                   typevars: List[str] = None) -> TypeInfo:
    """Make a TypeInfo suitable for use in unit tests."""

    class_def = ClassDef(name, Block([]), None, [])
    class_def.fullname = name

    if typevars:
        v = []  # type: List[TypeVarDef]
        id = 1
        for n in typevars:
            v.append(TypeVarDef(n, id, None))
            id += 1
        class_def.type_vars = v

    info = TypeInfo(SymbolTable(), class_def)
    if mro is None:
        mro = []
    info.mro = [info] + mro
    if bases is None:
        if mro:
            # By default, assume that there is a single non-generic base.
            bases = [Instance(mro[0], [])]
        else:
            bases = []
    info.bases = bases

    return info
Пример #6
0
def add_new_class_for_module(module: MypyFile,
                             name: str,
                             bases: List[Instance],
                             fields: Optional[Dict[str, MypyType]] = None
                             ) -> TypeInfo:
    new_class_unique_name = checker.gen_unique_name(name, module.names)

    # make new class expression
    classdef = ClassDef(new_class_unique_name, Block([]))
    classdef.fullname = module.fullname + '.' + new_class_unique_name

    # make new TypeInfo
    new_typeinfo = TypeInfo(SymbolTable(), classdef, module.fullname)
    new_typeinfo.bases = bases
    calculate_mro(new_typeinfo)
    new_typeinfo.calculate_metaclass_type()

    # add fields
    if fields:
        for field_name, field_type in fields.items():
            var = Var(field_name, type=field_type)
            var.info = new_typeinfo
            var._fullname = new_typeinfo.fullname + '.' + field_name
            new_typeinfo.names[field_name] = SymbolTableNode(MDEF, var, plugin_generated=True)

    classdef.info = new_typeinfo
    module.names[new_class_unique_name] = SymbolTableNode(GDEF, new_typeinfo, plugin_generated=True)
    return new_typeinfo
Пример #7
0
    def analyze_namedtuple_classdef(self, defn: ClassDef) -> Tuple[bool, Optional[TypeInfo]]:
        """Analyze if given class definition can be a named tuple definition.

        Return a tuple where first item indicates whether this can possibly be a named tuple,
        and the second item is the corresponding TypeInfo (may be None if not ready and should be
        deferred).
        """
        for base_expr in defn.base_type_exprs:
            if isinstance(base_expr, RefExpr):
                self.api.accept(base_expr)
                if base_expr.fullname == 'typing.NamedTuple':
                    result = self.check_namedtuple_classdef(defn)
                    if result is None:
                        # This is a valid named tuple, but some types are incomplete.
                        return True, None
                    items, types, default_items = result
                    info = self.build_namedtuple_typeinfo(
                        defn.name, items, types, default_items, defn.line)
                    defn.info = info
                    defn.analyzed = NamedTupleExpr(info, is_typed=True)
                    defn.analyzed.line = defn.line
                    defn.analyzed.column = defn.column
                    # All done: this is a valid named tuple with all types known.
                    return True, info
        # This can't be a valid named tuple.
        return False, None
Пример #8
0
def _combine_protocols(p1: Instance, p2: Instance) -> Instance:
    def base_repr(base):
        if 'pfun.Intersection' in base.type.fullname:
            return ', '.join([repr(b) for b in base.type.bases])
        return repr(base)

    def get_bases(base):
        if 'pfun.Intersection' in base.type.fullname:
            bases = set()
            for b in base.type.bases:
                bases |= get_bases(b)
            return bases
        return set([base])

    names = p1.type.names.copy()
    names.update(p2.type.names)
    keywords = p1.type.defn.keywords.copy()
    keywords.update(p2.type.defn.keywords)
    bases = get_bases(p1) | get_bases(p2)
    bases_repr = ', '.join(sorted([repr(base) for base in bases]))
    name = f'Intersection[{bases_repr}]'
    defn = ClassDef(name, Block([]),
                    p1.type.defn.type_vars + p2.type.defn.type_vars,
                    [NameExpr(p1.type.fullname),
                     NameExpr(p2.type.fullname)], None, list(keywords.items()))
    defn.fullname = f'pfun.{name}'
    info = TypeInfo(names, defn, '')
    info.is_protocol = True
    info.is_abstract = True
    info.bases = [p1, p2]
    info.abstract_attributes = (p1.type.abstract_attributes +
                                p2.type.abstract_attributes)
    calculate_mro(info)
    return Instance(info, p1.args + p2.args)
Пример #9
0
 def visit_class_def(self, node: ClassDef) -> None:
     """Strip class body and type info, but don't strip methods."""
     self.strip_type_info(node.info)
     node.type_vars = []
     node.base_type_exprs.extend(node.removed_base_type_exprs)
     node.removed_base_type_exprs = []
     with self.enter_class(node.info):
         super().visit_class_def(node)
Пример #10
0
    def transform_class_def(self, tdef: ClassDef) -> List[Node]:        
        """Transform a type definition.

        The result may be one or two definitions.  The first is the
        transformation of the original ClassDef. The second is a
        wrapper type, which is generated for generic types only.
        """
        defs = [] # type: List[Node]
        
        if tdef.info.type_vars:
            # This is a generic type. Insert type variable slots in
            # the class definition for new type variables, i.e. type
            # variables not mapped to superclass type variables.
            defs.extend(self.make_tvar_representation(tdef.info))
        
        # Iterate over definitions and transform each of them.
        vars = set() # type: Set[Var]
        for d in tdef.defs.body:
            if isinstance(d, FuncDef):
                # Implicit cast from FuncDef[] to Node[] is safe below.
                defs.extend(Any(self.func_tf.transform_method(d)))
            elif isinstance(d, VarDef):
                defs.extend(self.transform_var_def(d))
                for n in d.items:
                    vars.add(n)
            elif isinstance(d, AssignmentStmt):
                self.transform_assignment(d)
                defs.append(d)

        # Add accessors for implicitly defined attributes.
        for node in tdef.info.names.values():
            if isinstance(node.node, Var):
                v = cast(Var, node.node)
                if v.info == tdef.info and v not in vars:
                    defs.extend(self.make_accessors(v))
        
        # For generic classes, add an implicit __init__ wrapper.
        defs.extend(self.make_init_wrapper(tdef))
        
        if tdef.is_generic() or (tdef.info.bases and
                                 tdef.info.mro[1].is_generic()):
            self.make_instance_tvar_initializer(
                cast(FuncDef, tdef.info.get_method('__init__')))

        if not defs:
            defs.append(PassStmt())

        if tdef.is_generic():
            gen_wrapper = self.generic_class_wrapper(tdef)

        tdef.defs = Block(defs)

        dyn_wrapper = self.make_type_object_wrapper(tdef)
        
        if not tdef.is_generic():
            return [tdef, dyn_wrapper]
        else:
            return [tdef, dyn_wrapper, gen_wrapper]
Пример #11
0
def _create_intersection(args, context, api):
    defn = ClassDef('Intersection', Block([]))
    defn.fullname = 'pfun.Intersection'
    info = TypeInfo({}, defn, 'pfun')
    info.is_protocol = True
    calculate_mro(info)
    i = Instance(info, args, line=context.line, column=context.column)
    intersection_translator = TranslateIntersection(api, i)
    return i.accept(intersection_translator)
Пример #12
0
def stale_info() -> TypeInfo:
    suggestion = "<stale cache: consider running mypy without --quick>"
    dummy_def = ClassDef(suggestion, Block([]))
    dummy_def.fullname = suggestion

    info = TypeInfo(SymbolTable(), dummy_def, "<stale>")
    info.mro = [info]
    info.bases = []
    return info
Пример #13
0
 def visit_class_def(self, node: ClassDef) -> ClassDef:
     new = ClassDef(node.name, self.block(node.defs), node.type_vars,
                    self.expressions(node.base_type_exprs), node.metaclass)
     new.fullname = node.fullname
     new.info = node.info
     new.decorators = [
         self.expr(decorator) for decorator in node.decorators
     ]
     return new
Пример #14
0
def stale_info() -> TypeInfo:
    suggestion = "<stale cache: consider running mypy without --quick>"
    dummy_def = ClassDef(suggestion, Block([]))
    dummy_def.fullname = suggestion

    info = TypeInfo(SymbolTable(), dummy_def, "<stale>")
    info.mro = [info]
    info.bases = []
    return info
Пример #15
0
def missing_info(modules: Dict[str, MypyFile]) -> TypeInfo:
    suggestion = _SUGGESTION.format('info')
    dummy_def = ClassDef(suggestion, Block([]))
    dummy_def.fullname = suggestion

    info = TypeInfo(SymbolTable(), dummy_def, "<missing>")
    obj_type = lookup_fully_qualified_typeinfo(modules, 'builtins.object', allow_missing=False)
    info.bases = [Instance(obj_type, [])]
    info.mro = [info, obj_type]
    return info
Пример #16
0
    def visit_class_def(self, node: ClassDef) -> None:
        """Strip class body and type info, but don't strip methods."""
        to_delete = set(self.strip_type_info(node.info))
        node.type_vars = []
        node.base_type_exprs.extend(node.removed_base_type_exprs)
        node.removed_base_type_exprs = []
        node.defs.body = [s for s in node.defs.body if s not in to_delete]

        with self.enter_class(node.info):
            super().visit_class_def(node)
Пример #17
0
 def visit_class_def(self, node: ClassDef) -> Node:
     new = ClassDef(node.name, self.block(node.defs), node.type_vars,
                    self.nodes(node.base_type_exprs), node.metaclass)
     new.fullname = node.fullname
     new.info = node.info
     new.decorators = [
         decorator.accept(self) for decorator in node.decorators
     ]
     new.is_builtinclass = node.is_builtinclass
     return new
Пример #18
0
def missing_info(modules: Dict[str, MypyFile]) -> TypeInfo:
    suggestion = "<missing info: *should* have gone away during fine-grained update>"
    dummy_def = ClassDef(suggestion, Block([]))
    dummy_def.fullname = suggestion

    info = TypeInfo(SymbolTable(), dummy_def, "<missing>")
    obj_type = lookup_qualified(modules, 'builtins.object', False)
    assert isinstance(obj_type, TypeInfo)
    info.bases = [Instance(obj_type, [])]
    info.mro = [info, obj_type]
    return info
Пример #19
0
def add_info_hook(ctx) -> None:
    class_def = ClassDef(ctx.name, Block([]))
    class_def.fullname = ctx.api.qualified_name(ctx.name)

    info = TypeInfo(SymbolTable(), class_def, ctx.api.cur_mod_id)
    class_def.info = info
    obj = ctx.api.builtin_type('builtins.object')
    info.mro = [info, obj.type]
    info.bases = [obj]
    ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info))
    info.metadata['magic'] = True
Пример #20
0
    def visit_class_def(self, node: ClassDef) -> None:
        """Strip class body and type info, but don't strip methods."""
        to_delete = set(self.strip_type_info(node.info))
        node.type_vars = []
        node.base_type_exprs.extend(node.removed_base_type_exprs)
        node.removed_base_type_exprs = []
        node.defs.body = [s for s in node.defs.body
                          if s not in to_delete]

        with self.enter_class(node.info):
            super().visit_class_def(node)
Пример #21
0
    def visit_ClassDef(self, n: ast27.ClassDef) -> ClassDef:
        self.class_nesting += 1

        cdef = ClassDef(n.name,
                        self.as_required_block(n.body, n.lineno),
                        None,
                        self.translate_expr_list(n.bases),
                        metaclass=None)
        cdef.decorators = self.translate_expr_list(n.decorator_list)
        self.class_nesting -= 1
        return cdef
Пример #22
0
def add_info_hook(ctx) -> None:
    class_def = ClassDef(ctx.name, Block([]))
    class_def.fullname = ctx.api.qualified_name(ctx.name)

    info = TypeInfo(SymbolTable(), class_def, ctx.api.cur_mod_id)
    class_def.info = info
    obj = ctx.api.named_type('builtins.object')
    info.mro = [info, obj.type]
    info.bases = [obj]
    ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info))
    info.metadata['magic'] = True
Пример #23
0
    def visit_ClassDef(self, n: ast27.ClassDef) -> ClassDef:
        self.class_nesting += 1

        cdef = ClassDef(n.name,
                        self.as_block(n.body, n.lineno),
                        None,
                        self.translate_expr_list(n.bases),
                        metaclass=None)
        cdef.decorators = self.translate_expr_list(n.decorator_list)
        self.class_nesting -= 1
        return cdef
Пример #24
0
    def visit_ClassDef(self, n: ast27.ClassDef) -> Node:
        self.class_nesting += 1

        cdef = ClassDef(n.name,
                        self.as_block(n.body, n.lineno),
                        None,
                        self.visit_list(n.bases),
                        metaclass=None)
        cdef.decorators = self.visit_list(n.decorator_list)
        self.class_nesting -= 1
        return cdef
Пример #25
0
 def visit_class_def(self, node: ClassDef) -> ClassDef:
     new = ClassDef(node.name,
                    self.block(node.defs),
                    node.type_vars,
                    self.expressions(node.base_type_exprs),
                    node.metaclass)
     new.fullname = node.fullname
     new.info = node.info
     new.decorators = [self.expr(decorator)
                       for decorator in node.decorators]
     return new
Пример #26
0
def add_info_hook(ctx):
    class_def = ClassDef(ctx.name, Block([]))
    class_def.fullname = ctx.api.qualified_name(ctx.name)

    info = TypeInfo(SymbolTable(), class_def, ctx.api.cur_mod_id)
    class_def.info = info
    obj = ctx.api.builtin_type('builtins.object')
    info.mro = [info, obj.type]
    info.bases = [obj]
    ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info))
    DECL_BASES.add(class_def.fullname)
Пример #27
0
def missing_info(modules: Dict[str, MypyFile]) -> TypeInfo:
    suggestion = "<missing info: *should* have gone away during fine-grained update>"
    dummy_def = ClassDef(suggestion, Block([]))
    dummy_def.fullname = suggestion

    info = TypeInfo(SymbolTable(), dummy_def, "<missing>")
    obj_type = lookup_qualified(modules, 'builtins.object', False)
    assert isinstance(obj_type, TypeInfo)
    info.bases = [Instance(obj_type, [])]
    info.mro = [info, obj_type]
    return info
Пример #28
0
def stale_info(modules: Dict[str, MypyFile]) -> TypeInfo:
    suggestion = "<stale cache: consider running mypy without --quick>"
    dummy_def = ClassDef(suggestion, Block([]))
    dummy_def.fullname = suggestion

    info = TypeInfo(SymbolTable(), dummy_def, "<stale>")
    obj_type = lookup_qualified(modules, 'builtins.object', False)
    assert isinstance(obj_type, TypeInfo)
    info.bases = [Instance(obj_type, [])]
    info.mro = [info, obj_type]
    return info
Пример #29
0
    def visit_ClassDef(self, n: ast27.ClassDef) -> ClassDef:
        self.class_and_function_stack.append('C')

        cdef = ClassDef(n.name,
                        self.as_required_block(n.body, n.lineno),
                        None,
                        self.translate_expr_list(n.bases),
                        metaclass=None)
        cdef.decorators = self.translate_expr_list(n.decorator_list)
        self.set_line(cdef, n)
        self.class_and_function_stack.pop()
        return cdef
Пример #30
0
def add_info_hook(ctx: DynamicClassDefContext):
    class_def = ClassDef(ctx.name, Block([]))
    class_def.fullname = ctx.api.qualified_name(ctx.name)

    info = TypeInfo(SymbolTable(), class_def, ctx.api.cur_mod_id)
    class_def.info = info
    queryset_type_fullname = ctx.call.args[0].fullname
    queryset_info = ctx.api.lookup_fully_qualified_or_none(queryset_type_fullname).node  # type: TypeInfo
    obj = ctx.api.named_type('builtins.object')
    info.mro = [info, queryset_info, obj.type]
    info.bases = [Instance(queryset_info, [])]
    ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info))
Пример #31
0
 def visit_class_def(self, cdef: ClassDef) -> None:
     kind = self.kind_by_scope()
     if kind == LDEF:
         return
     elif kind == GDEF:
         self.sem.check_no_global(cdef.name, cdef)
     cdef.fullname = self.sem.qualified_name(cdef.name)
     info = TypeInfo(SymbolTable(), cdef, self.sem.cur_mod_id)
     info.set_line(cdef.line, cdef.column)
     cdef.info = info
     if kind == GDEF:
         self.sem.globals[cdef.name] = SymbolTableNode(kind, info)
     self.process_nested_classes(cdef)
Пример #32
0
 def visit_class_def(self, cdef: ClassDef) -> None:
     kind = self.kind_by_scope()
     if kind == LDEF:
         return
     elif kind == GDEF:
         self.sem.check_no_global(cdef.name, cdef)
     cdef.fullname = self.sem.qualified_name(cdef.name)
     info = TypeInfo(SymbolTable(), cdef, self.sem.cur_mod_id)
     info.set_line(cdef.line, cdef.column)
     cdef.info = info
     if kind == GDEF:
         self.sem.globals[cdef.name] = SymbolTableNode(kind, info)
     self.process_nested_classes(cdef)
Пример #33
0
    def visit_ClassDef(self, n: ast3.ClassDef) -> ClassDef:
        self.class_nesting += 1
        keywords = [(kw.arg, self.visit(kw.value)) for kw in n.keywords
                    if kw.arg]

        cdef = ClassDef(n.name,
                        self.as_required_block(n.body, n.lineno),
                        None,
                        self.translate_expr_list(n.bases),
                        metaclass=dict(keywords).get('metaclass'),
                        keywords=keywords)
        cdef.decorators = self.translate_expr_list(n.decorator_list)
        self.class_nesting -= 1
        return cdef
Пример #34
0
    def visit_ClassDef(self, n: ast27.ClassDef) -> ClassDef:
        self.class_and_function_stack.append('C')

        cdef = ClassDef(n.name,
                        self.as_required_block(n.body, n.lineno),
                        None,
                        self.translate_expr_list(n.bases),
                        metaclass=None)
        cdef.decorators = self.translate_expr_list(n.decorator_list)
        cdef.line = n.lineno + len(n.decorator_list)
        cdef.column = n.col_offset
        cdef.end_line = n.lineno
        self.class_and_function_stack.pop()
        return cdef
Пример #35
0
    def visit_ClassDef(self, n: ast3.ClassDef) -> ClassDef:
        self.class_nesting += 1
        keywords = [(kw.arg, self.visit(kw.value))
                    for kw in n.keywords if kw.arg]

        cdef = ClassDef(n.name,
                        self.as_required_block(n.body, n.lineno),
                        None,
                        self.translate_expr_list(n.bases),
                        metaclass=dict(keywords).get('metaclass'),
                        keywords=keywords)
        cdef.decorators = self.translate_expr_list(n.decorator_list)
        self.class_nesting -= 1
        return cdef
Пример #36
0
def make_fake_register_class_instance(api: CheckerPluginInterface, type_args: Sequence[Type]
                                      ) -> Instance:
    defn = ClassDef(REGISTER_RETURN_CLASS, Block([]))
    defn.fullname = f'functools.{REGISTER_RETURN_CLASS}'
    info = TypeInfo(SymbolTable(), defn, "functools")
    obj_type = api.named_generic_type('builtins.object', []).type
    info.bases = [Instance(obj_type, [])]
    info.mro = [info, obj_type]
    defn.info = info

    func_arg = Argument(Var('name'), AnyType(TypeOfAny.implementation_artifact), None, ARG_POS)
    add_method_to_class(api, defn, '__call__', [func_arg], NoneType())

    return Instance(info, type_args)
Пример #37
0
    def visit_ClassDef(self, n: ast35.ClassDef) -> ClassDef:
        self.class_nesting += 1
        metaclass_arg = find(lambda x: x.arg == 'metaclass', n.keywords)
        metaclass = None
        if metaclass_arg:
            metaclass = self.stringify_name(metaclass_arg.value)

        cdef = ClassDef(n.name,
                        self.as_block(n.body, n.lineno),
                        None,
                        self.translate_expr_list(n.bases),
                        metaclass=metaclass)
        cdef.decorators = self.translate_expr_list(n.decorator_list)
        self.class_nesting -= 1
        return cdef
Пример #38
0
    def visit_ClassDef(self, n):
        self.in_class = True
        metaclass_arg = find(lambda x: x.arg == 'metaclass', n.keywords)
        metaclass = None
        if metaclass_arg:
            metaclass = self.stringify_name(metaclass_arg.value)

        cdef = ClassDef(n.name,
                        Block(self.fix_function_overloads(self.visit(n.body))),
                        None,
                        self.visit(n.bases),
                        metaclass=metaclass)
        cdef.decorators = self.visit(n.decorator_list)
        self.in_class = False
        return cdef
Пример #39
0
    def visit_ClassDef(self, n: ast35.ClassDef) -> Node:
        self.class_nesting += 1
        metaclass_arg = find(lambda x: x.arg == 'metaclass', n.keywords)
        metaclass = None
        if metaclass_arg:
            metaclass = self.stringify_name(metaclass_arg.value)

        cdef = ClassDef(n.name,
                        Block(self.fix_function_overloads(self.visit_list(n.body))),
                        None,
                        self.visit_list(n.bases),
                        metaclass=metaclass)
        cdef.decorators = self.visit_list(n.decorator_list)
        self.class_nesting -= 1
        return cdef
Пример #40
0
    def visit_ClassDef(self, n):
        self.in_class = True
        metaclass_arg = find(lambda x: x.arg == 'metaclass', n.keywords)
        metaclass = None
        if metaclass_arg:
            metaclass = self.stringify_name(metaclass_arg.value)

        cdef = ClassDef(n.name,
                        Block(self.fix_function_overloads(self.visit(n.body))),
                        None,
                        self.visit(n.bases),
                        metaclass=metaclass)
        cdef.decorators = self.visit(n.decorator_list)
        self.in_class = False
        return cdef
Пример #41
0
def decl_info_hook(ctx: DynamicClassDefContext) -> None:
    """Support dynamically defining declarative bases.

    For example:
        from sqlalchemy.ext.declarative import declarative_base

        Base = declarative_base()
    """
    cls_bases = []  # type: List[Instance]

    # Passing base classes as positional arguments is currently not handled.
    if 'cls' in ctx.call.arg_names:
        declarative_base_cls_arg = ctx.call.args[ctx.call.arg_names.index(
            "cls")]
        if isinstance(declarative_base_cls_arg, TupleExpr):
            items = [item for item in declarative_base_cls_arg.items]
        else:
            items = [declarative_base_cls_arg]

        for item in items:
            if isinstance(item, RefExpr) and isinstance(item.node, TypeInfo):
                base = fill_typevars_with_any(item.node)
                # TODO: Support tuple types?
                if isinstance(base, Instance):
                    cls_bases.append(base)

    class_def = ClassDef(ctx.name, Block([]))
    class_def.fullname = ctx.api.qualified_name(ctx.name)

    info = TypeInfo(SymbolTable(), class_def, ctx.api.cur_mod_id)
    class_def.info = info
    obj = ctx.api.builtin_type('builtins.object')
    info.bases = cls_bases or [obj]
    try:
        calculate_mro(info)
    except MroError:
        ctx.api.fail("Not able to calculate MRO for declarative base",
                     ctx.call)
        info.bases = [obj]
        info.fallback_to_any = True

    ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info))
    set_declarative(info)

    # TODO: check what else is added.
    add_metadata_var(ctx.api, info)
Пример #42
0
 def visit_class_def(self, node: ClassDef) -> None:
     # TODO additional things?
     node.defs.body = self.replace_statements(node.defs.body)
     node.info = self.fixup(node.info)
     for tv in node.type_vars:
         self.process_type_var_def(tv)
     self.process_type_info(node.info)
     super().visit_class_def(node)
Пример #43
0
    def visit_ClassDef(self, n: ast35.ClassDef) -> ClassDef:
        self.class_nesting += 1
        metaclass_arg = find(lambda x: x.arg == 'metaclass', n.keywords)
        metaclass = None
        if metaclass_arg:
            metaclass = self.stringify_name(metaclass_arg.value)
            if metaclass is None:
                metaclass = '<error>'  # To be reported later

        cdef = ClassDef(n.name,
                        self.as_block(n.body, n.lineno),
                        None,
                        self.translate_expr_list(n.bases),
                        metaclass=metaclass)
        cdef.decorators = self.translate_expr_list(n.decorator_list)
        self.class_nesting -= 1
        return cdef
Пример #44
0
    def make_type_info(self,
                       name: str,
                       module_name: Optional[str] = None,
                       is_abstract: bool = False,
                       mro: Optional[List[TypeInfo]] = None,
                       bases: Optional[List[Instance]] = None,
                       typevars: Optional[List[str]] = None,
                       variances: Optional[List[int]] = None) -> TypeInfo:
        """Make a TypeInfo suitable for use in unit tests."""

        class_def = ClassDef(name, Block([]), None, [])
        class_def.fullname = name

        if module_name is None:
            if '.' in name:
                module_name = name.rsplit('.', 1)[0]
            else:
                module_name = '__main__'

        if typevars:
            v: List[TypeVarLikeType] = []
            for id, n in enumerate(typevars, 1):
                if variances:
                    variance = variances[id - 1]
                else:
                    variance = COVARIANT
                v.append(TypeVarType(n, n, id, [], self.o, variance=variance))
            class_def.type_vars = v

        info = TypeInfo(SymbolTable(), class_def, module_name)
        if mro is None:
            mro = []
            if name != 'builtins.object':
                mro.append(self.oi)
        info.mro = [info] + mro
        if bases is None:
            if mro:
                # By default, assume that there is a single non-generic base.
                bases = [Instance(mro[0], [])]
            else:
                bases = []
        info.bases = bases

        return info
Пример #45
0
    def make_type_info(self, name: str,
                       module_name: Optional[str] = None,
                       is_abstract: bool = False,
                       mro: Optional[List[TypeInfo]] = None,
                       bases: Optional[List[Instance]] = None,
                       typevars: Optional[List[str]] = None,
                       variances: Optional[List[int]] = None) -> TypeInfo:
        """Make a TypeInfo suitable for use in unit tests."""

        class_def = ClassDef(name, Block([]), None, [])
        class_def.fullname = name

        if module_name is None:
            if '.' in name:
                module_name = name.rsplit('.', 1)[0]
            else:
                module_name = '__main__'

        if typevars:
            v = []  # type: List[TypeVarDef]
            for id, n in enumerate(typevars, 1):
                if variances:
                    variance = variances[id - 1]
                else:
                    variance = COVARIANT
                v.append(TypeVarDef(n, n, id, [], self.o, variance=variance))
            class_def.type_vars = v

        info = TypeInfo(SymbolTable(), class_def, module_name)
        if mro is None:
            mro = []
            if name != 'builtins.object':
                mro.append(self.oi)
        info.mro = [info] + mro
        if bases is None:
            if mro:
                # By default, assume that there is a single non-generic base.
                bases = [Instance(mro[0], [])]
            else:
                bases = []
        info.bases = bases

        return info
Пример #46
0
 def visit_class_def(self, node: ClassDef) -> None:
     """Strip class body and type info, but don't strip methods."""
     node.info.type_vars = []
     node.info.bases = []
     node.info.abstract_attributes = []
     node.info.mro = []
     node.info.add_type_vars()
     node.base_type_exprs.extend(node.removed_base_type_exprs)
     node.removed_base_type_exprs = []
     with self.enter_class(node.info):
         super().visit_class_def(node)
Пример #47
0
 def analyze_namedtuple_classdef(self, defn: ClassDef) -> Optional[TypeInfo]:
     # special case for NamedTuple
     for base_expr in defn.base_type_exprs:
         if isinstance(base_expr, RefExpr):
             self.api.accept(base_expr)
             if base_expr.fullname == 'typing.NamedTuple':
                 node = self.api.lookup(defn.name, defn)
                 if node is not None:
                     node.kind = GDEF  # TODO in process_namedtuple_definition also applies here
                     items, types, default_items = self.check_namedtuple_classdef(defn)
                     info = self.build_namedtuple_typeinfo(
                         defn.name, items, types, default_items)
                     node.node = info
                     defn.info.replaced = info
                     defn.info = info
                     defn.analyzed = NamedTupleExpr(info, is_typed=True)
                     defn.analyzed.line = defn.line
                     defn.analyzed.column = defn.column
                     return info
     return None
Пример #48
0
 def visit_class_def(self, node: ClassDef) -> None:
     """Strip class body and type info, but don't strip methods."""
     # We need to save the implicitly defined instance variables,
     # i.e. those defined as attributes on self. Otherwise, they would
     # be lost if we only reprocess top-levels (this kills TypeInfos)
     # but not the methods that defined those variables.
     if not self.recurse_into_functions:
         self.prepare_implicit_var_patches(node)
     # We need to delete any entries that were generated by plugins,
     # since they will get regenerated.
     to_delete = {v.node for v in node.info.names.values() if v.plugin_generated}
     node.type_vars = []
     node.base_type_exprs.extend(node.removed_base_type_exprs)
     node.removed_base_type_exprs = []
     node.defs.body = [s for s in node.defs.body
                       if s not in to_delete]
     with self.enter_class(node.info):
         super().visit_class_def(node)
     TypeState.reset_subtype_caches_for(node.info)
     # Kill the TypeInfo, since there is none before semantic analysis.
     node.info = CLASSDEF_NO_INFO
Пример #49
0
 def visit_class_def(self, node: ClassDef) -> None:
     # TODO additional things?
     node.info = self.fixup_and_reset_typeinfo(node.info)
     node.defs.body = self.replace_statements(node.defs.body)
     info = node.info
     for tv in node.type_vars:
         self.process_type_var_def(tv)
     if info:
         if info.is_named_tuple:
             self.process_synthetic_type_info(info)
         else:
             self.process_type_info(info)
     super().visit_class_def(node)
Пример #50
0
    def make_init_wrapper(self, tdef: ClassDef) -> List[Node]:
        """Make and return an implicit __init__ if class needs it.
        
        Otherwise, return an empty list. We include an implicit
        __init__ if the class is generic or if it extends a generic class
        and if it does not define __init__.
        
        The __init__ of a generic class requires one or more extra type
        variable arguments. The inherited __init__ may not accept these.

        For example, assume these definitions:
        
        . class A(Generic[T]): pass
        . class B(A[int]): pass
        
        The constructor for B will be (equivalent to)
        
        . def __init__(self: B) -> None:
        .     self.__tv = <int>
        .     super().__init__(<int>)
        """
        
        # FIX overloading, default args / varargs, keyword args

        info = tdef.info
        
        if '__init__' not in info.names and (
                tdef.is_generic() or (info.bases and
                                      info.mro[1].is_generic())):
            # Generic class with no explicit __init__ method
            # (i.e. __init__ inherited from superclass). Generate a
            # wrapper that initializes type variable slots and calls
            # the superclass __init__ method.

            base = info.mro[1]
            selftype = self_type(info)    
            callee_type = cast(Callable, analyse_member_access(
                '__init__', selftype, None, False, True, None, None,
                base))
            
            # Now the callee type may contain the type variables of a
            # grandparent as bound type variables, but we want the
            # type variables of the parent class. Explicitly set the
            # bound type variables.
            callee_type = self.fix_bound_init_tvars(callee_type,
                map_instance_to_supertype(selftype, base))
            
            super_init = cast(FuncDef, base.get_method('__init__'))
            
            # Build argument list.
            args = [Var('self')]
            for i in range(1, len(super_init.args)):
                args.append(Var(super_init.args[i].name()))
                args[-1].type = callee_type.arg_types[i - 1]

            selft = self_type(self.tf.type_context())
            callee_type = prepend_arg_type(callee_type, selft)
            
            creat = FuncDef('__init__', args,
                            super_init.arg_kinds, [None] * len(args),
                            Block([]))
            creat.info = tdef.info
            creat.type = callee_type
            creat.is_implicit = False
            tdef.info.names['__init__'] = SymbolTableNode(MDEF, creat,
                                                          typ=creat.type)
            
            # Insert a call to superclass constructor. If the
            # superclass is object, the constructor does nothing =>
            # omit the call.
            if base.fullname() != 'builtins.object':
                creat.body.body.append(
                    self.make_superclass_constructor_call(tdef.info,
                                                          callee_type))
            
            # Implicit cast from FuncDef[] to Node[] is safe below.
            return Any(self.func_tf.transform_method(creat))
        else:
            return []
Пример #51
0
    def analyze_typeddict_classdef(self, defn: ClassDef) -> Tuple[bool, Optional[TypeInfo]]:
        """Analyze a class that may define a TypedDict.

        Assume that base classes have been analyzed already.

        Note: Unlike normal classes, we won't create a TypeInfo until
        the whole definition of the TypeDict (including the body and all
        key names and types) is complete.  This is mostly because we
        store the corresponding TypedDictType in the TypeInfo.

        Return (is this a TypedDict, new TypeInfo). Specifics:
         * If we couldn't finish due to incomplete reference anywhere in
           the definition, return (True, None).
         * If this is not a TypedDict, return (False, None).
        """
        possible = False
        for base_expr in defn.base_type_exprs:
            if isinstance(base_expr, RefExpr):
                self.api.accept(base_expr)
                if (base_expr.fullname == 'mypy_extensions.TypedDict' or
                        self.is_typeddict(base_expr)):
                    possible = True
        if possible:
            if (len(defn.base_type_exprs) == 1 and
                    isinstance(defn.base_type_exprs[0], RefExpr) and
                    defn.base_type_exprs[0].fullname == 'mypy_extensions.TypedDict'):
                # Building a new TypedDict
                fields, types, required_keys = self.analyze_typeddict_classdef_fields(defn)
                if fields is None:
                    return True, None  # Defer
                info = self.build_typeddict_typeinfo(defn.name, fields, types, required_keys)
                defn.analyzed = TypedDictExpr(info)
                defn.analyzed.line = defn.line
                defn.analyzed.column = defn.column
                return True, info
            # Extending/merging existing TypedDicts
            if any(not isinstance(expr, RefExpr) or
                   expr.fullname != 'mypy_extensions.TypedDict' and
                   not self.is_typeddict(expr) for expr in defn.base_type_exprs):
                self.fail("All bases of a new TypedDict must be TypedDict types", defn)
            typeddict_bases = list(filter(self.is_typeddict, defn.base_type_exprs))
            keys = []  # type: List[str]
            types = []
            required_keys = set()
            for base in typeddict_bases:
                assert isinstance(base, RefExpr)
                assert isinstance(base.node, TypeInfo)
                assert isinstance(base.node.typeddict_type, TypedDictType)
                base_typed_dict = base.node.typeddict_type
                base_items = base_typed_dict.items
                valid_items = base_items.copy()
                for key in base_items:
                    if key in keys:
                        self.fail('Cannot overwrite TypedDict field "{}" while merging'
                                  .format(key), defn)
                        valid_items.pop(key)
                keys.extend(valid_items.keys())
                types.extend(valid_items.values())
                required_keys.update(base_typed_dict.required_keys)
            new_keys, new_types, new_required_keys = self.analyze_typeddict_classdef_fields(defn,
                                                                                            keys)
            if new_keys is None:
                return True, None  # Defer
            keys.extend(new_keys)
            types.extend(new_types)
            required_keys.update(new_required_keys)
            info = self.build_typeddict_typeinfo(defn.name, keys, types, required_keys)
            defn.analyzed = TypedDictExpr(info)
            defn.analyzed.line = defn.line
            defn.analyzed.column = defn.column
            return True, info
        return False, None
Пример #52
0
 def analyze_typeddict_classdef(self, defn: ClassDef) -> bool:
     # special case for TypedDict
     possible = False
     for base_expr in defn.base_type_exprs:
         if isinstance(base_expr, RefExpr):
             self.api.accept(base_expr)
             if (base_expr.fullname == 'mypy_extensions.TypedDict' or
                     self.is_typeddict(base_expr)):
                 possible = True
     if possible:
         node = self.api.lookup(defn.name, defn)
         if node is not None:
             node.kind = GDEF  # TODO in process_namedtuple_definition also applies here
             if (len(defn.base_type_exprs) == 1 and
                     isinstance(defn.base_type_exprs[0], RefExpr) and
                     defn.base_type_exprs[0].fullname == 'mypy_extensions.TypedDict'):
                 # Building a new TypedDict
                 fields, types, required_keys = self.check_typeddict_classdef(defn)
                 info = self.build_typeddict_typeinfo(defn.name, fields, types, required_keys)
                 defn.info.replaced = info
                 defn.info = info
                 node.node = info
                 defn.analyzed = TypedDictExpr(info)
                 defn.analyzed.line = defn.line
                 defn.analyzed.column = defn.column
                 return True
             # Extending/merging existing TypedDicts
             if any(not isinstance(expr, RefExpr) or
                    expr.fullname != 'mypy_extensions.TypedDict' and
                    not self.is_typeddict(expr) for expr in defn.base_type_exprs):
                 self.fail("All bases of a new TypedDict must be TypedDict types", defn)
             typeddict_bases = list(filter(self.is_typeddict, defn.base_type_exprs))
             keys = []  # type: List[str]
             types = []
             required_keys = set()
             for base in typeddict_bases:
                 assert isinstance(base, RefExpr)
                 assert isinstance(base.node, TypeInfo)
                 assert isinstance(base.node.typeddict_type, TypedDictType)
                 base_typed_dict = base.node.typeddict_type
                 base_items = base_typed_dict.items
                 valid_items = base_items.copy()
                 for key in base_items:
                     if key in keys:
                         self.fail('Cannot overwrite TypedDict field "{}" while merging'
                                   .format(key), defn)
                         valid_items.pop(key)
                 keys.extend(valid_items.keys())
                 types.extend(valid_items.values())
                 required_keys.update(base_typed_dict.required_keys)
             new_keys, new_types, new_required_keys = self.check_typeddict_classdef(defn, keys)
             keys.extend(new_keys)
             types.extend(new_types)
             required_keys.update(new_required_keys)
             info = self.build_typeddict_typeinfo(defn.name, keys, types, required_keys)
             defn.info.replaced = info
             defn.info = info
             node.node = info
             defn.analyzed = TypedDictExpr(info)
             defn.analyzed.line = defn.line
             defn.analyzed.column = defn.column
             return True
     return False