Beispiel #1
0
    def find_replacements_in_call(self, call: CallExpr,
                                  keys: List[str]) -> List[Expression]:
        """Find replacement expression for every specifier in str.format() call.

        In case of an error use TempNode(AnyType).
        """
        result = []  # type: List[Expression]
        used = set()  # type: Set[Expression]
        for key in keys:
            if key.isdecimal():
                expr = self.get_expr_by_position(int(key), call)
                if not expr:
                    self.msg.fail('Cannot find replacement for positional'
                                  ' format specifier {}'.format(key),
                                  call,
                                  code=codes.STRING_FORMATTING)
                    expr = TempNode(AnyType(TypeOfAny.from_error))
            else:
                expr = self.get_expr_by_name(key, call)
                if not expr:
                    self.msg.fail('Cannot find replacement for named'
                                  ' format specifier "{}"'.format(key),
                                  call,
                                  code=codes.STRING_FORMATTING)
                    expr = TempNode(AnyType(TypeOfAny.from_error))
            result.append(expr)
            if not isinstance(expr, TempNode):
                used.add(expr)
        # Strictly speaking not using all replacements is not a type error, but most likely
        # a typo in user code, so we show an error like we do for % formatting.
        total_explicit = len(
            [kind for kind in call.arg_kinds if kind in (ARG_POS, ARG_NAMED)])
        if len(used) < total_explicit:
            self.msg.too_many_string_formatting_arguments(call)
        return result
Beispiel #2
0
    def get_expr_by_position(self, pos: int,
                             call: CallExpr) -> Optional[Expression]:
        """Get positional replacement expression from '{0}, {1}'.format(x, y, ...) call.

        If the type is from *args, return TempNode(<item type>). Return None in case of
        an error.
        """
        pos_args = [
            arg for arg, kind in zip(call.args, call.arg_kinds)
            if kind == ARG_POS
        ]
        if pos < len(pos_args):
            return pos_args[pos]
        star_args = [
            arg for arg, kind in zip(call.args, call.arg_kinds)
            if kind == ARG_STAR
        ]
        if not star_args:
            return None

        # Fall back to *args when present in call.
        star_arg = star_args[0]
        varargs_type = get_proper_type(self.chk.type_map[star_arg])
        if (not isinstance(varargs_type, Instance)
                or not varargs_type.type.has_base('typing.Sequence')):
            # Error should be already reported.
            return TempNode(AnyType(TypeOfAny.special_form))
        iter_info = self.chk.named_generic_type(
            'typing.Sequence', [AnyType(TypeOfAny.special_form)]).type
        return TempNode(
            map_instance_to_supertype(varargs_type, iter_info).args[0])
    def apply_field_accessors(self, spec: ConversionSpecifier, repl: Expression,
                              ctx: Context) -> Expression:
        """Transform and validate expr in '{.attr[item]}'.format(expr) into expr.attr['item'].

        If validation fails, return TempNode(AnyType).
        """
        assert spec.key, "Keys must be auto-generated first!"
        if spec.field == spec.key:
            return repl
        assert spec.field

        # This is a bit of a dirty trick, but it looks like this is the simplest way.
        temp_errors = self.msg.clean_copy().errors
        dummy = DUMMY_FIELD_NAME + spec.field[len(spec.key):]
        temp_ast = parse(dummy, fnam='<format>', module=None,
                         options=self.chk.options, errors=temp_errors)  # type: Node
        if temp_errors.is_errors():
            self.msg.fail('Syntax error in format specifier "{}"'.format(spec.field),
                          ctx, code=codes.STRING_FORMATTING)
            return TempNode(AnyType(TypeOfAny.from_error))

        # These asserts are guaranteed by the original regexp.
        assert isinstance(temp_ast, MypyFile)
        temp_ast = temp_ast.defs[0]
        assert isinstance(temp_ast, ExpressionStmt)
        temp_ast = temp_ast.expr
        if not self.validate_and_transform_accessors(temp_ast, repl, spec, ctx=ctx):
            return TempNode(AnyType(TypeOfAny.from_error))

        # Check if there are any other errors (like missing members).
        # TODO: fix column to point to actual start of the format specifier _within_ string.
        temp_ast.line = ctx.line
        temp_ast.column = ctx.column
        self.exprchk.accept(temp_ast)
        return temp_ast
