예제 #1
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 YES
        return
    # first argument of instance/class method
    if self.args and getattr(self.args[0], 'name', None) == name:
        functype = self.parent.type
        if functype == 'method':
            yield Instance(self.parent.parent.frame())
            return
        if functype == 'classmethod':
            yield self.parent.parent.frame()
            return
    if name == self.vararg:
        yield const_factory(())
        return
    if name == self.kwarg:
        yield const_factory({})
        return
    # if there is a default value, yield it. And then yield YES to reflect
    # we can't guess given argument value
    try:
        context = copy_context(context)
        for infered in self.default_value(name).infer(context):
            yield infered
        yield YES
    except NoDefault:
        yield YES
예제 #2
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 YES
        return
    # first argument of instance/class method
    if self.args and getattr(self.args[0], 'name', None) == name:
        functype = self.parent.type
        if functype == 'method':
            yield Instance(self.parent.parent.frame())
            return
        if functype == 'classmethod':
            yield self.parent.parent.frame()
            return
    if name == self.vararg:
        vararg = const_factory(())
        vararg.parent = self
        yield vararg
        return
    if name == self.kwarg:
        kwarg = const_factory({})
        kwarg.parent = self
        yield kwarg
        return
    # if there is a default value, yield it. And then yield YES to reflect
    # we can't guess given argument value
    try:
        if context is None:
            context = InferenceContext()
        for infered in self.default_value(name).infer(context):
            yield infered
        yield YES
    except NoDefault:
        yield YES
예제 #3
0
def const_infer_unary_op(self, operator):
    if operator == 'not':
        return const_factory(not self.value)
    # XXX log potentially raised TypeError
    elif operator == '+':
        return const_factory(+self.value)
    else:  # operator == '-':
        return const_factory(-self.value)
예제 #4
0
def const_infer_unary_op(self, operator):
    if operator == 'not':
        return const_factory(not self.value)
    # XXX log potentially raised TypeError
    elif operator == '+':
        return const_factory(+self.value)
    else: # operator == '-':
        return const_factory(-self.value)
예제 #5
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
예제 #6
0
 def test_infered_dont_pollute(self):
     code = '''
         def func(a=None):
             a.custom_attr = 0
         def func2(a={}):
             a.custom_attr = 0
         '''
     test_utils.build_module(code)
     nonetype = nodes.const_factory(None)
     self.assertNotIn('custom_attr', nonetype.locals)
     self.assertNotIn('custom_attr', nonetype.instance_attrs)
     nonetype = nodes.const_factory({})
     self.assertNotIn('custom_attr', nonetype.locals)
     self.assertNotIn('custom_attr', nonetype.instance_attrs)
예제 #7
0
 def test_inferred_dont_pollute(self):
     code = '''
         def func(a=None):
             a.custom_attr = 0
         def func2(a={}):
             a.custom_attr = 0
         '''
     builder.parse(code)
     nonetype = nodes.const_factory(None)
     self.assertNotIn('custom_attr', nonetype._locals)
     self.assertNotIn('custom_attr', nonetype._instance_attrs)
     nonetype = nodes.const_factory({})
     self.assertNotIn('custom_attr', nonetype._locals)
     self.assertNotIn('custom_attr', nonetype._instance_attrs)
예제 #8
0
    def test_infered_dont_pollute(self):
        code = '''
def func(a=None):
    a.custom_attr = 0
def func2(a={}):
    a.custom_attr = 0
    '''
        astroid = self.builder.string_build(code)
        nonetype = nodes.const_factory(None)
        self.assertNotIn('custom_attr', nonetype.locals)
        self.assertNotIn('custom_attr', nonetype.instance_attrs)
        nonetype = nodes.const_factory({})
        self.assertNotIn('custom_attr', nonetype.locals)
        self.assertNotIn('custom_attr', nonetype.instance_attrs)
예제 #9
0
 def test_inferred_dont_pollute(self) -> None:
     code = """
         def func(a=None):
             a.custom_attr = 0
         def func2(a={}):
             a.custom_attr = 0
         """
     builder.parse(code)
     nonetype = nodes.const_factory(None)
     self.assertNotIn("custom_attr", nonetype.locals)
     self.assertNotIn("custom_attr", nonetype.instance_attrs)
     nonetype = nodes.const_factory({})
     self.assertNotIn("custom_attr", nonetype.locals)
     self.assertNotIn("custom_attr", nonetype.instance_attrs)
 def test_inferred_dont_pollute(self):
     code = """
         def func(a=None):
             a.custom_attr = 0
         def func2(a={}):
             a.custom_attr = 0
         """
     builder.parse(code)
     nonetype = nodes.const_factory(None)
     self.assertNotIn("custom_attr", nonetype.locals)
     self.assertNotIn("custom_attr", nonetype.instance_attrs)
     nonetype = nodes.const_factory({})
     self.assertNotIn("custom_attr", nonetype.locals)
     self.assertNotIn("custom_attr", nonetype.instance_attrs)
예제 #11
0
    def test_infered_dont_pollute(self):
        code = '''
def func(a=None):
    a.custom_attr = 0
def func2(a={}):
    a.custom_attr = 0
    '''
        astroid = self.builder.string_build(code)
        nonetype = nodes.const_factory(None)
        self.assertNotIn('custom_attr', nonetype.locals)
        self.assertNotIn('custom_attr', nonetype.instance_attrs)
        nonetype = nodes.const_factory({})
        self.assertNotIn('custom_attr', nonetype.locals)
        self.assertNotIn('custom_attr', nonetype.instance_attrs)
