diff options
Diffstat (limited to 'astroid/bases.py')
-rw-r--r-- | astroid/bases.py | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/astroid/bases.py b/astroid/bases.py index 3b6a248a..64df70dd 100644 --- a/astroid/bases.py +++ b/astroid/bases.py @@ -203,7 +203,7 @@ class BaseInstance(Proxy): else: yield attr - def infer_call_result(self, caller, context=None): + def infer_call_result(self, caller, context=None, context_lookup=None): """infer what a class instance is returning when called""" inferred = False for node in self._proxied.igetattr('__call__', context): @@ -302,14 +302,33 @@ class UnboundMethod(Proxy): return iter((self.special_attributes.lookup(name), )) return self._proxied.igetattr(name, context) - def infer_call_result(self, caller, context): + def infer_call_result(self, caller, context, context_lookup=None): + """ + The context_lookup argument is used to correctly infer + arguments to object.__new__(cls) calls inside classmethods + + The boundnode of the regular context with a function called + on ``object.__new__`` will be of type ``object``, + which is incorrect for the argument in general. + If no context is given the ``object.__new__`` call argument will + correctly inferred except when inside a call that requires + the additonal context (such as a classmethod) of the boundnode + to determine which class the method was called from + """ + # If we're unbound method __new__ of builtin object, the result is an # instance of the class given as first argument. if (self._proxied.name == '__new__' and self._proxied.parent.frame().qname() == '%s.object' % BUILTINS): - infer = caller.args[0].infer() if caller.args else [] + if caller.args: + if context_lookup is None: + context_lookup = {} + node_context = context_lookup.get(caller.args[0]) + infer = caller.args[0].infer(context=node_context) + else: + infer = [] return (Instance(x) if x is not util.Uninferable else x for x in infer) - return self._proxied.infer_call_result(caller, context) + return self._proxied.infer_call_result(caller, context, context_lookup) def bool_value(self): return True @@ -394,7 +413,7 @@ class BoundMethod(UnboundMethod): cls.locals = cls_locals return cls - def infer_call_result(self, caller, context=None): + def infer_call_result(self, caller, context=None, context_lookup=None): if context is None: context = contextmod.InferenceContext() context = context.clone() @@ -412,7 +431,7 @@ class BoundMethod(UnboundMethod): if new_cls: return iter((new_cls, )) - return super(BoundMethod, self).infer_call_result(caller, context) + return super(BoundMethod, self).infer_call_result(caller, context, context_lookup) def bool_value(self): return True |