Esempio n. 1
0
def infer_functiondef(
    self: _FunctionDefT,
    context: InferenceContext | None = None,
    **kwargs: Any
) -> Generator[Property | _FunctionDefT, None, InferenceErrorInfo]:
    if not self.decorators or not bases._is_property(self):
        yield self
        return InferenceErrorInfo(node=self, context=context)

    # When inferring a property, we instantiate a new `objects.Property` object,
    # which in turn, because it inherits from `FunctionDef`, sets itself in the locals
    # of the wrapping frame. This means that every time we infer a property, the locals
    # are mutated with a new instance of the property. To avoid this, we detect this
    # scenario and avoid passing the `parent` argument to the constructor.
    parent_frame = self.parent.frame(future=True)
    property_already_in_parent_locals = self.name in parent_frame.locals and any(
        isinstance(val, objects.Property)
        for val in parent_frame.locals[self.name])
    # We also don't want to pass parent if the definition is within a Try node
    if isinstance(self.parent, (nodes.TryExcept, nodes.TryFinally, nodes.If)):
        property_already_in_parent_locals = True

    prop_func = objects.Property(
        function=self,
        name=self.name,
        lineno=self.lineno,
        parent=self.parent if not property_already_in_parent_locals else None,
        col_offset=self.col_offset,
    )
    if property_already_in_parent_locals:
        prop_func.parent = self.parent
    prop_func.postinit(body=[], args=self.args, doc_node=self.doc_node)
    yield prop_func
    return InferenceErrorInfo(node=self, context=context)
Esempio n. 2
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 exceptions.SuperError as exc:
            raise exceptions.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 exceptions.MroError as exc:
            raise exceptions.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 bases._is_property(inferred):
                    # TODO: support other descriptors as well.
                    try:
                        yield from inferred.infer_call_result(self, context)
                    except exceptions.InferenceError:
                        yield util.Uninferable
                else:
                    yield bases.BoundMethod(inferred, cls)

        if not found:
            raise exceptions.AttributeInferenceError(target=self,
                                                     attribute=name,
                                                     context=context)
Esempio n. 3
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 exceptions.SuperError as exc:
            util.reraise(exceptions.AttributeInferenceError(
                ('Lookup for {name} on {target!r} because super call {super!r} '
                 'is invalid.'),
                target=self, attribute=name, context=context, super_=exc.super_))
        except exceptions.MroError as exc:
            util.reraise(exceptions.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))
        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 bases._is_property(inferred):
                    # TODO: support other descriptors as well.
                    for value in inferred.infer_call_result(self, context):
                        yield value
                else:
                    yield bases.BoundMethod(inferred, cls)

        if not found:
            raise exceptions.AttributeInferenceError(target=self,
                                                     attribute=name,
                                                     context=context)
Esempio n. 4
0
def query_functiondef(self, context=None):
    if not self.decorators or not bases._is_property(self):
        return [self]

    prop_func = objects.Property(
        function=self,
        name=self.name,
        doc=self.doc,
        lineno=self.lineno,
        parent=self.parent,
        col_offset=self.col_offset,
    )
    prop_func.postinit(body=[], args=self.args)
    return [prop_func]
Esempio n. 5
0
def infer_functiondef(self, context=None):
    if not self.decorators or not bases._is_property(self):
        yield self
        return dict(node=self, context=context)

    prop_func = objects.Property(
        function=self,
        name=self.name,
        doc=self.doc,
        lineno=self.lineno,
        parent=self.parent,
        col_offset=self.col_offset,
    )
    prop_func.postinit(body=[], args=self.args)
    yield prop_func
    return dict(node=self, context=context)
Esempio n. 6
0
    def igetattr(self, name, context=None):
        """Retrieve the inferred values of the given attribute name."""

        local_name = self._model.get(name)
        if local_name:
            yield local_name
            return

        try:
            mro = self.super_mro()
        except (MroError, SuperError) as exc:
            # Don't let invalid MROs or invalid super calls
            # to leak out as is from this function.
            six.raise_from(NotFoundError, exc)

        found = False
        for cls in mro:
            if name not in cls._locals:
                continue

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

                # We can obtain different descriptors from a super depending
                # on what we are accessing and where the super call is.
                if infered.type == 'classmethod':
                    yield BoundMethod(infered, cls)
                elif self._scope.type == 'classmethod' and infered.type == 'method':
                    yield infered
                elif self._class_based or infered.type == 'staticmethod':
                    yield infered
                elif _is_property(infered):
                    # TODO: support other descriptors as well.
                    for value in infered.infer_call_result(self, context):
                        yield value
                else:
                    yield BoundMethod(infered, cls)

        if not found:
            raise NotFoundError(name)
Esempio n. 7
0
    def igetattr(self, name, context=None):
        """Retrieve the inferred values of the given attribute name."""

        local_name = self._model.get(name)
        if local_name:
            yield local_name
            return

        try:
            mro = self.super_mro()
        except (MroError, SuperError) as exc:
            # Don't let invalid MROs or invalid super calls
            # to leak out as is from this function.
            six.raise_from(NotFoundError, exc)

        found = False
        for cls in mro:
            if name not in cls._locals:
                continue

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

                # We can obtain different descriptors from a super depending
                # on what we are accessing and where the super call is.
                if infered.type == 'classmethod':
                    yield BoundMethod(infered, cls)
                elif self._scope.type == 'classmethod' and infered.type == 'method':
                    yield infered
                elif self._class_based or infered.type == 'staticmethod':
                    yield infered
                elif _is_property(infered):
                    # TODO: support other descriptors as well.
                    for value in infered.infer_call_result(self, context):
                        yield value
                else:
                    yield BoundMethod(infered, cls)

        if not found:
            raise NotFoundError(name)
Esempio n. 8
0
    def igetattr(self, name: str, context: InferenceContext | None = None):
        """Retrieve the inferred values of the given attribute name."""
        # '__class__' is a special attribute that should be taken directly
        # from the special attributes dict
        if name == "__class__":
            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)

        # Only if we haven't found any explicit overwrites for the
        # attribute we look it up in the special attributes
        if not found and name in self.special_attributes:
            yield self.special_attributes.lookup(name)
            return

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