Ejemplo n.º 1
0
    def ancestors(self, recurs=True, context=None):
        """return an iterator on the node base classes in a prefixed
        depth first order

        :param recurs:
          boolean indicating if it should recurse or return direct
          ancestors only
        """
        # FIXME: should be possible to choose the resolution order
        # XXX inference make infinite loops possible here (see BaseTransformer
        # manipulation in the builder module for instance)
        yielded = set([self])
        if context is None:
            context = InferenceContext()
        for stmt in self.bases:
            with context.restore_path():
                try:
                    for baseobj in stmt.infer(context):
                        if not isinstance(baseobj, Class):
                            # duh ?
                            continue
                        if baseobj in yielded:
                            continue # cf xxx above
                        yielded.add(baseobj)
                        yield baseobj
                        if recurs:
                            for grandpa in baseobj.ancestors(True, context):
                                if grandpa in yielded:
                                    continue # cf xxx above
                                yielded.add(grandpa)
                                yield grandpa
                except InferenceError:
                    # XXX log error ?
                    continue
Ejemplo n.º 2
0
    def ancestors(self, recurs=True, context=None):
        """return an iterator on the node base classes in a prefixed
        depth first order

        :param recurs:
          boolean indicating if it should recurse or return direct
          ancestors only
        """
        # FIXME: should be possible to choose the resolution order
        # XXX inference make infinite loops possible here (see BaseTransformer
        # manipulation in the builder module for instance)
        yielded = set([self])
        if context is None:
            context = InferenceContext()
        for stmt in self.bases:
            with context.restore_path():
                try:
                    for baseobj in stmt.infer(context):
                        if not isinstance(baseobj, Class):
                            # duh ?
                            continue
                        if baseobj in yielded:
                            continue  # cf xxx above
                        yielded.add(baseobj)
                        yield baseobj
                        if recurs:
                            for grandpa in baseobj.ancestors(True, context):
                                if grandpa in yielded:
                                    continue  # cf xxx above
                                yielded.add(grandpa)
                                yield grandpa
                except InferenceError:
                    # XXX log error ?
                    continue
Ejemplo n.º 3
0
 def test_absolute_import(self):
     astroid = resources.build_file('data/absimport.py')
     ctx = InferenceContext()
     # will fail if absolute import failed
     ctx.lookupname = 'message'
     next(astroid['message'].infer(ctx))
     ctx.lookupname = 'email'
     m = next(astroid['email'].infer(ctx))
     self.assertFalse(m.file.startswith(os.path.join('data', 'email.py')))
Ejemplo n.º 4
0
 def test_absolute_import(self):
     astroid = abuilder.file_build(self.datapath('absimport.py'))
     ctx = InferenceContext()
     ctx.lookupname = 'message'
     # will fail if absolute import failed
     next(astroid['message'].infer(ctx))
     ctx.lookupname = 'email'
     m = next(astroid['email'].infer(ctx))
     self.assertFalse(m.file.startswith(self.datapath('email.py')))
Ejemplo n.º 5
0
 def test_absolute_import(self):
     astroid = resources.build_file('data/absimport.py')
     ctx = InferenceContext()
     # will fail if absolute import failed
     ctx.lookupname = 'message'
     next(astroid['message'].infer(ctx))
     ctx.lookupname = 'email'
     m = next(astroid['email'].infer(ctx))
     self.assertFalse(m.file.startswith(os.path.join('data', 'email.py')))
Ejemplo n.º 6
0
 def test_absolute_import(self):
     astroid = abuilder.file_build(self.datapath('absimport.py'))
     ctx = InferenceContext()
     ctx.lookupname = 'message'
     # will fail if absolute import failed
     astroid['message'].infer(ctx).next()
     ctx.lookupname = 'email'
     m = astroid['email'].infer(ctx).next()
     self.assertFalse(m.file.startswith(self.datapath('email.py')))
Ejemplo n.º 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.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
Ejemplo n.º 8
0
 def igetattr(self, name, context=None):
     """inferred getattr, need special treatment in class to handle
     descriptors
     """
     # set lookup name since this is necessary to infer on import nodes for
     # instance
     if not context:
         context = InferenceContext()
     try:
         for infered in _infer_stmts(self.getattr(name, context), context,
                                     frame=self, lookupname=name):
             # yield YES object instead of descriptors when necessary
             if not isinstance(infered, Const) and isinstance(infered, Instance):
                 try:
                     infered._proxied.getattr('__get__', context)
                 except NotFoundError:
                     yield infered
                 else:
                     yield YES
             else:
                 yield function_to_method(infered, self)
     except NotFoundError:
         if not name.startswith('__') and self.has_dynamic_getattr(context):
             # class handle some dynamic attributes, return a YES object
             yield YES
         else:
             raise InferenceError(name)
Ejemplo n.º 9
0
def infer_getattr(self, context=None):
    """infer a Getattr node by using getattr on the associated object"""
    if not context:
        context = InferenceContext()
    for owner in self.expr.infer(context):
        if owner is YES:
            yield owner
            continue
        try:
            with context.scope(boundnode=owner):
                for obj in owner.igetattr(self.attrname, context):
                    yield obj
        except (NotFoundError, InferenceError):
            pass
        except AttributeError:
            # XXX method / function
            pass
