From 94126edda89ffc975bb254d615490b75c2827d34 Mon Sep 17 00:00:00 2001 From: David Halter Date: Fri, 8 Feb 2013 12:32:19 +0100 Subject: [PATCH] get rid of generate_param_array --- jedi/evaluate.py | 9 ++--- jedi/evaluate_representation.py | 70 ++++++++++++++++++--------------- jedi/helpers.py | 13 ------ 3 files changed, 42 insertions(+), 50 deletions(-) diff --git a/jedi/evaluate.py b/jedi/evaluate.py index a7a12229..7cc4062c 100644 --- a/jedi/evaluate.py +++ b/jedi/evaluate.py @@ -82,7 +82,6 @@ import debug import builtin import imports import recursion -import helpers import dynamic import docstrings @@ -416,9 +415,8 @@ def check_getattr(inst, name_str): result = [] # str is important to lose the NamePart! name = pr.Call(str(name_str), pr.Call.STRING, (0, 0), inst) - args = helpers.generate_param_array([name]) try: - result = inst.execute_subscope_by_name('__getattr__', args) + result = inst.execute_subscope_by_name('__getattr__', [name]) except KeyError: pass if not result: @@ -427,7 +425,7 @@ def check_getattr(inst, name_str): # could be practical and the jedi would return wrong types. If # you ever have something, let me know! try: - result = inst.execute_subscope_by_name('__getattribute__', args) + result = inst.execute_subscope_by_name('__getattribute__', [name]) except KeyError: pass return result @@ -663,8 +661,7 @@ def follow_call_path(path, scope, position): debug.warning('unknown type:', current.type, current) scopes = [] # Make instances of those number/string objects. - arr = helpers.generate_param_array([current.name]) - scopes = [er.Instance(s, arr) for s in scopes] + scopes = [er.Instance(s, [current.name]) for s in scopes] result = imports.strip_imports(scopes) return follow_paths(path, result, scope, position=position) diff --git a/jedi/evaluate_representation.py b/jedi/evaluate_representation.py index 6ba4effc..95b5acbe 100644 --- a/jedi/evaluate_representation.py +++ b/jedi/evaluate_representation.py @@ -35,12 +35,12 @@ class DecoratorNotFound(LookupError): class Executable(pr.Base): - """ An instance is also an executable - because __init__ is called """ - def __init__(self, base, var_args=None): + """ + An instance is also an executable - because __init__ is called + :param var_args: The param input array, consist of `pr.Array` or list. + """ + def __init__(self, base, var_args=[]): self.base = base - # The param input array. - if var_args is None: - var_args = pr.Array(None, None) self.var_args = var_args def get_parent_until(self, *args, **kwargs): @@ -122,20 +122,15 @@ class Instance(use_metaclass(cache.CachedMetaClass, Executable)): sub = self.base.get_subscope_by_name(name) return InstanceElement(self, sub, True) - def execute_subscope_by_name(self, name, args=None): - if args is None: - args = helpers.generate_param_array([]) + def execute_subscope_by_name(self, name, args=[]): method = self.get_subscope_by_name(name) - if args.parent_stmt is None: - args.parent_stmt = method return Execution(method, args).get_return_types() def get_descriptor_return(self, obj): """ Throws a KeyError if there's no method. """ # Arguments in __get__ descriptors are obj, class. # `method` is the new parent of the array, don't know if that's good. - v = [obj, obj.base] if isinstance(obj, Instance) else [None, obj] - args = helpers.generate_param_array(v) + args = [obj, obj.base] if isinstance(obj, Instance) else [None, obj] return self.execute_subscope_by_name('__get__', args) @cache.memoize_default([]) @@ -165,7 +160,7 @@ class Instance(use_metaclass(cache.CachedMetaClass, Executable)): yield self, names def get_index_types(self, index=None): - args = helpers.generate_param_array([] if index is None else [index]) + args = [] if index is None else [index] try: return self.execute_subscope_by_name('__getitem__', args) except KeyError: @@ -340,9 +335,8 @@ class Function(use_metaclass(cache.CachedMetaClass, pr.Base)): decorator = dec_results.pop() # Create param array. old_func = Function(f, is_decorated=True) - params = helpers.generate_param_array([old_func], old_func) - wrappers = Execution(decorator, params).get_return_types() + wrappers = Execution(decorator, [old_func]).get_return_types() if not len(wrappers): debug.warning('no wrappers found', self.base_func) return None @@ -389,6 +383,17 @@ class Execution(Executable): multiple calls to functions and recursion has to be avoided. But this is responsibility of the decorators. """ + def follow_var_arg(self, index): + try: + stmt = self.var_args[index] + except IndexError: + return [] + else: + if isinstance(stmt, pr.Statement): + return evaluate.follow_statement(stmt) + else: + return [stmt] # just some arbitrary object + @cache.memoize_default(default=[]) @recursion.ExecutionRecursionDecorator def get_return_types(self, evaluate_generator=False): @@ -402,8 +407,8 @@ class Execution(Executable): if func_name == 'getattr': # follow the first param try: - objects = evaluate.follow_call_list([self.var_args[0]]) - names = evaluate.follow_call_list([self.var_args[1]]) + objects = self.follow_var_arg(0) + names = self.follow_var_arg(1) except IndexError: debug.warning('getattr() called with to few args.') return [] @@ -421,11 +426,12 @@ class Execution(Executable): elif func_name == 'type': # otherwise it would be a metaclass if len(self.var_args) == 1: - objects = evaluate.follow_call_list([self.var_args[0]]) + objects = self.follow_var_arg(0) return [o.base for o in objects if isinstance(o, Instance)] elif func_name == 'super': + # TODO make this able to detect multiple inheritance supers accept = (pr.Function,) - func = self.var_args.parent_stmt.get_parent_until(accept) + func = self.var_args.get_parent_until(accept) if func.isinstance(*accept): cls = func.get_parent_until(accept + (pr.Class,), include_current=False) @@ -597,20 +603,20 @@ class Execution(Executable): """ def iterate(): # `var_args` is typically an Array, and not a list. - for var_arg in self.var_args: - # empty var_arg - if len(var_arg) == 0: - yield None, None + for stmt in self.var_args: + if not isinstance(stmt, pr.Statement): + yield None, stmt # *args - elif var_arg[0] == '*': - arrays = evaluate.follow_call_list([var_arg[1:]]) + elif stmt.token_list[0] == '*': + arrays = evaluate.follow_call_list([stmt.token_list[1:]]) + # *args must be some sort of an array, otherwise -> ignore for array in arrays: if hasattr(array, 'get_contents'): for field in array.get_contents(): yield None, field # **kwargs - elif var_arg[0] == '**': - arrays = evaluate.follow_call_list([var_arg[1:]]) + elif stmt[0] == '**': + arrays = evaluate.follow_call_list([stmt.token_list[1:]]) for array in arrays: if hasattr(array, 'get_contents'): for key, field in array.get_contents(): @@ -623,11 +629,13 @@ class Execution(Executable): yield name, field # Normal arguments (including key arguments). else: - if len(var_arg) > 1 and var_arg[1] == '=': - # This is a named parameter (var_arg[0] is a Call). - yield var_arg[0].name, var_arg[2:] + if stmt.assignment_detail: + tok, key_arr = stmt.assignment_detail[0] + # named parameter + if key_arr and isinstance(key_arr[0], pr.Call): + yield tok[0].name, stmt else: - yield None, var_arg + yield None, stmt return iter(common.PushBackIterator(iterate())) diff --git a/jedi/helpers.py b/jedi/helpers.py index b276a5dd..4478ba20 100644 --- a/jedi/helpers.py +++ b/jedi/helpers.py @@ -60,19 +60,6 @@ def fast_parent_copy(obj): return recursion(obj) -def generate_param_array(args_tuple, parent_stmt=None): - """ This generates an array, that can be used as a param. """ - values = [] - for arg in args_tuple: - if arg is None: - values.append([]) - else: - values.append([arg]) - pos = None - arr = pr.Array(pos, pr.Array.TUPLE, parent_stmt, values=values) - return arr - - def check_arr_index(arr, pos): positions = arr.arr_el_pos for index, comma_pos in enumerate(positions):