def igetattr(self, name, context=None): """inferred getattr""" if not context: context = InferenceContext() try: context.lookupname = name # avoid recursively inferring the same attr on the same class if context.push(self._proxied): raise InferenceError( message="Cannot infer the same attribute again", node=self, context=context, ) # XXX frame should be self._proxied, or not ? get_attr = self.getattr(name, context, lookupclass=False) yield from _infer_stmts(self._wrap_attr(get_attr, context), context, frame=self) except AttributeInferenceError: try: # fallback to class.igetattr since it has some logic to handle # descriptors # But only if the _proxied is the Class. if self._proxied.__class__.__name__ != "ClassDef": raise attrs = self._proxied.igetattr(name, context, class_context=False) yield from self._wrap_attr(attrs, context) except AttributeInferenceError as error: raise InferenceError(**vars(error)) from error
def _infer_stmts(stmts, context, frame=None): """Return an iterator on statements inferred by each statement in *stmts*.""" inferred = False if context is not None: name = context.lookupname context = context.clone() else: name = None context = InferenceContext() for stmt in stmts: if stmt is Uninferable: yield stmt inferred = True continue context.lookupname = stmt._infer_name(frame, name) try: for inf in stmt.infer(context=context): yield inf inferred = True except NameInferenceError: continue except InferenceError: yield Uninferable inferred = True if not inferred: raise InferenceError( "Inference failed for all members of {stmts!r}.", stmts=stmts, frame=frame, context=context, )