Beispiel #4
0
    def get_expr_by_name(self, key: str,
                         call: CallExpr) -> Optional[Expression]:
        """Get named replacement expression from '{name}'.format(name=...) call.

        If the type is from **kwargs, return TempNode(<item type>). Return None in case of
        an error.
        """
        named_args = [
            arg for arg, kind, name in zip(call.args, call.arg_kinds,
                                           call.arg_names)
            if kind == ARG_NAMED and name == key
        ]
        if named_args:
            return named_args[0]
        star_args_2 = [
            arg for arg, kind in zip(call.args, call.arg_kinds)
            if kind == ARG_STAR2
        ]
        if not star_args_2:
            return None
        star_arg_2 = star_args_2[0]
        kwargs_type = get_proper_type(self.chk.type_map[star_arg_2])
        if (not isinstance(kwargs_type, Instance)
                or not kwargs_type.type.has_base('typing.Mapping')):
            # Error should be already reported.
            return TempNode(AnyType(TypeOfAny.special_form))
        any_type = AnyType(TypeOfAny.special_form)
        mapping_info = self.chk.named_generic_type('typing.Mapping',
                                                   [any_type, any_type]).type
        return TempNode(
            map_instance_to_supertype(kwargs_type, mapping_info).args[1])
Beispiel #5
0
    def check_simple_str_interpolation(self,
                                       specifiers: List[ConversionSpecifier],
                                       replacements: Expression,
                                       expr: FormatStringExpr) -> None:
        """Check % string interpolation with positional specifiers '%s, %d' % ('yes, 42')."""
        checkers = self.build_replacement_checkers(specifiers, replacements,
                                                   expr)
        if checkers is None:
            return

        rhs_type = get_proper_type(self.accept(replacements))
        rep_types: List[Type] = []
        if isinstance(rhs_type, TupleType):
            rep_types = rhs_type.items
        elif isinstance(rhs_type, AnyType):
            return
        elif isinstance(
                rhs_type,
                Instance) and rhs_type.type.fullname == 'builtins.tuple':
            # Assume that an arbitrary-length tuple has the right number of items.
            rep_types = [rhs_type.args[0]] * len(checkers)
        elif isinstance(rhs_type, UnionType):
            for typ in rhs_type.relevant_items():
                temp_node = TempNode(typ)
                temp_node.line = replacements.line
                self.check_simple_str_interpolation(specifiers, temp_node,
                                                    expr)
            return
        else:
            rep_types = [rhs_type]

        if len(checkers) > len(rep_types):
            # Only check the fix-length Tuple type. Other Iterable types would skip.
            if (is_subtype(rhs_type, self.chk.named_type("typing.Iterable"))
                    and not isinstance(rhs_type, TupleType)):
                return
            else:
                self.msg.too_few_string_formatting_arguments(replacements)
        elif len(checkers) < len(rep_types):
            self.msg.too_many_string_formatting_arguments(replacements)
        else:
            if len(checkers) == 1:
                check_node, check_type = checkers[0]
                if isinstance(rhs_type, TupleType) and len(
                        rhs_type.items) == 1:
                    check_type(rhs_type.items[0])
                else:
                    check_node(replacements)
            elif (isinstance(replacements, TupleExpr) and not any(
                    isinstance(item, StarExpr)
                    for item in replacements.items)):
                for checks, rep_node in zip(checkers, replacements.items):
                    check_node, check_type = checks
                    check_node(rep_node)
            else:
                for checks, rep_type in zip(checkers, rep_types):
                    check_node, check_type = checks
                    check_type(rep_type)
Beispiel #6
0
def transform_jsonclass_class(ctx: ClassDefContext) -> None:
    cls = ctx.cls
    for stmt in cls.defs.body:
        if not isinstance(stmt, AssignmentStmt):
            continue
        lhs = stmt.lvalues[0]
        if not isinstance(lhs, NameExpr):
            continue
        if not stmt.new_syntax:
            ctx.api.fail('Untyped fields disallowed in JSON Class body.', stmt, code=ERROR_UNTYPED)
            continue
        sym = cls.info.names.get(lhs.name)
        if sym is None:
            # This name is likely blocked by a star import. We don't need to defer because
            # defer() is already called by mark_incomplete().
            continue
        node = sym.node
        if isinstance(node, PlaceholderNode):
            # This node is not ready yet.
            return None
        assert isinstance(node, Var)
        if node.is_classvar:
            continue
        # node_type = get_proper_type(node.type)
        if is_json_class_types_expr(stmt.rvalue):
            stmt.rvalue = TempNode(AnyType(TypeOfAny.explicit), False)
