Ejemplo n.º 1
0
    def attr___subclasses__(self):
        """Get the subclasses of the underlying class

        This looks only in the current module for retrieving the subclasses,
        thus it might miss a couple of them.
        """
        if not self._instance.newstyle:
            raise AttributeInferenceError(
                target=self._instance, attribute="__subclasses__"
            )

        qname = self._instance.qname()
        root = self._instance.root()
        classes = [
            cls
            for cls in root.nodes_of_class(nodes.ClassDef)
            if cls != self._instance and cls.is_subtype_of(qname, context=self.context)
        ]

        obj = node_classes.List(parent=self._instance)
        obj.postinit(classes)

        class SubclassesBoundMethod(bases.BoundMethod):
            def infer_call_result(self, caller, context=None):
                yield obj

        implicit_metaclass = self._instance.implicit_metaclass()
        subclasses_method = implicit_metaclass.locals["__subclasses__"][0]
        return SubclassesBoundMethod(proxy=subclasses_method, bound=implicit_metaclass)
Ejemplo n.º 2
0
    def getattr(self, name, context=None, lookupclass=True):
        try:
            values = self._proxied.instance_attr(name, context)
        except AttributeInferenceError as exc:
            if self.special_attributes and name in self.special_attributes:
                return [self.special_attributes.lookup(name)]

            if lookupclass:
                # Class attributes not available through the instance
                # unless they are explicitly defined.
                return self._proxied.getattr(name,
                                             context,
                                             class_context=False)

            raise AttributeInferenceError(target=self,
                                          attribute=name,
                                          context=context) from exc
        # since we've no context information, return matching class members as
        # well
        if lookupclass:
            try:
                return values + self._proxied.getattr(
                    name, context, class_context=False)
            except AttributeInferenceError:
                pass
        return values
Ejemplo n.º 3
0
 def full_raiser(origin_func, attr, *args, **kwargs):
     """
     Raises an AttributeInferenceError in case of access to __class_getitem__ method.
     Otherwise just call origin_func.
     """
     if attr == "__class_getitem__":
         raise AttributeInferenceError("__class_getitem__ access is not allowed")
     return origin_func(attr, *args, **kwargs)
Ejemplo n.º 4
0
    def attr___mro__(self):
        if not self._instance.newstyle:
            raise AttributeInferenceError(target=self._instance, attribute="__mro__")

        mro = self._instance.mro()
        obj = node_classes.Tuple(parent=self._instance)
        obj.postinit(mro)
        return obj
Ejemplo n.º 5
0
    def lookup(self, name):
        """Look up the given *name* in the current model

        It should return an AST or an interpreter object,
        but if the name is not found, then an AttributeInferenceError will be raised.
        """
        if name in self.attributes():
            return getattr(self, IMPL_PREFIX + name)
        raise AttributeInferenceError(target=self._instance, attribute=name)
Ejemplo n.º 6
0
def _lookup_in_mro(node, name):
    attrs = node.locals.get(name, [])

    nodes = itertools.chain.from_iterable(
        ancestor.locals.get(name, [])
        for ancestor in node.ancestors(recurs=True))
    values = list(itertools.chain(attrs, nodes))
    if not values:
        raise AttributeInferenceError(attribute=name, target=node)

    return values
Ejemplo n.º 7
0
 def real_name(self, asname):
     """get name from 'as' name"""
     for name, _asname in self.names:
         if name == "*":
             return asname
         if not _asname:
             name = name.split(".", 1)[0]
             _asname = name
         if asname == _asname:
             return name
     raise AttributeInferenceError(
         "Could not find original name for {attribute} in {target!r}",
         target=self,
         attribute=asname,
     )
