From 4f2223ae7bf4ddf7391fb9b7ad2e29d486553ccf Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Tue, 28 Oct 2014 16:22:59 +0100 Subject: [PATCH] Super is now working. Still has the same flaws like the old implementation, but the tests are passing. --- jedi/evaluate/__init__.py | 6 +++--- jedi/evaluate/param.py | 9 +++++++-- jedi/evaluate/stdlib.py | 21 +++++++++++---------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index 947add09..8a7ac03f 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -233,7 +233,7 @@ class Evaluator(object): if trailer_op == '.': new_types += self.find_types(typ, node) elif trailer_op == '(': - new_types += self.execute(typ, node) + new_types += self.execute(typ, node, trailer) elif trailer_op == '[': try: get = typ.get_index_types @@ -245,8 +245,8 @@ class Evaluator(object): return new_types @debug.increase_indent - def execute(self, obj, arguments=()): - arguments = param.Arguments(self, arguments) + def execute(self, obj, arguments=(), trailer=None): + arguments = param.Arguments(self, arguments, trailer) if obj.isinstance(er.Function): obj = obj.get_decorated_func() diff --git a/jedi/evaluate/param.py b/jedi/evaluate/param.py index e95eb08e..89507c8c 100644 --- a/jedi/evaluate/param.py +++ b/jedi/evaluate/param.py @@ -13,13 +13,14 @@ from jedi.evaluate import precedence class Arguments(pr.Base): - def __init__(self, evaluator, argument_node): + def __init__(self, evaluator, argument_node, trailer=None): """ The argument_node is either a parser node or a list of evaluated objects. """ self.argument_node = argument_node self._evaluator = evaluator + self._trailer = trailer # Can be None, e.g. in a class definition. def _split(self): if isinstance(self.argument_node, (tuple, list)): @@ -110,10 +111,14 @@ class Arguments(pr.Base): if not values and not optional: # For the stdlib we always want values. If we don't get them, # that's ok, maybe something is too hard to resolve, however, - # we will not proceed with the evaluation of that function. + # we will not proceed with the evaluation of that function. raise ValueError yield values + def scope(self): + # Returns the scope in which the arguments are used. + return (self._trailer or self.argument_node).get_parent_until(pr.IsScope) + def eval_args(self): return [self._evaluator.eval_element(el) for stars, el in self._split()] diff --git a/jedi/evaluate/stdlib.py b/jedi/evaluate/stdlib.py index 23e6e3f4..e8559720 100644 --- a/jedi/evaluate/stdlib.py +++ b/jedi/evaluate/stdlib.py @@ -56,7 +56,7 @@ def _follow_param(evaluator, params, index): return [stmt] # just some arbitrary object -def argument_clinic(string, want_obj=False): +def argument_clinic(string, want_obj=False, want_scope=False): """ Works like Argument Clinic (PEP 436), to validate function params. """ @@ -83,10 +83,12 @@ def argument_clinic(string, want_obj=False): except ValueError: return [] else: + kwargs = {} + if want_scope: + kwargs['scope'] = arguments.scope() if want_obj: - return func(evaluator, obj, *lst) - else: - return func(evaluator, *lst) + kwargs['obj'] = obj + return func(evaluator, *lst, **kwargs) return wrapper return f @@ -127,15 +129,14 @@ class SuperInstance(er.Instance): super().__init__(evaluator, su and su[0] or self) -@argument_clinic('[type[, obj]], /', want_obj=True) -def builtins_super(evaluator, obj, types, objects): +@argument_clinic('[type[, obj]], /', want_scope=True) +def builtins_super(evaluator, types, objects, scope): # TODO make this able to detect multiple inheritance super accept = (pr.Function, er.FunctionExecution) - func = obj.get_parent_until(accept) - if func.isinstance(*accept): + if scope.isinstance(*accept): wanted = (pr.Class, er.Instance) - cls = func.get_parent_until(accept + wanted, - include_current=False) + cls = scope.get_parent_until(accept + wanted, + include_current=False) if isinstance(cls, wanted): if isinstance(cls, pr.Class): cls = er.Class(evaluator, cls)