Beispiel #7
0
 def visit_Assign(self, n: ast35.Assign) -> AssignmentStmt:
     typ = None
     if hasattr(n,
                'annotation') and n.annotation is not None:  # type: ignore
         new_syntax = True
     else:
         new_syntax = False
     if new_syntax and self.pyversion < (3, 6):
         raise TypeCommentParseError(
             'Variable annotation syntax is only '
             'suppoted in Python 3.6, use type '
             'comment instead', n.lineno, n.col_offset)
     # typed_ast prevents having both type_comment and annotation.
     if n.type_comment is not None:
         typ = parse_type_comment(n.type_comment, n.lineno)
     elif new_syntax:
         typ = TypeConverter(line=n.lineno).visit(
             n.annotation)  # type: ignore
         typ.column = n.annotation.col_offset
     if n.value is None:  # always allow 'x: int'
         rvalue = TempNode(AnyType())  # type: Expression
     else:
         rvalue = self.visit(n.value)
     lvalues = self.translate_expr_list(n.targets)
     return AssignmentStmt(lvalues, rvalue, type=typ, new_syntax=new_syntax)
Beispiel #8
0
 def visit_AnnAssign(self, n: ast3.AnnAssign) -> AssignmentStmt:
     if n.value is None:  # always allow 'x: int'
         rvalue = TempNode(AnyType())  # type: Expression
     else:
         rvalue = self.visit(n.value)
     typ = TypeConverter(self.errors, line=n.lineno).visit(n.annotation)
     typ.column = n.annotation.col_offset
     return AssignmentStmt([self.visit(n.target)], rvalue, type=typ, new_syntax=True)
Beispiel #9
0
def add_additional_orm_attributes(
    cls: ClassDef,
    api: SemanticAnalyzerPluginInterface,
    attributes: List[util.SQLAlchemyAttribute],
) -> None:
    """Apply __init__, __table__ and other attributes to the mapped class."""

    info = util.info_for_cls(cls, api)

    if info is None:
        return

    is_base = util.get_is_base(info)

    if "__init__" not in info.names and not is_base:
        mapped_attr_names = {attr.name: attr.type for attr in attributes}

        for base in info.mro[1:-1]:
            if "sqlalchemy" not in info.metadata:
                continue

            base_cls_attributes = util.get_mapped_attributes(base, api)
            if base_cls_attributes is None:
                continue

            for attr in base_cls_attributes:
                mapped_attr_names.setdefault(attr.name, attr.type)

        arguments = []
        for name, typ in mapped_attr_names.items():
            if typ is None:
                typ = AnyType(TypeOfAny.special_form)
            arguments.append(
                Argument(
                    variable=Var(name, typ),
                    type_annotation=typ,
                    initializer=TempNode(typ),
                    kind=ARG_NAMED_OPT,
                )
            )

        add_method_to_class(api, cls, "__init__", arguments, NoneTyp())

    if "__table__" not in info.names and util.get_has_table(info):
        _apply_placeholder_attr_to_class(
            api, cls, "sqlalchemy.sql.schema.Table", "__table__"
        )
    if not is_base:
        _apply_placeholder_attr_to_class(
            api, cls, "sqlalchemy.orm.mapper.Mapper", "__mapper__"
        )
Beispiel #10
0
 def visit_AnnAssign(self, n: ast3.AnnAssign) -> AssignmentStmt:
     if n.value is None:  # always allow 'x: int'
         rvalue = TempNode(AnyType(TypeOfAny.special_form),
                           no_rhs=True)  # type: Expression
     else:
         rvalue = self.visit(n.value)
     typ = TypeConverter(self.errors, line=n.lineno).visit(n.annotation)
     assert typ is not None
     typ.column = n.annotation.col_offset
     s = AssignmentStmt([self.visit(n.target)],
                        rvalue,
                        type=typ,
                        new_syntax=True)
     return self.set_line(s, n)