Ejemplo n.º 8
0
    def attr_mro(self):
        if not self._instance.newstyle:
            raise AttributeInferenceError(target=self._instance, attribute="mro")

        other_self = self

        # Cls.mro is a method and we need to return one in order to have a proper inference.
        # The method we're returning is capable of inferring the underlying MRO though.
        class MroBoundMethod(bases.BoundMethod):
            def infer_call_result(self, caller, context=None):
                yield other_self.attr___mro__

        implicit_metaclass = self._instance.implicit_metaclass()
        mro_method = implicit_metaclass.locals["mro"][0]
        return MroBoundMethod(proxy=mro_method, bound=implicit_metaclass)
Ejemplo n.º 9
0
def lookup(node, name):
    """Lookup the given special method name in the given *node*

    If the special method was found, then a list of attributes
    will be returned. Otherwise, `astroid.AttributeInferenceError`
    is going to be raised.
    """
    if isinstance(node, (astroid.List, astroid.Tuple, astroid.Const,
                         astroid.Dict, astroid.Set)):
        return _builtin_lookup(node, name)
    if isinstance(node, astroid.Instance):
        return _lookup_in_mro(node, name)
    if isinstance(node, astroid.ClassDef):
        return _class_lookup(node, name)

    raise AttributeInferenceError(attribute=name, target=node)
Ejemplo n.º 10
0
    def attr___path__(self):
        if not self._instance.package:
            raise AttributeInferenceError(target=self._instance,
                                          attribute="__path__")

        path_objs = [
            node_classes.Const(
                value=path
                if not path.endswith("__init__.py") else os.path.dirname(path),
                parent=self._instance,
            ) for path in self._instance.path
        ]

        container = node_classes.List(parent=self._instance)
        container.postinit(path_objs)

        return container
Ejemplo n.º 11
0
def _builtin_lookup(node, name):
    values = node.locals.get(name, [])
    if not values:
        raise AttributeInferenceError(attribute=name, target=node)

    return values
Ejemplo n.º 12
0
def _class_lookup(node, name):
    metaclass = node.metaclass()
    if metaclass is None:
        raise AttributeInferenceError(attribute=name, target=node)

    return _lookup_in_mro(metaclass, name)
Ejemplo n.º 13
0
    def igetattr(self, name, context=None):
        """Retrieve the inferred values of the given attribute name."""

        if name in self.special_attributes:
            yield self.special_attributes.lookup(name)
            return

        try:
            mro = self.super_mro()
        # Don't let invalid MROs or invalid super calls
        # leak out as is from this function.
        except SuperError as exc:
            raise AttributeInferenceError(
                (
                    "Lookup for {name} on {target!r} because super call {super!r} "
                    "is invalid."
                ),
                target=self,
                attribute=name,
                context=context,
                super_=exc.super_,
            ) from exc
        except MroError as exc:
            raise AttributeInferenceError(
                (
                    "Lookup for {name} on {target!r} failed because {cls!r} has an "
                    "invalid MRO."
                ),
                target=self,
                attribute=name,
                context=context,
                mros=exc.mros,
                cls=exc.cls,
            ) from exc
        found = False
        for cls in mro:
            if name not in cls.locals:
                continue

            found = True
            for inferred in bases._infer_stmts([cls[name]], context, frame=self):
                if not isinstance(inferred, scoped_nodes.FunctionDef):
                    yield inferred
                    continue

                # We can obtain different descriptors from a super depending
                # on what we are accessing and where the super call is.
                if inferred.type == "classmethod":
                    yield bases.BoundMethod(inferred, cls)
                elif self._scope.type == "classmethod" and inferred.type == "method":
                    yield inferred
                elif self._class_based or inferred.type == "staticmethod":
                    yield inferred
                elif isinstance(inferred, Property):
                    function = inferred.function
                    try:
                        yield from function.infer_call_result(
                            caller=self, context=context
                        )
                    except InferenceError:
                        yield util.Uninferable
                elif bases._is_property(inferred):
                    # TODO: support other descriptors as well.
                    try:
                        yield from inferred.infer_call_result(self, context)
                    except InferenceError:
                        yield util.Uninferable
                else:
                    yield bases.BoundMethod(inferred, cls)

        if not found:
            raise AttributeInferenceError(target=self, attribute=name, context=context)