Пример #1
0
def infer_import_from(self, context=None, asname=True):
    """infer a ImportFrom node: return the imported module/object"""
    name = context.lookupname
    if name is None:
        raise exceptions.InferenceError(node=self, context=context)
    if asname:
        name = self.real_name(name)

    try:
        module = self.do_import_module()
    except exceptions.AstroidBuildingError as exc:
        raise exceptions.InferenceError(
            node=self,
            context=context,
        ) from exc

    try:
        context = contextmod.copy_context(context)
        context.lookupname = name
        stmts = module.getattr(name, ignore_locals=module is self.root())
        return bases._infer_stmts(stmts, context)
    except exceptions.AttributeInferenceError as error:
        raise exceptions.InferenceError(
            error.message,
            target=self,
            attribute=name,
            context=context,
        ) from error
Пример #2
0
def query_call(self: nodes.Call, context=None):
    """query a Call node by trying to guess what the function returns"""
    callcontext = contextmod.copy_context(context)
    callcontext.callcontext = contextmod.CallContext(args=self.args,
                                                     keywords=self.keywords)
    callcontext.boundnode = None
    if context is not None:
        # extra context saved the args, what's for?
        callcontext.extra_context = _populate_context_lookup(
            self, context.clone())

    for callee in self.func.query(context):
        if callee is util.Uninferable:
            yield callee
            continue
        if callee is util.Unqueryable:
            if not isinstance(self.keywords, None):
                # not implemented
                print(kv)
                assert False
            return self.args

        try:
            if hasattr(callee, "query_call_result"):
                # no filed sensitive here
                yield from callee.query_call_result(caller=self,
                                                    context=callcontext)
        except exceptions.InferenceError:
            continue
    return dict(node=self, context=context)
Пример #3
0
            def infer_call_result(self, caller, context=None):
                if len(caller.args) != 2:
                    raise exceptions.InferenceError(
                        "Invalid arguments for descriptor binding",
                        target=self, context=context)

                context = contextmod.copy_context(context)
                cls = next(caller.args[0].infer(context=context))

                if cls is astroid.Uninferable:
                    raise exceptions.InferenceError(
                        "Invalid class inferred",
                        target=self, context=context)

                # For some reason func is a Node that the below
                # code is not expecting
                if isinstance(func, bases.BoundMethod):
                    yield func
                    return

                # Rebuild the original value, but with the parent set as the
                # class where it will be bound.
                new_func = func.__class__(name=func.name, doc=func.doc,
                                          lineno=func.lineno, col_offset=func.col_offset,
                                          parent=cls)
                # pylint: disable=no-member
                new_func.postinit(func.args, func.body,
                                  func.decorators, func.returns)

                # Build a proper bound method that points to our newly built function.
                proxy = bases.UnboundMethod(new_func)
                yield bases.BoundMethod(proxy=proxy, bound=cls)
Пример #4
0
            def infer_call_result(self, caller, context=None):
                if len(caller.args) != 2:
                    raise exceptions.InferenceError(
                        "Invalid arguments for descriptor binding",
                        target=self,
                        context=context)

                context = contextmod.copy_context(context)
                cls = next(caller.args[0].infer(context=context))

                if cls is astroid.Uninferable:
                    raise exceptions.InferenceError("Invalid class inferred",
                                                    target=self,
                                                    context=context)

                # For some reason func is a Node that the below
                # code is not expecting
                if isinstance(func, bases.BoundMethod):
                    yield func
                    return

                # Rebuild the original value, but with the parent set as the
                # class where it will be bound.
                new_func = func.__class__(name=func.name,
                                          doc=func.doc,
                                          lineno=func.lineno,
                                          col_offset=func.col_offset,
                                          parent=cls)
                # pylint: disable=no-member
                new_func.postinit(func.args, func.body, func.decorators,
                                  func.returns)

                # Build a proper bound method that points to our newly built function.
                proxy = bases.UnboundMethod(new_func)
                yield bases.BoundMethod(proxy=proxy, bound=cls)
Пример #5
0
def arguments_assigned_stmts(self, node=None, context=None, asspath=None):
    if context.callcontext:
        # reset call context/name
        callcontext = context.callcontext
        context = contextmod.copy_context(context)
        context.callcontext = None
        args = arguments.CallSite(callcontext)
        return args.infer_argument(self.parent, node.name, context)
    return _arguments_infer_argname(self, node.name, context)