Beispiel #11
0
def _add_additional_orm_attributes(
    cls: ClassDef,
    api: SemanticAnalyzerPluginInterface,
    cls_metadata: util.DeclClassApplied,
) -> None:
    """Apply __init__, __table__ and other attributes to the mapped class."""

    info = util._info_for_cls(cls, api)
    if "__init__" not in info.names and cls_metadata.is_mapped:
        mapped_attr_names = {n: t for n, t in cls_metadata.mapped_attr_names}

        for mapped_base in cls_metadata.mapped_mro:
            base_cls_metadata = util.DeclClassApplied.deserialize(
                mapped_base.type.metadata["_sa_decl_class_applied"], api
            )
            for n, t in base_cls_metadata.mapped_attr_names:
                mapped_attr_names.setdefault(n, t)

        arguments = []
        for name, typ in mapped_attr_names.items():
            if typ is None:
                typ = AnyType(TypeOfAny.special_form)
            arguments.append(
                Argument(
                    variable=Var(name, typ),
                    type_annotation=typ,
                    initializer=TempNode(typ),
                    kind=ARG_NAMED_OPT,
                )
            )
        add_method_to_class(api, cls, "__init__", arguments, NoneTyp())

    if "__table__" not in info.names and cls_metadata.has_table:
        _apply_placeholder_attr_to_class(
            api, cls, "sqlalchemy.sql.schema.Table", "__table__"
        )
    if cls_metadata.is_mapped:
        _apply_placeholder_attr_to_class(
            api, cls, "sqlalchemy.orm.mapper.Mapper", "__mapper__"
        )
Beispiel #12
0
def _scan_declarative_decorator_stmt(
    cls: ClassDef,
    api: SemanticAnalyzerPluginInterface,
    stmt: Decorator,
    attributes: List[util.SQLAlchemyAttribute],
) -> None:
    """Extract mapping information from a @declared_attr in a declarative
    class.

    E.g.::

        @reg.mapped
        class MyClass:
            # ...

            @declared_attr
            def updated_at(cls) -> Column[DateTime]:
                return Column(DateTime)

    Will resolve in mypy as::

        @reg.mapped
        class MyClass:
            # ...

            updated_at: Mapped[Optional[datetime.datetime]]

    """
    for dec in stmt.decorators:
        if (isinstance(dec, (NameExpr, MemberExpr, SymbolNode))
                and names.type_id_for_named_node(dec) is names.DECLARED_ATTR):
            break
    else:
        return

    dec_index = cls.defs.body.index(stmt)

    left_hand_explicit_type: Optional[ProperType] = None

    if util.name_is_dunder(stmt.name):
        # for dunder names like __table_args__, __tablename__,
        # __mapper_args__ etc., rewrite these as simple assignment
        # statements; otherwise mypy doesn't like if the decorated
        # function has an annotation like ``cls: Type[Foo]`` because
        # it isn't @classmethod
        any_ = AnyType(TypeOfAny.special_form)
        left_node = NameExpr(stmt.var.name)
        left_node.node = stmt.var
        new_stmt = AssignmentStmt([left_node], TempNode(any_))
        new_stmt.type = left_node.node.type
        cls.defs.body[dec_index] = new_stmt
        return
    elif isinstance(stmt.func.type, CallableType):
        func_type = stmt.func.type.ret_type
        if isinstance(func_type, UnboundType):
            type_id = names.type_id_for_unbound_type(func_type, cls, api)
        else:
            # this does not seem to occur unless the type argument is
            # incorrect
            return

        if (type_id in {
                names.MAPPED,
                names.RELATIONSHIP,
                names.COMPOSITE_PROPERTY,
                names.MAPPER_PROPERTY,
                names.SYNONYM_PROPERTY,
                names.COLUMN_PROPERTY,
        } and func_type.args):
            left_hand_explicit_type = get_proper_type(func_type.args[0])
        elif type_id is names.COLUMN and func_type.args:
            typeengine_arg = func_type.args[0]
            if isinstance(typeengine_arg, UnboundType):
                sym = api.lookup_qualified(typeengine_arg.name, typeengine_arg)
                if sym is not None and isinstance(sym.node, TypeInfo):
                    if names.has_base_type_id(sym.node, names.TYPEENGINE):
                        left_hand_explicit_type = UnionType([
                            infer.extract_python_type_from_typeengine(
                                api, sym.node, []),
                            NoneType(),
                        ])
                    else:
                        util.fail(
                            api,
                            "Column type should be a TypeEngine "
                            "subclass not '{}'".format(sym.node.fullname),
                            func_type,
                        )

    if left_hand_explicit_type is None:
        # no type on the decorated function.  our option here is to
        # dig into the function body and get the return type, but they
        # should just have an annotation.
        msg = ("Can't infer type from @declared_attr on function '{}';  "
               "please specify a return type from this function that is "
               "one of: Mapped[<python type>], relationship[<target class>], "
               "Column[<TypeEngine>], MapperProperty[<python type>]")
        util.fail(api, msg.format(stmt.var.name), stmt)

        left_hand_explicit_type = AnyType(TypeOfAny.special_form)

    left_node = NameExpr(stmt.var.name)
    left_node.node = stmt.var

    # totally feeling around in the dark here as I don't totally understand
    # the significance of UnboundType.  It seems to be something that is
    # not going to do what's expected when it is applied as the type of
    # an AssignmentStatement.  So do a feeling-around-in-the-dark version
    # of converting it to the regular Instance/TypeInfo/UnionType structures
    # we see everywhere else.
    if isinstance(left_hand_explicit_type, UnboundType):
        left_hand_explicit_type = get_proper_type(
            util.unbound_to_instance(api, left_hand_explicit_type))

    left_node.node.type = api.named_type(names.NAMED_TYPE_SQLA_MAPPED,
                                         [left_hand_explicit_type])

    # this will ignore the rvalue entirely
    # rvalue = TempNode(AnyType(TypeOfAny.special_form))

    # rewrite the node as:
    # <attr> : Mapped[<typ>] =
    # _sa_Mapped._empty_constructor(lambda: <function body>)
    # the function body is maintained so it gets type checked internally
    rvalue = util.expr_to_mapped_constructor(
        LambdaExpr(stmt.func.arguments, stmt.func.body))

    new_stmt = AssignmentStmt([left_node], rvalue)
    new_stmt.type = left_node.node.type

    attributes.append(
        util.SQLAlchemyAttribute(
            name=left_node.name,
            line=stmt.line,
            column=stmt.column,
            typ=left_hand_explicit_type,
            info=cls.info,
        ))
    cls.defs.body[dec_index] = new_stmt
