Ejemplo n.º 1
0
def add_method(
        ctx: ClassDefContext,
        name: str,
        args: List[Argument],
        return_type: Type,
        self_type: Optional[Type] = None,
        tvar_def: Optional[TypeVarDef] = None,
) -> None:
    """Adds a new method to a class.
    """
    info = ctx.cls.info

    # First remove any previously generated methods with the same name
    # to avoid clashes and problems in new semantic analyzer.
    if name in info.names:
        sym = info.names[name]
        if sym.plugin_generated and isinstance(sym.node, FuncDef):
            ctx.cls.defs.body.remove(sym.node)

    self_type = self_type or fill_typevars(info)
    function_type = ctx.api.named_type('__builtins__.function')

    args = [Argument(Var('self'), self_type, None, ARG_POS)] + args
    arg_types, arg_names, arg_kinds = [], [], []
    for arg in args:
        assert arg.type_annotation, 'All arguments must be fully typed.'
        arg_types.append(arg.type_annotation)
        arg_names.append(arg.variable.name())
        arg_kinds.append(arg.kind)

    signature = CallableType(arg_types, arg_kinds, arg_names, return_type, function_type)
    if tvar_def:
        signature.variables = [tvar_def]

    func = FuncDef(name, args, Block([PassStmt()]))
    func.info = info
    func.type = set_callable_name(signature, func)
    func._fullname = info.fullname() + '.' + name
    func.line = info.line

    info.names[name] = SymbolTableNode(MDEF, func, plugin_generated=True)
    info.defn.defs.body.append(func)
Ejemplo n.º 2
0
def create_dynamic_class(
    ctx: DynamicClassDefContext,
    bases: List[Instance],
    *,
    name: Optional[str] = None,
    metaclass: Optional[str] = None,
    symbol_table: Optional[SymbolTable] = None,
) -> TypeInfo:
    if name is None:
        name = ctx.name

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

    info = TypeInfo(SymbolTable(), class_def, ctx.api.cur_mod_id)

    if metaclass is not None:
        metaclass_type_info = lookup_type_info(ctx.api, metaclass)
        if metaclass_type_info is not None:
            info.declared_metaclass = Instance(metaclass_type_info, [])

    class_def.info = info

    obj = ctx.api.builtin_type("builtins.object")
    info.bases = bases or [obj]

    try:
        calculate_mro(info)
    except MroError:
        ctx.api.fail("Not able to calculate MRO for dynamic class", ctx.call)
        info.bases = [obj]
        info.fallback_to_any = True

    if symbol_table is None:
        ctx.api.add_symbol_table_node(name, SymbolTableNode(GDEF, info))
    else:
        symbol_table[name] = SymbolTableNode(GDEF, info)

    add_metadata_var(ctx.api, info)
    add_query_cls_var(ctx.api, info)

    return info
Ejemplo n.º 3
0
        def add_method(
            funcname: str,
            ret: Type,
            args: List[Argument],
            is_classmethod: bool = False,
            is_new: bool = False,
        ) -> None:
            if is_classmethod or is_new:
                first = [
                    Argument(Var('_cls'), TypeType.make_normalized(selftype),
                             None, ARG_POS)
                ]
            else:
                first = [Argument(Var('_self'), selftype, None, ARG_POS)]
            args = first + args

            types = [arg.type_annotation for arg in args]
            items = [arg.variable.name for arg in args]
            arg_kinds = [arg.kind for arg in args]
            assert None not in types
            signature = CallableType(cast(List[Type], types), arg_kinds, items,
                                     ret, function_type)
            signature.variables = [tvd]
            func = FuncDef(funcname, args, Block([]))
            func.info = info
            func.is_class = is_classmethod
            func.type = set_callable_name(signature, func)
            func._fullname = info.fullname + '.' + funcname
            func.line = line
            if is_classmethod:
                v = Var(funcname, func.type)
                v.is_classmethod = True
                v.info = info
                v._fullname = func._fullname
                func.is_decorated = True
                dec = Decorator(func, [NameExpr('classmethod')], v)
                dec.line = line
                sym = SymbolTableNode(MDEF, dec)
            else:
                sym = SymbolTableNode(MDEF, func)
            sym.plugin_generated = True
            info.names[funcname] = sym