Пример #6
0
def arguments_assigned_stmts(self, node=None, context=None, asspath=None):
    if context.callcontext:
        # reset call context/name
        callcontext = context.callcontext
        context = contextmod.copy_context(context)
        context.callcontext = None
        args = arguments.CallSite(callcontext)
        return args.infer_argument(self.parent, node.name, context)
    return _arguments_infer_argname(self, node.name, context)
Пример #7
0
def _arguments_infer_argname(self, name, context):
    # arguments information may be missing, in which case we can't do anything
    # more
    if not (self.arguments or self.vararg or self.kwarg):
        yield util.Uninferable
        return

    functype = self.parent.type
    # first argument of instance/class method
    if (
        self.arguments
        and getattr(self.arguments[0], "name", None) == name
        and functype != "staticmethod"
    ):
        cls = self.parent.parent.scope()
        is_metaclass = isinstance(cls, nodes.ClassDef) and cls.type == "metaclass"
        # If this is a metaclass, then the first argument will always
        # be the class, not an instance.
        if context.boundnode and isinstance(context.boundnode, bases.Instance):
            cls = context.boundnode._proxied
        if is_metaclass or functype == "classmethod":
            yield cls
            return
        if functype == "method":
            yield cls.instantiate_class()
            return

    if context and context.callcontext:
        callee = context.callcontext.callee
        while hasattr(callee, "_proxied"):
            callee = callee._proxied
        if getattr(callee, "name", None) == self.parent.name:
            call_site = arguments.CallSite(context.callcontext, context.extra_context)
            yield from call_site.infer_argument(self.parent, name, context)
            return

    if name == self.vararg:
        vararg = nodes.const_factory(())
        vararg.parent = self
        if not self.arguments and self.parent.name == "__init__":
            cls = self.parent.parent.scope()
            vararg.elts = [cls.instantiate_class()]
        yield vararg
        return
    if name == self.kwarg:
        kwarg = nodes.const_factory({})
        kwarg.parent = self
        yield kwarg
        return
    # if there is a default value, yield it. And then yield Uninferable to reflect
    # we can't guess given argument value
    try:
        context = copy_context(context)
        yield from self.default_value(name).infer(context)
        yield util.Uninferable
    except NoDefault:
        yield util.Uninferable
Пример #8
0
def _infer_unaryop(self, context=None):
    """Infer what an UnaryOp should return when evaluated."""
    for operand in self.operand.infer(context):
        try:
            yield operand.infer_unary_op(self.op)
        except TypeError as exc:
            # The operand doesn't support this operation.
            yield util.BadUnaryOperationMessage(operand, self.op, exc)
        except AttributeError as exc:
            meth = protocols.UNARY_OP_METHOD[self.op]
            if meth is None:
                # `not node`. Determine node's boolean
                # value and negate its result, unless it is
                # Uninferable, which will be returned as is.
                bool_value = operand.bool_value()
                if bool_value is not util.Uninferable:
                    yield nodes.const_factory(not bool_value)
                else:
                    yield util.Uninferable
            else:
                if not isinstance(operand, (bases.Instance, nodes.ClassDef)):
                    # The operation was used on something which
                    # doesn't support it.
                    yield util.BadUnaryOperationMessage(operand, self.op, exc)
                    continue

                try:
                    try:
                        methods = dunder_lookup.lookup(operand, meth)
                    except AttributeInferenceError:
                        yield util.BadUnaryOperationMessage(
                            operand, self.op, exc)
                        continue

                    meth = methods[0]
                    inferred = next(meth.infer(context=context), None)
                    if inferred is util.Uninferable or not inferred.callable():
                        continue

                    context = copy_context(context)
                    context.boundnode = operand
                    context.callcontext = CallContext(args=[], callee=inferred)

                    call_results = inferred.infer_call_result(self,
                                                              context=context)
                    result = next(call_results, None)
                    if result is None:
                        # Failed to infer, return the same type.
                        yield operand
                    else:
                        yield result
                except AttributeInferenceError as exc:
                    # The unary operation special method was not found.
                    yield util.BadUnaryOperationMessage(operand, self.op, exc)
                except InferenceError:
                    yield util.Uninferable
Пример #9
0
def arguments_query_assigned_stmts(self, node=None, context=None, assign_path=None):
    if context.callcontext:
        # reset call context/name
        callcontext = context.callcontext
        context = contextmod.copy_context(context)
        context.callcontext = None
        args = arguments.CallSite(callcontext, context=context)
        return args.query_argument(self.parent, node.name, context)
    # no call context means that we get to the end point
    # print("end point here!!")
    node.query_end = True
    return [node]