예제 #12
0
 def test_inferred_dont_pollute(self):
     code = '''
         def func(a=None):
             a.custom_attr = 0
         def func2(a={}):
             a.custom_attr = 0
         '''
     builder.parse(code)
     nonetype = nodes.const_factory(None)
     # pylint: disable=no-member; Infers two potential values
     self.assertNotIn('custom_attr', nonetype.locals)
     self.assertNotIn('custom_attr', nonetype.instance_attrs)
     nonetype = nodes.const_factory({})
     self.assertNotIn('custom_attr', nonetype.locals)
     self.assertNotIn('custom_attr', nonetype.instance_attrs)
예제 #13
0
 def test_inferred_dont_pollute(self):
     code = """
         def func(a=None):
             a.custom_attr = 0
         def func2(a={}):
             a.custom_attr = 0
         """
     builder.parse(code)
     nonetype = nodes.const_factory(None)
     # pylint: disable=no-member; Infers two potential values
     self.assertNotIn("custom_attr", nonetype.locals)
     self.assertNotIn("custom_attr", nonetype.instance_attrs)
     nonetype = nodes.const_factory({})
     self.assertNotIn("custom_attr", nonetype.locals)
     self.assertNotIn("custom_attr", nonetype.instance_attrs)
예제 #14
0
 def test_inferred_dont_pollute(self):
     code = '''
         def func(a=None):
             a.custom_attr = 0
         def func2(a={}):
             a.custom_attr = 0
         '''
     builder.parse(code)
     nonetype = nodes.const_factory(None)
     # pylint: disable=no-member; union type in const_factory, this shouldn't happen
     self.assertNotIn('custom_attr', nonetype.locals)
     self.assertNotIn('custom_attr', nonetype.instance_attrs)
     nonetype = nodes.const_factory({})
     self.assertNotIn('custom_attr', nonetype.locals)
     self.assertNotIn('custom_attr', nonetype.instance_attrs)
예제 #15
0
 def test_inferred_dont_pollute(self):
     code = '''
         def func(a=None):
             a.custom_attr = 0
         def func2(a={}):
             a.custom_attr = 0
         '''
     builder.parse(code)
     nonetype = nodes.const_factory(None)
     # pylint: disable=no-member; union type in const_factory, this shouldn't happen
     self.assertNotIn('custom_attr', nonetype.locals)
     self.assertNotIn('custom_attr', nonetype.instance_attrs)
     nonetype = nodes.const_factory({})
     self.assertNotIn('custom_attr', nonetype.locals)
     self.assertNotIn('custom_attr', nonetype.instance_attrs)
예제 #16
0
def build_function(
    name,
    args: Optional[List[str]] = None,
    posonlyargs: Optional[List[str]] = None,
    defaults=None,
    doc=None,
    kwonlyargs: Optional[List[str]] = None,
) -> nodes.FunctionDef:
    """create and initialize an astroid FunctionDef node"""
    # first argument is now a list of decorators
    func = nodes.FunctionDef(name, doc)
    func.args = argsnode = nodes.Arguments(parent=func)
    argsnode.postinit(
        args=[
            nodes.AssignName(name=arg, parent=argsnode) for arg in args or ()
        ],
        defaults=[],
        kwonlyargs=[
            nodes.AssignName(name=arg, parent=argsnode)
            for arg in kwonlyargs or ()
        ],
        kw_defaults=[],
        annotations=[],
        posonlyargs=[
            nodes.AssignName(name=arg, parent=argsnode)
            for arg in posonlyargs or ()
        ],
    )
    for default in defaults or ():
        argsnode.defaults.append(nodes.const_factory(default))
        argsnode.defaults[-1].parent = argsnode
    if args:
        register_arguments(func)
    return func
예제 #17
0
def const_infer_binary_op(self, opnode, operator, other, context, _):
    not_implemented = nodes.Const(NotImplemented)
    if isinstance(other, nodes.Const):
        if (operator == "**" and isinstance(self, nodes.Const)
                and isinstance(self.value, (int, float))
                and isinstance(other.value, (int, float))
                and (self.value > 1e5 or other.value > 1e5)):
            yield not_implemented
            return
        try:
            impl = BIN_OP_IMPL[operator]
            try:
                yield nodes.const_factory(impl(self.value, other.value))
            except TypeError:
                # ArithmeticError is not enough: float >> float is a TypeError
                yield not_implemented
            except Exception:  # pylint: disable=broad-except
                yield util.Uninferable
        except TypeError:
            yield not_implemented
    elif isinstance(self.value, str) and operator == "%":
        # TODO(cpopa): implement string interpolation later on.
        yield util.Uninferable
    else:
        yield not_implemented