Ejemplo n.º 4
0
    def build_newtype_typeinfo(self, name: str, old_type: Type, base_type: Instance) -> TypeInfo:
        info = self.api.basic_new_typeinfo(name, base_type)
        info.is_newtype = True

        # Add __init__ method
        args = [Argument(Var('self'), NoneType(), None, ARG_POS),
                self.make_argument('item', old_type)]
        signature = CallableType(
            arg_types=[Instance(info, []), old_type],
            arg_kinds=[arg.kind for arg in args],
            arg_names=['self', 'item'],
            ret_type=NoneType(),
            fallback=self.api.named_type('__builtins__.function'),
            name=name)
        init_func = FuncDef('__init__', args, Block([]), typ=signature)
        init_func.info = info
        init_func._fullname = info.fullname + '.__init__'
        info.names['__init__'] = SymbolTableNode(MDEF, init_func)

        return info
Ejemplo n.º 5
0
    def translate_stmt_list(self,
                            stmts: Sequence[ast27.stmt],
                            module: bool = False) -> List[Statement]:
        # A "# type: ignore" comment before the first statement of a module
        # ignores the whole module:
        if (module and stmts and self.type_ignores
                and min(self.type_ignores) < self.get_lineno(stmts[0])):
            self.errors.used_ignored_lines[self.errors.file][min(
                self.type_ignores)].append(codes.MISC.code)
            block = Block(
                self.fix_function_overloads(self.translate_stmt_list(stmts)))
            mark_block_unreachable(block)
            return [block]

        res: List[Statement] = []
        for stmt in stmts:
            node = self.visit(stmt)
            assert isinstance(node, Statement)
            res.append(node)
        return res
def create_ortho_diff_class(base1: TypeInfo, base2: TypeInfo,
                            api: SemanticAnalyzerPluginInterface,
                            call_ctx: Context) -> Tuple[str, SymbolTableNode]:
    # https://github.com/dropbox/sqlalchemy-stubs/blob/55470ceab8149db983411d5c094c9fe16343c58b/sqlmypy.py#L173-L216
    cls_name = get_ortho_diff_name(base1.defn, base2.defn)
    class_def = ClassDef(cls_name, Block([]))
    class_def.fullname = api.qualified_name(cls_name)

    info = TypeInfo(SymbolTable(), class_def, api.cur_mod_id)
    class_def.info = info
    obj = api.builtin_type('builtins.object')
    info.bases = [cast(Instance, fill_typevars(b)) for b in (base1, base2)]
    try:
        calculate_mro(info)
    except MroError:
        api.fail('Unable to calculate MRO for dynamic class', call_ctx)
        info.bases = [obj]
        info.fallback_to_any = True

    return cls_name, SymbolTableNode(GDEF, info)
Ejemplo n.º 7
0
    def _basic_new_typeinfo(self, ctx: AnalyzeTypeContext, name: str,
                            basetype_or_fallback: Instance) -> TypeInfo:
        """
        Build a basic :class:`.TypeInfo`.

        This was basically lifted from ``mypy.semanal``.
        """
        class_def = ClassDef(name, Block([]))
        class_def.fullname = name

        info = TypeInfo(SymbolTable(), class_def, '')
        class_def.info = info
        mro = basetype_or_fallback.type.mro
        if not mro:
            mro = [
                basetype_or_fallback.type,
                named_builtin_type(ctx, 'object').type
            ]
        info.mro = [info] + mro
        info.bases = [basetype_or_fallback]
        return info