Пример #10
0
def _infer_unaryop(self, context=None):
    """Infer what an UnaryOp should return when evaluated."""
    for operand in self.operand.infer(context):
        try:
            yield operand.infer_unary_op(self.op)
        except TypeError as exc:
            # The operand doesn't support this operation.
            yield util.BadUnaryOperationMessage(operand, self.op, exc)
        except AttributeError as exc:
            meth = protocols.UNARY_OP_METHOD[self.op]
            if meth is None:
                # `not node`. Determine node's boolean
                # value and negate its result, unless it is
                # Uninferable, which will be returned as is.
                bool_value = operand.bool_value()
                if bool_value is not util.Uninferable:
                    yield nodes.const_factory(not bool_value)
                else:
                    yield util.Uninferable
            else:
                if not isinstance(operand, (bases.Instance, nodes.ClassDef)):
                    # The operation was used on something which
                    # doesn't support it.
                    yield util.BadUnaryOperationMessage(operand, self.op, exc)
                    continue

                try:
                    try:
                        methods = dunder_lookup.lookup(operand, meth)
                    except exceptions.AttributeInferenceError:
                        yield util.BadUnaryOperationMessage(operand, self.op, exc)
                        continue

                    meth = methods[0]
                    inferred = next(meth.infer(context=context))
                    if inferred is util.Uninferable or not inferred.callable():
                        continue

                    context = contextmod.copy_context(context)
                    context.callcontext = contextmod.CallContext(args=[operand])
                    call_results = inferred.infer_call_result(self, context=context)
                    result = next(call_results, None)
                    if result is None:
                        # Failed to infer, return the same type.
                        yield operand
                    else:
                        yield result
                except exceptions.AttributeInferenceError as exc:
                    # The unary operation special method was not found.
                    yield util.BadUnaryOperationMessage(operand, self.op, exc)
                except exceptions.InferenceError:
                    yield util.Uninferable
Пример #11
0
def _infer_binop(self, context):
    """Binary operation inference logic."""
    left = self.left
    right = self.right

    # we use two separate contexts for evaluating lhs and rhs because
    # 1. evaluating lhs may leave some undesired entries in context.path
    #    which may not let us infer right value of rhs
    context = context or contextmod.InferenceContext()
    lhs_context = contextmod.copy_context(context)
    rhs_context = contextmod.copy_context(context)
    lhs_iter = left.infer(context=lhs_context)
    rhs_iter = right.infer(context=rhs_context)
    for lhs, rhs in itertools.product(lhs_iter, rhs_iter):
        if any(value is util.Uninferable for value in (rhs, lhs)):
            # Don't know how to process this.
            yield util.Uninferable
            return

        try:
            yield from _infer_binary_operation(lhs, rhs, self, context, _get_binop_flow)
        except exceptions._NonDeducibleTypeHierarchy:
            yield util.Uninferable
Пример #12
0
def infer_import_from(self, context=None, asname=True):
    """infer a ImportFrom node: return the imported module/object"""
    name = context.lookupname
    if name is None:
        raise exceptions.InferenceError()
    if asname:
        name = self.real_name(name)
    module = self.do_import_module()
    try:
        context = contextmod.copy_context(context)
        context.lookupname = name
        stmts = module.getattr(name, ignore_locals=module is self.root())
        return bases._infer_stmts(stmts, context)
    except exceptions.NotFoundError:
        raise exceptions.InferenceError(name)
Пример #13
0
def arguments_assigned_stmts(self, node=None, context=None, assign_path=None):
    if context.callcontext:
        callee = context.callcontext.callee
        while hasattr(callee, "_proxied"):
            callee = callee._proxied
    else:
        callee = None
    if (context.callcontext and node
            and getattr(callee, "name", None) == node.frame().name):
        # reset call context/name
        callcontext = context.callcontext
        context = copy_context(context)
        context.callcontext = None
        args = arguments.CallSite(callcontext, context=context)
        return args.infer_argument(self.parent, node.name, context)
    return _arguments_infer_argname(self, node.name, context)
