Esempio n. 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.arguments or self.vararg or self.kwarg):
        yield util.Uninferable
        return
    # first argument of instance/class method
    if self.arguments and getattr(self.arguments[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(cls)
            return

    if context and context.callcontext:
        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 = [bases.Instance(cls)]
        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)
        yield from self.default_value(name).infer(context)
        yield util.Uninferable
    except exceptions.NoDefault:
        yield util.Uninferable
Esempio n. 2
0
def excepthandler_assigned_stmts(self, node=None, context=None, asspath=None):
    for assigned in node_classes.unpack_infer(self.type):
        if isinstance(assigned, nodes.ClassDef):
            assigned = bases.Instance(assigned)
        yield assigned
    # Explicit StopIteration to return error information, see comment
    # in raise_if_nothing_inferred.
    raise StopIteration(
        dict(node=self, unknown=node, assign_path=asspath, context=context))
Esempio n. 3
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
def interfaces(node, herited=True, handler_func=_iface_hdlr):
    """Return an iterator on interfaces implemented by the given class node."""
    try:
        implements = bases.Instance(node).getattr("__implements__")[0]
    except exceptions.NotFoundError:
        return
    if not herited and implements.frame() is not node:
        return
    found = set()
    missing = False
    for iface in node_classes.unpack_infer(implements):
        if iface is astroid.Uninferable:
            missing = True
            continue
        if iface not in found and handler_func(iface):
            found.add(iface)
            yield iface
    if missing:
        raise exceptions.InferenceError()
Esempio n. 5
0
def excepthandler_assigned_stmts(self, node=None, context=None, asspath=None):
    for assigned in node_classes.unpack_infer(self.type):
        if isinstance(assigned, nodes.ClassDef):
            assigned = bases.Instance(assigned)
        yield assigned
Esempio n. 6
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: TODO
        """
        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 = 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 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)
Esempio n. 7
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)