예제 #18
0
def _infer_unaryop(
    self: nodes.UnaryOp,
    context: InferenceContext | None = None
) -> Generator[InferenceResult | util.BadUnaryOperationMessage, None, 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 inner_exc:
                    # The unary operation special method was not found.
                    yield util.BadUnaryOperationMessage(
                        operand, self.op, inner_exc)
                except InferenceError:
                    yield util.Uninferable
예제 #19
0
def build_function(name, args=None, posonlyargs=None, defaults=None, doc=None):
    """create and initialize an astroid FunctionDef node"""
    args, defaults, posonlyargs = args or [], defaults or [], posonlyargs or []
    # first argument is now a list of decorators
    func = nodes.FunctionDef(name, doc)
    func.args = argsnode = nodes.Arguments()
    argsnode.args = []
    argsnode.posonlyargs = []
    for arg in args:
        argsnode.args.append(nodes.Name())
        argsnode.args[-1].name = arg
        argsnode.args[-1].parent = argsnode
    for arg in posonlyargs:
        argsnode.posonlyargs.append(nodes.Name())
        argsnode.posonlyargs[-1].name = arg
        argsnode.posonlyargs[-1].parent = argsnode
    argsnode.defaults = []
    for default in defaults:
        argsnode.defaults.append(nodes.const_factory(default))
        argsnode.defaults[-1].parent = argsnode
    argsnode.kwarg = None
    argsnode.vararg = None
    argsnode.parent = func
    if args:
        register_arguments(func)
    return func
예제 #20
0
 def transform_function(node):
     assign = nodes.Assign()
     name = nodes.AssignName()
     name.name = "value"
     assign.targets = [name]
     assign.value = nodes.const_factory(42)
     node.body.append(assign)
예제 #21
0
 def test_builtin_lookup(self):
     self.assertEqual(scoped_nodes.builtin_lookup('__dict__')[1], ())
     intstmts = scoped_nodes.builtin_lookup('int')[1]
     self.assertEqual(len(intstmts), 1)
     self.assertIsInstance(intstmts[0], nodes.ClassDef)
     self.assertEqual(intstmts[0].name, 'int')
     self.assertIs(intstmts[0], nodes.const_factory(1)._proxied)
예제 #22
0
 def _test(self, value):
     node = nodes.const_factory(value)
     self.assertIsInstance(node._proxied, nodes.Class)
     self.assertEqual(node._proxied.name, value.__class__.__name__)
     self.assertIs(node.value, value)
     self.assertTrue(node._proxied.parent)
     self.assertEqual(node._proxied.root().name, value.__class__.__module__)
예제 #23
0
 def test_builtin_lookup(self) -> None:
     self.assertEqual(nodes.builtin_lookup("__dict__")[1], ())
     intstmts = nodes.builtin_lookup("int")[1]
     self.assertEqual(len(intstmts), 1)
     self.assertIsInstance(intstmts[0], nodes.ClassDef)
     self.assertEqual(intstmts[0].name, "int")
     self.assertIs(intstmts[0], nodes.const_factory(1)._proxied)
예제 #24
0
 def transform_function(node):
     assign = nodes.Assign()
     name = nodes.AssignName()
     name.name = 'value'
     assign.targets = [name]
     assign.value = nodes.const_factory(42)
     node.body.append(assign)
 def test_builtin_lookup(self):
     self.assertEqual(scoped_nodes.builtin_lookup('__dict__')[1], ())
     intstmts = scoped_nodes.builtin_lookup('int')[1]
     self.assertEqual(len(intstmts), 1)
     self.assertIsInstance(intstmts[0], nodes.ClassDef)
     self.assertEqual(intstmts[0].name, 'int')
     self.assertIs(intstmts[0], nodes.const_factory(1)._proxied)
예제 #26
0
    def _infer_builtin_new(
        self,
        caller: nodes.Call,
        context: InferenceContext,
    ) -> collections.abc.Generator[nodes.Const | Instance | type[Uninferable],
                                   None, None]:
        if not caller.args:
            return
        # Attempt to create a constant
        if len(caller.args) > 1:
            value = None
            if isinstance(caller.args[1], nodes.Const):
                value = caller.args[1].value
            else:
                inferred_arg = next(caller.args[1].infer(), None)
                if isinstance(inferred_arg, nodes.Const):
                    value = inferred_arg.value
            if value is not None:
                yield nodes.const_factory(value)
                return

        node_context = context.extra_context.get(caller.args[0])
        for inferred in caller.args[0].infer(context=node_context):
            if inferred is Uninferable:
                yield inferred
            if isinstance(inferred, nodes.ClassDef):
                yield Instance(inferred)
            raise InferenceError
예제 #27
0
 def test_builtin_lookup(self):
     self.assertEqual(builtin_lookup("__dict__")[1], ())
     intstmts = builtin_lookup("int")[1]
     self.assertEqual(len(intstmts), 1)
     self.assertIsInstance(intstmts[0], nodes.Class)
     self.assertEqual(intstmts[0].name, "int")
     self.assertIs(intstmts[0], nodes.const_factory(1)._proxied)
예제 #28
0
 def _test(self, value):
     node = nodes.const_factory(value)
     self.assertIsInstance(node._proxied, nodes.Class)
     self.assertEqual(node._proxied.name, value.__class__.__name__)
     self.assertIs(node.value, value)
     self.assertTrue(node._proxied.parent)
     self.assertEqual(node._proxied.root().name, value.__class__.__module__)
예제 #29
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
예제 #30
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
예제 #31
0
 def _test(self, value):
     node = nodes.const_factory(value)
     # pylint: disable=no-member; Infers two potential values
     self.assertIsInstance(node._proxied, nodes.ClassDef)
     self.assertEqual(node._proxied.name, value.__class__.__name__)
     self.assertIs(node.value, value)
     self.assertTrue(node._proxied.parent)
     self.assertEqual(node._proxied.root().name, value.__class__.__module__)
예제 #32
0
 def _test(self, value):
     node = nodes.const_factory(value)
     # pylint: disable=no-member; Infers two potential values
     self.assertIsInstance(node._proxied, nodes.ClassDef)
     self.assertEqual(node._proxied.name, value.__class__.__name__)
     self.assertIs(node.value, value)
     self.assertTrue(node._proxied.parent)
     self.assertEqual(node._proxied.root().name, value.__class__.__module__)
예제 #33
0
 def test_builtin_lookup(self):
     self.assertEqual(scoped_nodes.builtin_lookup('__dict__')[1], ())
     intstmts = scoped_nodes.builtin_lookup('int')[1]
     self.assertEqual(len(intstmts), 1)
     self.assertIsInstance(intstmts[0], nodes.ClassDef)
     self.assertEqual(intstmts[0].name, 'int')
     # pylint: disable=no-member; union type in const_factory, this shouldn't happen
     self.assertIs(intstmts[0], nodes.const_factory(1)._proxied)
예제 #34
0
 def test_builtin_lookup(self):
     self.assertEqual(scoped_nodes.builtin_lookup('__dict__')[1], ())
     intstmts = scoped_nodes.builtin_lookup('int')[1]
     self.assertEqual(len(intstmts), 1)
     self.assertIsInstance(intstmts[0], nodes.ClassDef)
     self.assertEqual(intstmts[0].name, 'int')
     # pylint: disable=no-member; union type in const_factory, this shouldn't happen
     self.assertIs(intstmts[0], nodes.const_factory(1)._proxied)
예제 #35
0
 def _test(self, value):
     # pylint: disable=no-member; union type in const_factory, this shouldn't happen
     node = nodes.const_factory(value)
     self.assertIsInstance(node._proxied, nodes.ClassDef)
     self.assertEqual(node._proxied.name, value.__class__.__name__)
     self.assertIs(node.value, value)
     self.assertTrue(node._proxied.parent)
     self.assertEqual(node._proxied.root().name, value.__class__.__module__)
예제 #36
0
 def test_builtin_lookup(self):
     self.assertEqual(scoped_nodes.builtin_lookup('__dict__')[1], ())
     intstmts = scoped_nodes.builtin_lookup('int')[1]
     self.assertEqual(len(intstmts), 1)
     self.assertIsInstance(intstmts[0], nodes.ClassDef)
     self.assertEqual(intstmts[0].name, 'int')
     # pylint: disable=no-member; Infers two potential values
     self.assertIs(intstmts[0], nodes.const_factory(1)._proxied)
예제 #37
0
def _infer_unary_op(obj: Any, op: str) -> ConstFactoryResult:
    """Perform unary operation on `obj`, unless it is `NotImplemented`.

    Can raise TypeError if operation is unsupported.
    """
    if obj is NotImplemented:
        value = obj
    else:
        func = _UNARY_OPERATORS[op]
        value = func(obj)
    return nodes.const_factory(value)
예제 #38
0
파일: inference.py 프로젝트: byd913/vim
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
예제 #39
0
def build_function(
    name: str,
    args: list[str] | None = None,
    posonlyargs: list[str] | None = None,
    defaults: list[Any] | None = None,
    doc: str | None = None,
    kwonlyargs: list[str] | None = None,
) -> nodes.FunctionDef:
    """create and initialize an astroid FunctionDef node"""
    # first argument is now a list of decorators
    func = nodes.FunctionDef(name)
    argsnode = nodes.Arguments(parent=func)

    # If args is None we don't have any information about the signature
    # (in contrast to when there are no arguments and args == []). We pass
    # this to the builder to indicate this.
    if args is not None:
        arguments = [
            nodes.AssignName(name=arg, parent=argsnode) for arg in args
        ]
    else:
        arguments = None

    argsnode.postinit(
        args=arguments,
        defaults=[],
        kwonlyargs=[
            nodes.AssignName(name=arg, parent=argsnode)
            for arg in kwonlyargs or ()
        ],
        kw_defaults=[],
        annotations=[],
        posonlyargs=[
            nodes.AssignName(name=arg, parent=argsnode)
            for arg in posonlyargs or ()
        ],
    )
    func.postinit(
        args=argsnode,
        body=[],
        doc_node=nodes.Const(value=doc) if doc else None,
    )
    for default in defaults or ():
        argsnode.defaults.append(nodes.const_factory(default))
        argsnode.defaults[-1].parent = argsnode
    if args:
        register_arguments(func)
    return func
예제 #40
0
def const_infer_binary_op(self, operator, other, context, _):
    not_implemented = nodes.Const(NotImplemented)
    if isinstance(other, nodes.Const):
        try:
            impl = BIN_OP_IMPL[operator]
            try:
                yield nodes.const_factory(impl(self.value, other.value))
            except TypeError:
                # ArithmeticError is not enough: float >> float is a TypeError
                yield not_implemented
            except Exception: # pylint: disable=broad-except
                yield util.Uninferable
        except TypeError:
            yield not_implemented
    elif isinstance(self.value, six.string_types) and operator == '%':
        # TODO(cpopa): implement string interpolation later on.
        yield util.Uninferable
    else:
        yield not_implemented
예제 #41
0
def _infer_str_format_call(
    node: nodes.Call,
    context: InferenceContext | None = None
) -> Iterator[nodes.Const | type[util.Uninferable]]:
    """Return a Const node based on the template and passed arguments."""
    call = arguments.CallSite.from_call(node, context=context)
    if isinstance(node.func.expr, nodes.Name):
        value: nodes.Const = helpers.safe_infer(node.func.expr)
    else:
        value = node.func.expr

    format_template = value.value

    # Get the positional arguments passed
    inferred_positional = [
        helpers.safe_infer(i, context) for i in call.positional_arguments
    ]
    if not all(isinstance(i, nodes.Const) for i in inferred_positional):
        return iter([util.Uninferable])
    pos_values: list[str] = [i.value for i in inferred_positional]

    # Get the keyword arguments passed
    inferred_keyword = {
        k: helpers.safe_infer(v, context)
        for k, v in call.keyword_arguments.items()
    }
    if not all(isinstance(i, nodes.Const) for i in inferred_keyword.values()):
        return iter([util.Uninferable])
    keyword_values: dict[str, str] = {
        k: v.value
        for k, v in inferred_keyword.items()
    }

    try:
        formatted_string = format_template.format(*pos_values,
                                                  **keyword_values)
    except (IndexError, KeyError):
        # If there is an IndexError there are too few arguments to interpolate
        return iter([util.Uninferable])

    return iter([nodes.const_factory(formatted_string)])
예제 #42
0
def build_function(name, args=None, defaults=None, flag=0, doc=None):
    """create and initialize a astroid Function node"""
    args, defaults = args or [], defaults or []
    # first argument is now a list of decorators
    func = Function(name, doc)
    func.args = argsnode = Arguments()
    argsnode.args = []
    for arg in args:
        argsnode.args.append(Name())
        argsnode.args[-1].name = arg
        argsnode.args[-1].parent = argsnode
    argsnode.defaults = []
    for default in defaults:
        argsnode.defaults.append(const_factory(default))
        argsnode.defaults[-1].parent = argsnode
    argsnode.kwarg = None
    argsnode.vararg = None
    argsnode.parent = func
    if args:
        register_arguments(func)
    return func
예제 #43
0
def const_infer_binary_op(self, operator, other, context):
    for other in other.infer(context):
        if isinstance(other, nodes.Const):
            try:
                impl = BIN_OP_IMPL[operator]

                try:
                    yield const_factory(impl(self.value, other.value))
                except Exception:
                    # ArithmeticError is not enough: float >> float is a TypeError
                    # TODO : let pylint know about the problem
                    pass
            except TypeError:
                # XXX log TypeError
                continue
        elif other is YES:
            yield other
        else:
            try:
                for val in other.infer_binary_op(operator, self, context):
                    yield val
            except AttributeError:
                yield YES
예제 #44
0
def const_infer_binary_op(self, operator, other, context):
    for other in other.infer(context):
        if isinstance(other, nodes.Const):
            try:
                impl = BIN_OP_IMPL[operator]

                try:
                    yield const_factory(impl(self.value, other.value))
                except Exception:
                    # ArithmeticError is not enough: float >> float is a TypeError
                    # TODO : let pylint know about the problem
                    pass
            except TypeError:
                # XXX log TypeError
                continue
        elif other is YES:
            yield other
        else:
            try:
                for val in other.infer_binary_op(operator, self, context):
                    yield val
            except AttributeError:
                yield YES
예제 #45
0
def _infer_old_style_string_formatting(
        instance: nodes.Const, other: nodes.NodeNG, context: InferenceContext
) -> tuple[type[util.Uninferable] | nodes.Const]:
    """Infer the result of '"string" % ...'.

    TODO: Instead of returning Uninferable we should rely
    on the call to '%' to see if the result is actually uninferable.
    """
    values = None
    if isinstance(other, nodes.Tuple):
        if util.Uninferable in other.elts:
            return (util.Uninferable, )
        inferred_positional = [
            helpers.safe_infer(i, context) for i in other.elts
        ]
        if all(isinstance(i, nodes.Const) for i in inferred_positional):
            values = tuple(i.value for i in inferred_positional)
    elif isinstance(other, nodes.Dict):
        values: dict[Any, Any] = {}
        for pair in other.items:
            key = helpers.safe_infer(pair[0], context)
            if not isinstance(key, nodes.Const):
                return (util.Uninferable, )
            value = helpers.safe_infer(pair[1], context)
            if not isinstance(value, nodes.Const):
                return (util.Uninferable, )
            values[key.value] = value.value
    elif isinstance(other, nodes.Const):
        values = other.value
    else:
        return (util.Uninferable, )

    try:
        return (nodes.const_factory(instance.value % values), )
    except (TypeError, KeyError, ValueError):
        return (util.Uninferable, )
예제 #46
0
def attach_const_node(node, name, value):
    """create a Const node and register it in the locals of the given
    node with the specified name
    """
    if name not in node.special_attributes:
        _attach_local_node(node, nodes.const_factory(value), name)
예제 #47
0
 def transform_function(node):
     return nodes.const_factory(42)
예제 #48
0
파일: arguments.py 프로젝트: hugovk/astroid
    def infer_argument(self, funcnode, name, context):
        """infer a function argument value according to the call context

        Arguments:
            funcnode: The function being called.
            name: The name of the argument whose value is being inferred.
            context: Inference context object
        """
        if name in self.duplicated_keywords:
            raise exceptions.InferenceError(
                "The arguments passed to {func!r} "
                " have duplicate keywords.",
                call_site=self,
                func=funcnode,
                arg=name,
                context=context,
            )

        # Look into the keywords first, maybe it's already there.
        try:
            return self.keyword_arguments[name].infer(context)
        except KeyError:
            pass

        # Too many arguments given and no variable arguments.
        if len(self.positional_arguments) > len(funcnode.args.args):
            if not funcnode.args.vararg and not funcnode.args.posonlyargs:
                raise exceptions.InferenceError(
                    "Too many positional arguments "
                    "passed to {func!r} that does "
                    "not have *args.",
                    call_site=self,
                    func=funcnode,
                    arg=name,
                    context=context,
                )

        positional = self.positional_arguments[:len(funcnode.args.args)]
        vararg = self.positional_arguments[len(funcnode.args.args):]
        argindex = funcnode.args.find_argname(name)[0]
        kwonlyargs = {arg.name for arg in funcnode.args.kwonlyargs}
        kwargs = {
            key: value
            for key, value in self.keyword_arguments.items()
            if key not in kwonlyargs
        }
        # If there are too few positionals compared to
        # what the function expects to receive, check to see
        # if the missing positional arguments were passed
        # as keyword arguments and if so, place them into the
        # positional args list.
        if len(positional) < len(funcnode.args.args):
            for func_arg in funcnode.args.args:
                if func_arg.name in kwargs:
                    arg = kwargs.pop(func_arg.name)
                    positional.append(arg)

        if argindex is not None:
            # 2. first argument of instance/class method
            if argindex == 0 and funcnode.type in ("method", "classmethod"):
                if context.boundnode is not None:
                    boundnode = context.boundnode
                else:
                    # XXX can do better ?
                    boundnode = funcnode.parent.frame()

                if isinstance(boundnode, nodes.ClassDef):
                    # Verify that we're accessing a method
                    # of the metaclass through a class, as in
                    # `cls.metaclass_method`. In this case, the
                    # first argument is always the class.
                    method_scope = funcnode.parent.scope()
                    if method_scope is boundnode.metaclass():
                        return iter((boundnode, ))

                if funcnode.type == "method":
                    if not isinstance(boundnode, bases.Instance):
                        boundnode = boundnode.instantiate_class()
                    return iter((boundnode, ))
                if funcnode.type == "classmethod":
                    return iter((boundnode, ))
            # if we have a method, extract one position
            # from the index, so we'll take in account
            # the extra parameter represented by `self` or `cls`
            if funcnode.type in ("method", "classmethod"):
                argindex -= 1
            # 2. search arg index
            try:
                return self.positional_arguments[argindex].infer(context)
            except IndexError:
                pass

        if funcnode.args.kwarg == name:
            # It wants all the keywords that were passed into
            # the call site.
            if self.has_invalid_keywords():
                raise exceptions.InferenceError(
                    "Inference failed to find values for all keyword arguments "
                    "to {func!r}: {unpacked_kwargs!r} doesn't correspond to "
                    "{keyword_arguments!r}.",
                    keyword_arguments=self.keyword_arguments,
                    unpacked_kwargs=self._unpacked_kwargs,
                    call_site=self,
                    func=funcnode,
                    arg=name,
                    context=context,
                )
            kwarg = nodes.Dict(
                lineno=funcnode.args.lineno,
                col_offset=funcnode.args.col_offset,
                parent=funcnode.args,
            )
            kwarg.postinit([(nodes.const_factory(key), value)
                            for key, value in kwargs.items()])
            return iter((kwarg, ))
        if funcnode.args.vararg == name:
            # It wants all the args that were passed into
            # the call site.
            if self.has_invalid_arguments():
                raise exceptions.InferenceError(
                    "Inference failed to find values for all positional "
                    "arguments to {func!r}: {unpacked_args!r} doesn't "
                    "correspond to {positional_arguments!r}.",
                    positional_arguments=self.positional_arguments,
                    unpacked_args=self._unpacked_args,
                    call_site=self,
                    func=funcnode,
                    arg=name,
                    context=context,
                )
            args = nodes.Tuple(
                lineno=funcnode.args.lineno,
                col_offset=funcnode.args.col_offset,
                parent=funcnode.args,
            )
            args.postinit(vararg)
            return iter((args, ))

        # Check if it's a default parameter.
        try:
            return funcnode.args.default_value(name).infer(context)
        except exceptions.NoDefault:
            pass
        raise exceptions.InferenceError(
            "No value found for argument {arg} to {func!r}",
            call_site=self,
            func=funcnode,
            arg=name,
            context=context,
        )
예제 #49
0
 def transform_compare(node):
     # Let's check the values of the ops
     _, right = node.ops[0]
     # Assume they are Consts and they were transformed before
     # us.
     return nodes.const_factory(node.left.value < right.value)
예제 #50
0
    def infer_argument(self, funcnode, name, context):
        """infer a function argument value according to the call context"""
        if name in self.duplicated_keywords:
            raise exceptions.InferenceError(name)

        # Look into the keywords first, maybe it's already there.
        try:
            return self.keyword_arguments[name].infer(context)
        except KeyError:
            pass

        # Too many arguments given and no variable arguments.
        if len(self.positional_arguments) > len(funcnode.args.args):
            if not funcnode.args.vararg:
                raise exceptions.InferenceError(name)

        positional = self.positional_arguments[:len(funcnode.args.args)]
        vararg = self.positional_arguments[len(funcnode.args.args):]
        argindex = funcnode.args.find_argname(name)[0]
        kwonlyargs = set(arg.name for arg in funcnode.args.kwonlyargs)
        kwargs = {
            key: value for key, value in self.keyword_arguments.items()
            if key not in kwonlyargs
        }
        # If there are too few positionals compared to
        # what the function expects to receive, check to see
        # if the missing positional arguments were passed
        # as keyword arguments and if so, place them into the
        # positional args list.
        if len(positional) < len(funcnode.args.args):
            for func_arg in funcnode.args.args:
                if func_arg.name in kwargs:
                    arg = kwargs.pop(func_arg.name)
                    positional.append(arg)

        if argindex is not None:
            # 2. first argument of instance/class method
            if argindex == 0 and funcnode.type in ('method', 'classmethod'):
                if context.boundnode is not None:
                    boundnode = context.boundnode
                else:
                    # XXX can do better ?
                    boundnode = funcnode.parent.frame()
                if funcnode.type == 'method':
                    if not isinstance(boundnode, bases.Instance):
                        boundnode = bases.Instance(boundnode)
                    return iter((boundnode,))
                if funcnode.type == 'classmethod':
                    return iter((boundnode,))
            # if we have a method, extract one position
            # from the index, so we'll take in account
            # the extra parameter represented by `self` or `cls`
            if funcnode.type in ('method', 'classmethod'):
                argindex -= 1
            # 2. search arg index
            try:
                return self.positional_arguments[argindex].infer(context)
            except IndexError:
                pass

        if funcnode.args.kwarg == name:
            # It wants all the keywords that were passed into
            # the call site.
            if self.has_invalid_keywords():
                raise exceptions.InferenceError
            kwarg = nodes.Dict()
            kwarg.lineno = funcnode.args.lineno
            kwarg.col_offset = funcnode.args.col_offset
            kwarg.parent = funcnode.args
            items = [(nodes.const_factory(key), value)
                     for key, value in kwargs.items()]
            kwarg.items = items
            return iter((kwarg, ))
        elif funcnode.args.vararg == name:
            # It wants all the args that were passed into
            # the call site.
            if self.has_invalid_arguments():
                raise exceptions.InferenceError
            args = nodes.Tuple()
            args.lineno = funcnode.args.lineno
            args.col_offset = funcnode.args.col_offset
            args.parent = funcnode.args
            args.elts = vararg
            return iter((args, ))

        # Check if it's a default parameter.
        try:
            return funcnode.args.default_value(name).infer(context)
        except exceptions.NoDefault:
            pass
        raise exceptions.InferenceError(name)
예제 #51
0
 def infer_argument(self, funcnode, name, context):
     """infer a function argument value according to the call context"""
     # 1. search in named keywords
     try:
         return self.nargs[name].infer(context)
     except KeyError:
         # Function.args.args can be None in astroid (means that we don't have
         # information on argnames)
         argindex = funcnode.args.find_argname(name)[0]
         if argindex is not None:
             # 2. first argument of instance/class method
             if argindex == 0 and funcnode.type in ('method', 'classmethod'):
                 if context.boundnode is not None:
                     boundnode = context.boundnode
                 else:
                     # XXX can do better ?
                     boundnode = funcnode.parent.frame()
                 if funcnode.type == 'method':
                     if not isinstance(boundnode, Instance):
                         boundnode = Instance(boundnode)
                     return iter((boundnode,))
                 if funcnode.type == 'classmethod':
                     return iter((boundnode,))
             # if we have a method, extract one position
             # from the index, so we'll take in account
             # the extra parameter represented by `self` or `cls`
             if funcnode.type in ('method', 'classmethod'):
                 argindex -= 1
             # 2. search arg index
             try:
                 return self.args[argindex].infer(context)
             except IndexError:
                 pass
             # 3. search in *args (.starargs)
             if self.starargs is not None:
                 its = []
                 for infered in self.starargs.infer(context):
                     if infered is YES:
                         its.append((YES,))
                         continue
                     try:
                         its.append(infered.getitem(argindex, context).infer(context))
                     except (InferenceError, AttributeError):
                         its.append((YES,))
                     except (IndexError, TypeError):
                         continue
                 if its:
                     return chain(*its)
     # 4. XXX search in **kwargs (.dstarargs)
     if self.dstarargs is not None:
         its = []
         for infered in self.dstarargs.infer(context):
             if infered is YES:
                 its.append((YES,))
                 continue
             try:
                 its.append(infered.getitem(name, context).infer(context))
             except (InferenceError, AttributeError):
                 its.append((YES,))
             except (IndexError, TypeError):
                 continue
         if its:
             return chain(*its)
     # 5. */** argument, (Tuple or Dict)
     if name == funcnode.args.vararg:
         return iter((nodes.const_factory(())))
     if name == funcnode.args.kwarg:
         return iter((nodes.const_factory({})))
     # 6. return default value if any
     try:
         return funcnode.args.default_value(name).infer(context)
     except NoDefault:
         raise InferenceError(name)
예제 #52
0
def dict_infer_unary_op(self, operator):
    if operator == 'not':
        return const_factory(not bool(self.items))
    raise TypeError() # XXX log unsupported operation
예제 #53
0
def attach_const_node(node, name, value):
    """create a Const node and register it in the locals of the given
    node with the specified name
    """
    if not name in node.special_attributes:
        _attach_local_node(node, const_factory(value), name)
예제 #54
0
def _infer_unary_op(obj, op):
    func = _UNARY_OPERATORS[op]
    value = func(obj)
    return nodes.const_factory(value)
예제 #55
0
    def infer_argument(self, funcnode, name, context):
        """infer a function argument value according to the call context

        Arguments:
            funcnode: The function being called.
            name: The name of the argument whose value is being inferred.
            context: Inference context object
        """
        if name in self.duplicated_keywords:
            raise exceptions.InferenceError('The arguments passed to {func!r} '
                                            ' have duplicate keywords.',
                                            call_site=self, func=funcnode,
                                            arg=name, context=context)

        # Look into the keywords first, maybe it's already there.
        try:
            return self.keyword_arguments[name].infer(context)
        except KeyError:
            pass

        # Too many arguments given and no variable arguments.
        if len(self.positional_arguments) > len(funcnode.args.args):
            if not funcnode.args.vararg:
                raise exceptions.InferenceError('Too many positional arguments '
                                                'passed to {func!r} that does '
                                                'not have *args.',
                                                call_site=self, func=funcnode,
                                                arg=name, context=context)

        positional = self.positional_arguments[:len(funcnode.args.args)]
        vararg = self.positional_arguments[len(funcnode.args.args):]
        argindex = funcnode.args.find_argname(name)[0]
        kwonlyargs = {arg.name for arg in funcnode.args.kwonlyargs}
        kwargs = {
            key: value for key, value in self.keyword_arguments.items()
            if key not in kwonlyargs
        }
        # If there are too few positionals compared to
        # what the function expects to receive, check to see
        # if the missing positional arguments were passed
        # as keyword arguments and if so, place them into the
        # positional args list.
        if len(positional) < len(funcnode.args.args):
            for func_arg in funcnode.args.args:
                if func_arg.name in kwargs:
                    arg = kwargs.pop(func_arg.name)
                    positional.append(arg)

        if argindex is not None:
            # 2. first argument of instance/class method
            if argindex == 0 and funcnode.type in ('method', 'classmethod'):
                if context.boundnode is not None:
                    boundnode = context.boundnode
                else:
                    # XXX can do better ?
                    boundnode = funcnode.parent.frame()

                if isinstance(boundnode, nodes.ClassDef):
                    # Verify that we're accessing a method
                    # of the metaclass through a class, as in
                    # `cls.metaclass_method`. In this case, the
                    # first argument is always the class.
                    method_scope = funcnode.parent.scope()
                    if method_scope is boundnode.metaclass():
                        return iter((boundnode, ))

                if funcnode.type == 'method':
                    if not isinstance(boundnode, bases.Instance):
                        boundnode = bases.Instance(boundnode)
                    return iter((boundnode,))
                if funcnode.type == 'classmethod':
                    return iter((boundnode,))
            # if we have a method, extract one position
            # from the index, so we'll take in account
            # the extra parameter represented by `self` or `cls`
            if funcnode.type in ('method', 'classmethod'):
                argindex -= 1
            # 2. search arg index
            try:
                return self.positional_arguments[argindex].infer(context)
            except IndexError:
                pass

        if funcnode.args.kwarg == name:
            # It wants all the keywords that were passed into
            # the call site.
            if self.has_invalid_keywords():
                raise exceptions.InferenceError(
                    "Inference failed to find values for all keyword arguments "
                    "to {func!r}: {unpacked_kwargs!r} doesn't correspond to "
                    "{keyword_arguments!r}.",
                    keyword_arguments=self.keyword_arguments,
                    unpacked_kwargs=self._unpacked_kwargs,
                    call_site=self, func=funcnode, arg=name, context=context)
            kwarg = nodes.Dict(lineno=funcnode.args.lineno,
                               col_offset=funcnode.args.col_offset,
                               parent=funcnode.args)
            kwarg.postinit([(nodes.const_factory(key), value)
                            for key, value in kwargs.items()])
            return iter((kwarg, ))
        elif funcnode.args.vararg == name:
            # It wants all the args that were passed into
            # the call site.
            if self.has_invalid_arguments():
                raise exceptions.InferenceError(
                    "Inference failed to find values for all positional "
                    "arguments to {func!r}: {unpacked_args!r} doesn't "
                    "correspond to {positional_arguments!r}.",
                    positional_arguments=self.positional_arguments,
                    unpacked_args=self._unpacked_args,
                    call_site=self, func=funcnode, arg=name, context=context)
            args = nodes.Tuple(lineno=funcnode.args.lineno,
                               col_offset=funcnode.args.col_offset,
                               parent=funcnode.args)
            args.postinit(vararg)
            return iter((args, ))

        # Check if it's a default parameter.
        try:
            return funcnode.args.default_value(name).infer(context)
        except exceptions.NoDefault:
            pass
        raise exceptions.InferenceError('No value found for argument {name} to '
                                        '{func!r}', call_site=self,
                                        func=funcnode, arg=name, context=context)