Пример #14
0
def _arguments_infer_argname(self, name, context):
    # arguments information may be missing, in which case we can't do anything
    # more
    if not (self.args or self.vararg or self.kwarg):
        yield util.Uninferable
        return
    # first argument of instance/class method
    if self.args and getattr(self.args[0], 'name', None) == name:
        functype = self.parent.type
        cls = self.parent.parent.scope()
        is_metaclass = isinstance(cls,
                                  nodes.ClassDef) and cls.type == 'metaclass'
        # If this is a metaclass, then the first argument will always
        # be the class, not an instance.
        if is_metaclass or functype == 'classmethod':
            yield cls
            return
        if functype == 'method':
            yield bases.Instance(self.parent.parent.frame())
            return

    if context and context.callcontext:
        call_site = arguments.CallSite(context.callcontext)
        for value in call_site.infer_argument(self.parent, name, context):
            yield value
        return

    # TODO: just provide the type here, no need to have an empty Dict.
    if name == self.vararg:
        vararg = nodes.const_factory(())
        vararg.parent = self
        yield vararg
        return
    if name == self.kwarg:
        kwarg = nodes.const_factory({})
        kwarg.parent = self
        yield kwarg
        return
    # if there is a default value, yield it. And then yield Uninferable to reflect
    # we can't guess given argument value
    try:
        context = contextmod.copy_context(context)
        for inferred in self.default_value(name).infer(context):
            yield inferred
        yield util.Uninferable
    except exceptions.NoDefault:
        yield util.Uninferable
Пример #15
0
def infer_name(self, context=None):
    """infer a Name: use name lookup rules"""
    frame, stmts = self.lookup(self.name)
    if not stmts:
        # Try to see if the name is enclosed in a nested function
        # and use the higher (first function) scope for searching.
        parent_function = _higher_function_scope(self.scope())
        if parent_function:
            _, stmts = parent_function.lookup(self.name)

        if not stmts:
            raise exceptions.NameInferenceError(name=self.name,
                                                scope=self.scope(),
                                                context=context)
    context = contextmod.copy_context(context)
    context.lookupname = self.name
    return bases._infer_stmts(stmts, context, frame)
Пример #16
0
def _arguments_infer_argname(self, name, context):
    # arguments information may be missing, in which case we can't do anything
    # more
    if not (self.args or self.vararg or self.kwarg):
        yield util.Uninferable
        return
    # first argument of instance/class method
    if self.args and getattr(self.args[0], 'name', None) == name:
        functype = self.parent.type
        cls = self.parent.parent.scope()
        is_metaclass = isinstance(cls, nodes.ClassDef) and cls.type == 'metaclass'
        # If this is a metaclass, then the first argument will always
        # be the class, not an instance.
        if is_metaclass or functype == 'classmethod':
            yield cls
            return
        if functype == 'method':
            yield bases.Instance(self.parent.parent.frame())
            return

    if context and context.callcontext:
        call_site = arguments.CallSite(context.callcontext)
        for value in call_site.infer_argument(self.parent, name, context):
            yield value
        return

    # TODO: just provide the type here, no need to have an empty Dict.
    if name == self.vararg:
        vararg = nodes.const_factory(())
        vararg.parent = self
        yield vararg
        return
    if name == self.kwarg:
        kwarg = nodes.const_factory({})
        kwarg.parent = self
        yield kwarg
        return
    # if there is a default value, yield it. And then yield Uninferable to reflect
    # we can't guess given argument value
    try:
        context = contextmod.copy_context(context)
        for inferred in self.default_value(name).infer(context):
            yield inferred
        yield util.Uninferable
    except exceptions.NoDefault:
        yield util.Uninferable
Пример #17
0
def infer_call(self, context=None):
    """infer a Call node by trying to guess what the function returns"""
    callcontext = contextmod.copy_context(context)
    callcontext.callcontext = contextmod.CallContext(
        args=self.args, keywords=self.keywords
    )
    callcontext.boundnode = None
    if context is not None:
        callcontext.extra_context = _populate_context_lookup(self, context.clone())

    for callee in self.func.infer(context):
        if callee is util.Uninferable:
            yield callee
            continue
        try:
            if hasattr(callee, "infer_call_result"):
                yield from callee.infer_call_result(caller=self, context=callcontext)
        except exceptions.InferenceError:
            continue
    return dict(node=self, context=context)
Пример #18
0
            def infer_call_result(self, caller, context=None):
                if len(caller.args) != 2:
                    raise exceptions.InferenceError(
                        "Invalid arguments for descriptor binding",
                        target=self, context=context)

                context = contextmod.copy_context(context)
                cls = next(caller.args[0].infer(context=context))

                # Rebuild the original value, but with the parent set as the
                # class where it will be bound.
                new_func = func.__class__(name=func.name, doc=func.doc,
                                          lineno=func.lineno, col_offset=func.col_offset,
                                          parent=cls)
                new_func.postinit(func.args, func.body,
                                  func.decorators, func.returns)

                # Build a proper bound method that points to our newly built function.
                proxy = bases.UnboundMethod(new_func)
                yield bases.BoundMethod(proxy=proxy, bound=cls)
