summaryrefslogtreecommitdiff
path: root/astroid/bases.py
diff options
context:
space:
mode:
Diffstat (limited to 'astroid/bases.py')
-rw-r--r--astroid/bases.py31
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