Beispiel #13
0
def addoption_class_callback(context: ClassDefContext) -> None:
    for stmt in context.cls.defs.body:
        if isinstance(stmt, AssignmentStmt) and stmt.type is not None:
            stmt.rvalue = TempNode(stmt.type, context=stmt.rvalue)
Beispiel #14
0
 def expression(self, context: Context) -> TempNode:
     """Hack to pass unexisting `Expression` to typechecker."""
     return TempNode(self.type, context=context)
Beispiel #15
0
def analyze_descriptor_access(descriptor_type: Type,
                              mx: MemberContext) -> Type:
    """Type check descriptor access.

    Arguments:
        descriptor_type: The type of the descriptor attribute being accessed
            (the type of ``f`` in ``a.f`` when ``f`` is a descriptor).
        mx: The current member access context.
    Return:
        The return type of the appropriate ``__get__`` overload for the descriptor.
    """
    instance_type = get_proper_type(mx.original_type)
    descriptor_type = get_proper_type(descriptor_type)

    if isinstance(descriptor_type, UnionType):
        # Map the access over union types
        return make_simplified_union([
            analyze_descriptor_access(typ, mx) for typ in descriptor_type.items
        ])
    elif not isinstance(descriptor_type, Instance):
        return descriptor_type

    if not descriptor_type.type.has_readable_member('__get__'):
        return descriptor_type

    dunder_get = descriptor_type.type.get_method('__get__')
    if dunder_get is None:
        mx.msg.fail(
            message_registry.DESCRIPTOR_GET_NOT_CALLABLE.format(
                descriptor_type), mx.context)
        return AnyType(TypeOfAny.from_error)

    bound_method = analyze_decorator_or_funcbase_access(
        defn=dunder_get,
        itype=descriptor_type,
        info=descriptor_type.type,
        self_type=descriptor_type,
        name='__set__',
        mx=mx)

    typ = map_instance_to_supertype(descriptor_type, dunder_get.info)
    dunder_get_type = expand_type_by_instance(bound_method, typ)

    if isinstance(instance_type, FunctionLike) and instance_type.is_type_obj():
        owner_type = instance_type.items[0].ret_type
        instance_type = NoneType()
    elif isinstance(instance_type, TypeType):
        owner_type = instance_type.item
        instance_type = NoneType()
    else:
        owner_type = instance_type

    callable_name = mx.chk.expr_checker.method_fullname(
        descriptor_type, "__get__")
    dunder_get_type = mx.chk.expr_checker.transform_callee_type(
        callable_name,
        dunder_get_type,
        [
            TempNode(instance_type, context=mx.context),
            TempNode(TypeType.make_normalized(owner_type), context=mx.context)
        ],
        [ARG_POS, ARG_POS],
        mx.context,
        object_type=descriptor_type,
    )

    _, inferred_dunder_get_type = mx.chk.expr_checker.check_call(
        dunder_get_type, [
            TempNode(instance_type, context=mx.context),
            TempNode(TypeType.make_normalized(owner_type), context=mx.context)
        ], [ARG_POS, ARG_POS],
        mx.context,
        object_type=descriptor_type,
        callable_name=callable_name)

    inferred_dunder_get_type = get_proper_type(inferred_dunder_get_type)
    if isinstance(inferred_dunder_get_type, AnyType):
        # check_call failed, and will have reported an error
        return inferred_dunder_get_type

    if not isinstance(inferred_dunder_get_type, CallableType):
        mx.msg.fail(
            message_registry.DESCRIPTOR_GET_NOT_CALLABLE.format(
                descriptor_type), mx.context)
        return AnyType(TypeOfAny.from_error)

    return inferred_dunder_get_type.ret_type