Пример #19
0
def infer_name(
    self: nodes.Name | nodes.AssignName,
    context: InferenceContext | None = None,
    **kwargs: Any,
) -> Generator[InferenceResult, None, None]:
    """infer a Name: use name lookup rules"""
    frame, stmts = self.lookup(self.name)
    if not stmts:
        # Try to see if the name is enclosed in a nested function
        # and use the higher (first function) scope for searching.
        parent_function = _higher_function_scope(self.scope())
        if parent_function:
            _, stmts = parent_function.lookup(self.name)

        if not stmts:
            raise NameInferenceError(name=self.name,
                                     scope=self.scope(),
                                     context=context)
    context = copy_context(context)
    context.lookupname = self.name
    return bases._infer_stmts(stmts, context, frame)
Пример #20
0
def arguments_assigned_stmts(
    self: nodes.Arguments,
    node: node_classes.AssignedStmtsPossibleNode = None,
    context: Optional[InferenceContext] = None,
    assign_path: Optional[List[int]] = None,
) -> Any:
    if context.callcontext:
        callee = context.callcontext.callee
        while hasattr(callee, "_proxied"):
            callee = callee._proxied
    else:
        callee = None
    if (context.callcontext and node
            and getattr(callee, "name", None) == node.frame(future=True).name):
        # reset call context/name
        callcontext = context.callcontext
        context = copy_context(context)
        context.callcontext = None
        args = arguments.CallSite(callcontext, context=context)
        return args.infer_argument(self.parent, node.name, context)
    return _arguments_infer_argname(self, node.name, context)
Пример #21
0
def infer_import_from(self, context=None, asname=True):
    """infer a ImportFrom node: return the imported module/object"""
    name = context.lookupname
    if name is None:
        raise exceptions.InferenceError(node=self, context=context)
    if asname:
        name = self.real_name(name)

    try:
        module = self.do_import_module()
    except exceptions.AstroidBuildingError as exc:
        raise exceptions.InferenceError(node=self, context=context) from exc

    try:
        context = contextmod.copy_context(context)
        context.lookupname = name
        stmts = module.getattr(name, ignore_locals=module is self.root())
        return bases._infer_stmts(stmts, context)
    except exceptions.AttributeInferenceError as error:
        raise exceptions.InferenceError(
            error.message, target=self, attribute=name, context=context
        ) from error
Пример #22
0
def query_call(self: nodes.Call, context=None):
    """query a Call node by trying to guess what the function returns"""
    callcontext = contextmod.copy_context(context)
    callcontext.callcontext = contextmod.CallContext(args=self.args,
                                                     keywords=self.keywords)
    callcontext.boundnode = None
    if context is not None:
        # extra context saved the args, what's for?
        callcontext.extra_context = _populate_context_lookup(
            self, context.clone())

    res = []
    for callee in self.func.query(context):
        if callee is util.Unqueryable:
            if self.keywords is not None:
                # not implemented
                print(self.keywords)
                assert False
            for arg in self.args:
                res.extend(arg.query(context))
            continue

        if hasattr(callee, "query_end") and callee.query_end:
            res.append(callee)
            continue

        try:
            if hasattr(callee, "query_call_result"):
                for result in callee.query_call_result(caller=self,
                                                       context=callcontext):
                    if result is util.Unqueryable:
                        for arg in self.args:
                            res.extend(arg.query(context))
                    else:
                        res.append(result)

        except exceptions.InferenceError:
            continue
    return res
Пример #23
0
            def infer_call_result(self, caller, context=None):
                if len(caller.args) != 2:
                    raise exceptions.InferenceError(
                        "Invalid arguments for descriptor binding",
                        target=self,
                        context=context)

                context = contextmod.copy_context(context)
                cls = next(caller.args[0].infer(context=context))

                # Rebuild the original value, but with the parent set as the
                # class where it will be bound.
                new_func = func.__class__(name=func.name,
                                          doc=func.doc,
                                          lineno=func.lineno,
                                          col_offset=func.col_offset,
                                          parent=cls)
                new_func.postinit(func.args, func.body, func.decorators,
                                  func.returns)

                # Build a proper bound method that points to our newly built function.
                proxy = bases.UnboundMethod(new_func)
                yield bases.BoundMethod(proxy=proxy, bound=cls)
Пример #24
0
 def __init__(self, parent=None, generator_initial_context=None):
     super().__init__()
     self.parent = parent
     self._call_context = copy_context(generator_initial_context)