Ejemplo n.º 8
0
def decl_info_hook(ctx):
    """Support dynamically defining declarative bases.

    For example:
        from sqlalchemy.ext.declarative import declarative_base

        Base = declarative_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.mro = [info, obj.type]
    info.bases = [obj]
    ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info))
    set_declarative(info)

    # TODO: check what else is added.
    add_metadata_var(ctx, info)
Ejemplo n.º 9
0
    def dyn_class_hook(self, ctx: DynamicClassDefContext) -> TypedDictType:
        """Generate annotations from a JSON Schema."""
        schema_path, = ctx.call.args
        schema_path = os.path.abspath(schema_path.value)
        schema = self._load_schema(schema_path)
        make_type = TypeMaker(schema_path, schema)
        td_type = make_type(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)
        info.typeddict_type = td_type

        dict_type = named_builtin_type(ctx, 'dict')
        mro = dict_type.type.mro
        if not mro:
            mro = [dict_type.type, named_builtin_type(ctx, 'object').type]

        class_def.info = info
        info.mro = mro
        info.bases = [dict_type]
        ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info))
Ejemplo n.º 10
0
def analyze_formset_factory(ctx: DynamicClassDefContext) -> None:
    class_lookup = (
        "reactivated.stubs.BaseModelFormSet" if ctx.call.callee.name ==
        "modelformset_factory"  # type: ignore[attr-defined]
        else "reactivated.stubs.BaseFormSet")
    form_set_class = ctx.api.lookup_fully_qualified_or_none(class_lookup, )
    assert form_set_class is not None

    form_set_class_instance = Instance(
        form_set_class.node,
        []  # type: ignore[arg-type]
    )

    cls_bases: List[Instance] = [form_set_class_instance]
    class_def = ClassDef(ctx.name, Block([]))
    class_def.fullname = ctx.api.qualified_name(ctx.name)

    if class_def.fullname in already_analyzed:
        # Fixes an issue with max iteration counts.
        # In theory add_symbol_table_node should already guard against this but
        # it doesn't.
        return

    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

    already_analyzed[class_def.fullname] = True
    ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info))
Ejemplo n.º 11
0
    def make_type_info(self,
                       name: str,
                       is_abstract: bool = False,
                       mro: List[TypeInfo] = None,
                       bases: List[Instance] = None,
                       typevars: List[str] = None,
                       variances: List[int] = 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]
            for id, n in enumerate(typevars, 1):
                if variances:
                    variance = variances[id - 1]
                else:
                    variance = COVARIANT
                v.append(TypeVarDef(n, id, None, self.o, variance=variance))
            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
Ejemplo n.º 12
0
    def make_type_object_wrapper(self, tdef: ClassDef) -> FuncDef:
        """Construct dynamically typed wrapper function for a class.

        It simple calls the type object and returns the result.
        """
        
        # TODO keyword args, default args and varargs
        # TODO overloads

        type_sig = cast(Callable, type_object_type(tdef.info, None))
        type_sig = cast(Callable, erasetype.erase_typevars(type_sig))
        
        init = cast(FuncDef, tdef.info.get_method('__init__'))
        arg_kinds = type_sig.arg_kinds

        # The wrapper function has a dynamically typed signature.
        wrapper_sig = Callable( [AnyType()] * len(arg_kinds),
                               arg_kinds, [None] * len(arg_kinds),
                               AnyType(), False)
        
        n = NameExpr(tdef.name) # TODO full name
        args = self.func_tf.call_args(
            init.args[1:],
            type_sig,
            wrapper_sig,
            True, False)
        call = CallExpr(n, args, arg_kinds)
        ret = ReturnStmt(call)
        

        fdef = FuncDef(tdef.name + self.tf.dynamic_suffix(),
                       init.args[1:],
                       arg_kinds, [None] * len(arg_kinds),
                       Block([ret]))
        
        fdef.type = wrapper_sig
        return fdef
Ejemplo n.º 13
0
    def make_dynamic_setter_wrapper(self, name: str, typ: Type) -> FuncDef:
        """Create a dynamically-typed setter wrapper for a data attribute.

        The setter will be of this form:
        
        . def set$name*(self: C, name; Any) -> None:
        .     self.name! = {typ name}
        """
        lvalue = MemberExpr(self_expr(), name, direct=True)
        name_expr = NameExpr(name)
        rvalue = coerce(name_expr, typ, AnyType(), self.tf.type_context())
        ret = AssignmentStmt([lvalue], rvalue)

        wrapper_name = 'set$' + name + self.tf.dynamic_suffix()
        selft = self_type(self.tf.type_context())            
        sig = Callable([selft, AnyType()],
                       [nodes.ARG_POS, nodes.ARG_POS],
                       [None, None],
                       Void(), False)
        return FuncDef(wrapper_name,
                       [Var('self'), Var(name)],
                       [nodes.ARG_POS, nodes.ARG_POS],
                       [None, None],
                       Block([ret]), sig)
Ejemplo n.º 14
0
    def make_dynamic_getter_wrapper(self, name: str, typ: Type) -> FuncDef:
        """Create a dynamically-typed getter wrapper for a data attribute.

        The getter will be of this form:
        
        . def $name*(self: C) -> Any:
        .     return {Any <= typ self.name!}
        """
        scope = self.make_scope()
        selft = self.self_type()
        selfv = scope.add('self', selft)
        
        member_expr = MemberExpr(scope.name_expr('self'), name, direct=True)
        coerce_expr = coerce(member_expr, AnyType(), typ,
                             self.tf.type_context())
        ret = ReturnStmt(coerce_expr)

        wrapper_name = '$' + name + self.tf.dynamic_suffix()
        sig = Callable([selft], [nodes.ARG_POS], [None], AnyType(), False)
        return FuncDef(wrapper_name,
                       [selfv],
                       [nodes.ARG_POS],
                       [None],
                       Block([ret]), sig)
Ejemplo n.º 15
0
    def make_getter_wrapper(self, name: str, typ: Type) -> FuncDef:
        """Create a getter wrapper for a data attribute.

        The getter will be of this form:
        
        . def $name*(self: C) -> type:
        .     return self.name!
        """
        scope = self.make_scope()
        selft = self.self_type()
        selfv = scope.add('self', selft)
        
        member_expr = MemberExpr(scope.name_expr('self'), name, direct=True)
        ret = ReturnStmt(member_expr)

        wrapper_name = '$' + name
        sig = Callable([selft], [nodes.ARG_POS], [None], typ, False)
        fdef = FuncDef(wrapper_name,
                       [selfv],
                       [nodes.ARG_POS],
                       [None],
                       Block([ret]), sig)
        fdef.info = self.tf.type_context()
        return fdef
Ejemplo n.º 16
0
def infer_reachability_of_if_statement(s: IfStmt, options: Options) -> None:
    for i in range(len(s.expr)):
        result = infer_condition_value(s.expr[i], options)
        if result in (ALWAYS_FALSE, MYPY_FALSE):
            # The condition is considered always false, so we skip the if/elif body.
            mark_block_unreachable(s.body[i])
        elif result in (ALWAYS_TRUE, MYPY_TRUE):
            # This condition is considered always true, so all of the remaining
            # elif/else bodies should not be checked.
            if result == MYPY_TRUE:
                # This condition is false at runtime; this will affect
                # import priorities.
                mark_block_mypy_only(s.body[i])
            for body in s.body[i + 1:]:
                mark_block_unreachable(body)

            # Make sure else body always exists and is marked as
            # unreachable so the type checker always knows that
            # all control flow paths will flow through the if
            # statement body.
            if not s.else_body:
                s.else_body = Block([])
            mark_block_unreachable(s.else_body)
            break
Ejemplo n.º 17
0
def build_class_with_annotated_fields(api: TypeChecker, base: Type,
                                      fields: 'OrderedDict[str, Type]',
                                      name: str) -> Instance:
    """Build an Instance with `name` that contains the specified `fields` as attributes and extends `base`."""
    # Credit: This code is largely copied/modified from TypeChecker.intersect_instance_callable and
    # NamedTupleAnalyzer.build_namedtuple_typeinfo

    cur_module = cast(MypyFile, api.scope.stack[0])
    gen_name = gen_unique_name(name, cur_module.names)

    cdef = ClassDef(name, Block([]))
    cdef.fullname = cur_module.fullname() + '.' + gen_name
    info = TypeInfo(SymbolTable(), cdef, cur_module.fullname())
    cdef.info = info
    info.bases = [base]

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

    vars = [Var(item, typ) for item, typ in fields.items()]
    for var in vars:
        add_field(var, is_property=True)

    calculate_mro(info)
    info.calculate_metaclass_type()

    cur_module.names[gen_name] = SymbolTableNode(GDEF,
                                                 info,
                                                 plugin_generated=True)
    return Instance(info, [])
Ejemplo n.º 18
0
Archivo: ops.py Proyecto: kxing/mypyc
    @property
    def ret_type(self) -> RType:
        return self.sig.ret_type

    def cname(self, names: NameGenerator) -> str:
        name = self.name
        if self.class_name:
            name += '_' + self.class_name
        return names.private_name(self.module_name, name)

    def __str__(self) -> str:
        return '\n'.join(format_func(self))


INVALID_FUNC_DEF = FuncDef('<INVALID_FUNC_DEF>', [], Block([]))

# Some notes on the vtable layout:
# Each concrete class has a vtable that contains function pointers for its
# methods and for getters/setters of its attributes. So that subclasses
# may be efficiently used when their parent class is expected, the layout
# of child vtables must be an extension of their base class's vtable.
#
# This makes multiple inheritance tricky, since obviously we cannot be
# an extension of multiple parent classes. We solve this by requriing
# all but one parent to be "traits", which we can operate on in a
# somewhat less efficient way. For each trait implemented by a class,
# we generate a separate vtable for the methods in that trait.
# We then store an array of (trait type, trait vtable) pointers alongside
# a class's main vtable. When we want to call a trait method, we
# (at runtime!) search the array of trait vtables to find the correct one,
Ejemplo n.º 19
0
 def as_required_block(self, stmts: List[ast27.stmt], lineno: int) -> Block:
     assert stmts  # must be non-empty
     b = Block(self.fix_function_overloads(self.translate_stmt_list(stmts)))
     b.set_line(lineno)
     return b
Ejemplo n.º 20
0
            'line': self.line,
            'traceback_name': self.traceback_name,
        }

    @classmethod
    def deserialize(cls, data: JsonDict, ctx: DeserMaps) -> 'FuncIR':
        return FuncIR(
            FuncDecl.deserialize(data['decl'], ctx),
            [],
            Environment(),
            data['line'],
            data['traceback_name'],
        )


INVALID_FUNC_DEF = FuncDef('<INVALID_FUNC_DEF>', [], Block([]))  # type: Final


def format_blocks(blocks: List[BasicBlock], env: Environment) -> List[str]:
    # First label all of the blocks
    for i, block in enumerate(blocks):
        block.label = i

    handler_map = {}  # type: Dict[BasicBlock, List[BasicBlock]]
    for b in blocks:
        if b.error_handler:
            handler_map.setdefault(b.error_handler, []).append(b)

    lines = []
    for i, block in enumerate(blocks):
        i == len(blocks) - 1
Ejemplo n.º 21
0
 def as_block(self, stmts: List[ast27.stmt], lineno: int) -> Block:
     b = None
     if stmts:
         b = Block(self.fix_function_overloads(self.visit_list(stmts)))
         b.set_line(lineno)
     return b
Ejemplo n.º 22
0
 def visit_block(self, node: Block) -> Block:
     return Block(self.nodes(node.body))
Ejemplo n.º 23
0
 def as_block(self, stmts: List[ast27.stmt], lineno: int) -> Optional[Block]:
     b = None
     if stmts:
         b = Block(self.fix_function_overloads(self.translate_stmt_list(stmts)))
         b.set_line(lineno)
     return b
Ejemplo n.º 24
0
    def visit_instance(self, t: Instance) -> Type:
        if 'pfun.Intersection' == t.type.fullname:
            args = [get_proper_type(arg) for arg in t.args]
            if any(isinstance(arg, AnyType) for arg in args):
                return AnyType(TypeOfAny.special_form)
            if all(
                    hasattr(arg, 'type')
                    and arg.type.fullname == 'builtins.object'
                    for arg in args):
                return args[0]
            is_typevar = lambda arg: isinstance(arg, TypeVarType)
            has_type_attr = lambda arg: hasattr(arg, 'type')
            is_protocol = lambda arg: arg.type.is_protocol
            is_object = lambda arg: arg.type.fullname == 'builtins.object'
            if not all(
                    is_typevar(arg) or has_type_attr(arg) and
                (is_protocol(arg) or is_object(arg)) for arg in args):
                s = str(t)
                if self.inferred:
                    msg = (f'All arguments to "Intersection" '
                           f'must be protocols but inferred "{s}"')
                else:
                    msg = (f'All arguments to "Intersection" '
                           f'must be protocols, but got "{s}"')
                self.api.msg.fail(msg, self.context)
                return AnyType(TypeOfAny.special_form)
            if not has_no_typevars(t):
                return t
            bases = []
            for arg in args:
                if arg in bases:
                    continue
                bases.extend(self.get_bases(arg, []))
            if len(bases) == 1:
                return bases[0]
            bases_repr = ', '.join([repr(base) for base in bases])
            name = f'Intersection[{bases_repr}]'
            defn = ClassDef(name, Block([]), [], [
                NameExpr(arg.name) if isinstance(arg, TypeVarType) else
                NameExpr(arg.type.fullname) for arg in args
            ], None, [])
            defn.fullname = f'pfun.{name}'
            info = TypeInfo({}, defn, '')
            info.is_protocol = True
            info.is_abstract = True
            info.bases = bases
            attrs = []
            for base in bases:
                if isinstance(base, TypeVarType):
                    continue
                attrs.extend(base.type.abstract_attributes)
            info.abstract_attributes = attrs
            try:
                calculate_mro(info)
            except MroError:
                self.api.msg.fail(
                    'Cannot determine consistent method resolution '
                    'order (MRO) for "%s"' % defn.fullname, self.context)
                return AnyType(TypeOfAny.special_form)
            return Instance(info, [])

        return super().visit_instance(t)
Ejemplo n.º 25
0
 def visit_block(self, node: Block) -> Block:
     return Block(self.statements(node.body))
Ejemplo n.º 26
0
def _add_method(
    ctx: ClassDefContext,
    name: str,
    args: List[Argument],
    return_type: mypy.types.Type,
    self_type: Optional[mypy.types.Type] = None,
    tvar_def: Optional[mypy.types.TypeVarDef] = None,
    is_classmethod: bool = False,
) -> None:
    """Adds a new method to a class.
    """
    info = ctx.cls.info

    # First remove any previously generated methods with the same name
    # to avoid clashes and problems in new semantic analyzer.
    if name in info.names:
        sym = info.names[name]
        if sym.plugin_generated and isinstance(sym.node, FuncDef):
            ctx.cls.defs.body.remove(sym.node)

    if is_classmethod:
        first = Argument(
            Var('cls'),
            # Working around python/mypy#5416.
            # This should be: mypy.types.TypeType.make_normalized(self_type)
            mypy.types.AnyType(mypy.types.TypeOfAny.implementation_artifact),
            None,
            ARG_POS)
    else:
        self_type = self_type or fill_typevars(info)
        first = Argument(Var('self'), self_type, None, ARG_POS)

    args = [first] + args

    function_type = ctx.api.named_type('__builtins__.function')

    arg_types, arg_names, arg_kinds = [], [], []
    for arg in args:
        assert arg.type_annotation, 'All arguments must be fully typed.'
        arg_types.append(arg.type_annotation)
        arg_names.append(get_name(arg.variable))
        arg_kinds.append(arg.kind)

    signature = mypy.types.CallableType(arg_types, arg_kinds, arg_names,
                                        return_type, function_type)
    if tvar_def:
        signature.variables = [tvar_def]

    func = FuncDef(name, args, Block([PassStmt()]))
    func.info = info
    func.is_class = is_classmethod
    func.type = set_callable_name(signature, func)
    func._fullname = get_fullname(info) + '.' + name
    func.line = info.line

    # NOTE: we would like the plugin generated node to dominate, but we still
    # need to keep any existing definitions so they get semantically analyzed.
    if name in info.names:
        # Get a nice unique name instead.
        r_name = get_unique_redefinition_name(name, info.names)
        info.names[r_name] = info.names[name]

    info.defn.defs.body.append(func)
    info.names[name] = SymbolTableNode(MDEF, func, plugin_generated=True)
Ejemplo n.º 27
0
            'line': self.line,
            'traceback_name': self.traceback_name,
        }

    @classmethod
    def deserialize(cls, data: JsonDict, ctx: DeserMaps) -> 'FuncIR':
        return FuncIR(
            FuncDecl.deserialize(data['decl'], ctx),
            [],
            [],
            data['line'],
            data['traceback_name'],
        )


INVALID_FUNC_DEF: Final = FuncDef("<INVALID_FUNC_DEF>", [], Block([]))


def all_values(args: List[Register], blocks: List[BasicBlock]) -> List[Value]:
    """Return the set of all values that may be initialized in the blocks.

    This omits registers that are only read.
    """
    values: List[Value] = list(args)
    seen_registers = set(args)

    for block in blocks:
        for op in block.ops:
            if not isinstance(op, ControlOp):
                if isinstance(op, (Assign, AssignMulti)):
                    if op.dest not in seen_registers:
Ejemplo n.º 28
0
 def as_block(self, stmts: List[ast35.stmt], lineno: int) -> Block:
     b = None
     if stmts:
         b = Block(self.visit_list(stmts))
         b.set_line(lineno)
     return b
Ejemplo n.º 29
0
 def _add_bool_dunder(self, type_info: TypeInfo) -> None:
     signature = CallableType([], [], [], Instance(self.bool_type_info, []),
                              self.function)
     bool_func = FuncDef('__bool__', [], Block([]))
     bool_func.type = set_callable_name(signature, bool_func)
     type_info.names[bool_func.name] = SymbolTableNode(MDEF, bool_func)
Ejemplo n.º 30
0
def add_method(
    ctx: ClassDefContext,
    name: str,
    args: List[Argument],
    return_type: Type,
    self_type: Optional[Type] = None,
    tvar_def: Optional[TypeVarDef] = None,
    is_classmethod: bool = False,
    is_new: bool = False,
    # is_staticmethod: bool = False,
) -> None:
    """
    Adds a new method to a class.

    This can be dropped if/when https://github.com/python/mypy/issues/7301 is merged
    """
    info = ctx.cls.info

    # First remove any previously generated methods with the same name
    # to avoid clashes and problems in the semantic analyzer.
    if name in info.names:
        sym = info.names[name]
        if sym.plugin_generated and isinstance(sym.node, FuncDef):
            ctx.cls.defs.body.remove(sym.node)

    self_type = self_type or fill_typevars(info)
    if is_classmethod or is_new:
        first = [
            Argument(Var("_cls"), TypeType.make_normalized(self_type), None,
                     ARG_POS)
        ]
    # elif is_staticmethod:
    #     first = []
    else:
        self_type = self_type or fill_typevars(info)
        first = [Argument(Var("self"), self_type, None, ARG_POS)]
    args = first + args
    arg_types, arg_names, arg_kinds = [], [], []
    for arg in args:
        assert arg.type_annotation, "All arguments must be fully typed."
        arg_types.append(arg.type_annotation)
        arg_names.append(get_name(arg.variable))
        arg_kinds.append(arg.kind)

    function_type = ctx.api.named_type("__builtins__.function")
    signature = CallableType(arg_types, arg_kinds, arg_names, return_type,
                             function_type)
    if tvar_def:
        signature.variables = [tvar_def]

    func = FuncDef(name, args, Block([PassStmt()]))
    func.info = info
    func.type = set_callable_name(signature, func)
    func.is_class = is_classmethod
    # func.is_static = is_staticmethod
    func._fullname = get_fullname(info) + "." + name
    func.line = info.line

    # NOTE: we would like the plugin generated node to dominate, but we still
    # need to keep any existing definitions so they get semantically analyzed.
    if name in info.names:
        # Get a nice unique name instead.
        r_name = get_unique_redefinition_name(name, info.names)
        info.names[r_name] = info.names[name]

    if is_classmethod:  # or is_staticmethod:
        func.is_decorated = True
        v = Var(name, func.type)
        v.info = info
        v._fullname = func._fullname
        # if is_classmethod:
        v.is_classmethod = True
        dec = Decorator(func, [NameExpr("classmethod")], v)
        # else:
        #     v.is_staticmethod = True
        #     dec = Decorator(func, [NameExpr('staticmethod')], v)

        dec.line = info.line
        sym = SymbolTableNode(MDEF, dec)
    else:
        sym = SymbolTableNode(MDEF, func)
    sym.plugin_generated = True

    info.names[name] = sym
    info.defn.defs.body.append(func)