Ejemplo n.º 10
0
    def ilookup(self, name):
        """infered lookup

        return an iterator on infered values of the statements returned by
        the lookup method
        """
        frame, stmts = self.lookup(name)
        context = InferenceContext()
        return _infer_stmts(stmts, context, frame)
Ejemplo n.º 11
0
def infer_callfunc(self, context=None):
    """infer a CallFunc node by trying to guess what the function returns"""
    if context is None:
        context = InferenceContext()
    for callee in self.func.infer(context):
        with context.scope(
            callcontext=CallContext(self.args, self.starargs, self.kwargs),
            boundnode=None,
        ):
            if callee is YES:
                yield callee
                continue
            try:
                if hasattr(callee, 'infer_call_result'):
                    for infered in callee.infer_call_result(self, context):
                        yield infered
            except InferenceError:
                ## XXX log error ?
                continue
Ejemplo n.º 12
0
 def igetattr(self, name, context=None):
     """inferred getattr"""
     # set lookup name since this is necessary to infer on import nodes for
     # instance
     if not context:
         context = InferenceContext()
     try:
         return _infer_stmts(self.getattr(name, context), context, frame=self, lookupname=name)
     except NotFoundError:
         raise InferenceError(name)
Ejemplo n.º 13
0
 def _newstyle_impl(self, context=None):
     if context is None:
         context = InferenceContext()
     if self._newstyle is not None:
         return self._newstyle
     for base in self.ancestors(recurs=False, context=context):
         if base._newstyle_impl(context):
             self._newstyle = True
             break
     if self._newstyle is None:
         self._newstyle = False
     return self._newstyle
Ejemplo n.º 14
0
def starred_assigned_stmts(self, node=None, context=None, asspath=None):
    stmt = self.statement()
    if not isinstance(stmt, (nodes.Assign, nodes.For)):
        raise InferenceError()

    if isinstance(stmt, nodes.Assign):
        value = stmt.value
        lhs = stmt.targets[0]

        if sum(1 for node in lhs.nodes_of_class(nodes.Starred)) > 1:
            # Too many starred arguments in the expression.
            raise InferenceError()

        if context is None:
            context = InferenceContext()
        try:
            rhs = next(value.infer(context))
        except InferenceError:
            yield YES
            return
        if rhs is YES or not hasattr(rhs, 'elts'):
            # Not interested in inferred values without elts.
            yield YES
            return

        elts = collections.deque(rhs.elts[:])
        if len(lhs.elts) > len(rhs.elts):
            # a, *b, c = (1, 2)
            raise InferenceError()

        # Unpack iteratively the values from the rhs of the assignment,
        # until the find the starred node. What will remain will
        # be the list of values which the Starred node will represent
        # This is done in two steps, from left to right to remove
        # anything before the starred node and from right to left
        # to remvoe anything after the starred node.

        for index, node in enumerate(lhs.elts):
            if not isinstance(node, nodes.Starred):
                elts.popleft()
                continue
            lhs_elts = collections.deque(reversed(lhs.elts[index:]))
            for node in lhs_elts:
                if not isinstance(node, nodes.Starred):
                    elts.pop()
                    continue
                # We're done
                for elt in elts:
                    yield elt
                break
Ejemplo n.º 15
0
 def _newstyle_impl(self, context=None):
     if context is None:
         context = InferenceContext()
     if self._newstyle is not None:
         return self._newstyle
     for base in self.ancestors(recurs=False, context=context):
         if base._newstyle_impl(context):
             self._newstyle = True
             break
     klass = self._explicit_metaclass()
     # could be any callable, we'd need to infer the result of klass(name,
     # bases, dict).  punt if it's not a class node.
     if klass is not None and isinstance(klass, Class):
         self._newstyle = klass._newstyle_impl(context)
     if self._newstyle is None:
         self._newstyle = False
     return self._newstyle
Ejemplo n.º 16
0
    def ancestors(self, recurs=True, context=None):
        """return an iterator on the node base classes in a prefixed
        depth first order

        :param recurs:
          boolean indicating if it should recurse or return direct
          ancestors only
        """
        # FIXME: should be possible to choose the resolution order
        # FIXME: inference make infinite loops possible here
        yielded = set([self])
        if context is None:
            context = InferenceContext()
        if sys.version_info[0] >= 3:
            if not self.bases and self.qname() != 'builtins.object':
                yield builtin_lookup("object")[1][0]
                return

        for stmt in self.bases:
            try:
                for baseobj in stmt.infer(context):
                    if not isinstance(baseobj, Class):
                        if isinstance(baseobj, Instance):
                            baseobj = baseobj._proxied
                        else:
                            # duh ?
                            continue
                    if not baseobj.hide:
                        if baseobj in yielded:
                            continue # cf xxx above
                        yielded.add(baseobj)
                        yield baseobj
                    if recurs:
                        for grandpa in baseobj.ancestors(recurs=True,
                                                         context=context):
                            if grandpa in yielded:
                                continue # cf xxx above
                            yielded.add(grandpa)
                            yield grandpa
            except InferenceError:
                # XXX log error ?
                continue
Ejemplo n.º 17
0
def infer_name_module(self, name):
    context = InferenceContext()
    return self.infer(context, asname=False, lookupname=name)
Ejemplo n.º 18
0
def infer_name_module(self, name):
    context = InferenceContext()
    context.lookupname = name
    return self.infer(context, asname=False)