Beispiel #16
0
 def visit_temp_node(self, node: TempNode) -> Node:
     return TempNode(self.type(node.type))
Beispiel #17
0
def analyze_descriptor_access(instance_type: Type, descriptor_type: Type,
                              builtin_type: Callable[[str], Instance],
                              msg: MessageBuilder, context: Context, *,
                              chk: 'mypy.checker.TypeChecker') -> Type:
    """Type check descriptor access.

    Arguments:
        instance_type: The type of the instance on which the descriptor
            attribute is being accessed (the type of ``a`` in ``a.f`` when
            ``f`` is a descriptor).
        descriptor_type: The type of the descriptor attribute being accessed
            (the type of ``f`` in ``a.f`` when ``f`` is a descriptor).
        context: The node defining the context of this inference.
    Return:
        The return type of the appropriate ``__get__`` overload for the descriptor.
    """
    if isinstance(descriptor_type, UnionType):
        # Map the access over union types
        return UnionType.make_simplified_union([
            analyze_descriptor_access(instance_type,
                                      typ,
                                      builtin_type,
                                      msg,
                                      context,
                                      chk=chk) for typ in descriptor_type.items
        ])
    elif not isinstance(descriptor_type, Instance):
        return descriptor_type

    if not descriptor_type.type.has_readable_member('__get__'):
        return descriptor_type

    dunder_get = descriptor_type.type.get_method('__get__')

    if dunder_get is None:
        msg.fail(
            message_registry.DESCRIPTOR_GET_NOT_CALLABLE.format(
                descriptor_type), context)
        return AnyType(TypeOfAny.from_error)

    function = function_type(dunder_get, builtin_type('builtins.function'))
    bound_method = bind_self(function, descriptor_type)
    typ = map_instance_to_supertype(descriptor_type, dunder_get.info)
    dunder_get_type = expand_type_by_instance(bound_method, typ)

    if isinstance(instance_type, FunctionLike) and instance_type.is_type_obj():
        owner_type = instance_type.items()[0].ret_type
        instance_type = NoneTyp()
    elif isinstance(instance_type, TypeType):
        owner_type = instance_type.item
        instance_type = NoneTyp()
    else:
        owner_type = instance_type

    _, inferred_dunder_get_type = chk.expr_checker.check_call(
        dunder_get_type, [
            TempNode(instance_type),
            TempNode(TypeType.make_normalized(owner_type))
        ], [ARG_POS, ARG_POS], context)

    if isinstance(inferred_dunder_get_type, AnyType):
        # check_call failed, and will have reported an error
        return inferred_dunder_get_type

    if not isinstance(inferred_dunder_get_type, CallableType):
        msg.fail(
            message_registry.DESCRIPTOR_GET_NOT_CALLABLE.format(
                descriptor_type), context)
        return AnyType(TypeOfAny.from_error)

    return inferred_dunder_get_type.ret_type
Beispiel #18
0
 def temp_node(self, t, context=None):
     """Create a temporary node with the given, fixed type."""
     temp = TempNode(t)
     if context:
         temp.set_line(context.get_line())
     return temp