From ae60bce836fd0dffa4c59b515d24cb2de3b6e53b Mon Sep 17 00:00:00 2001 From: David Halter Date: Thu, 9 Aug 2012 16:03:28 +0200 Subject: [PATCH] dynamic arrays are now working pretty good --- dynamic.py | 20 ++++++++++++++----- evaluate.py | 11 +++++----- imports.py | 2 +- mixin/builtins.py | 14 +++++++------ test/completion/arrays.py | 7 ------- test/completion/dynamic.py | 41 +++++++++++++++++++++++++++++++++++++- 6 files changed, 70 insertions(+), 25 deletions(-) diff --git a/dynamic.py b/dynamic.py index df10026d..0bdfb7c6 100644 --- a/dynamic.py +++ b/dynamic.py @@ -84,7 +84,7 @@ def search_params(param): @evaluate.memoize_default([]) -def check_array_additions(array, is_list=True): +def check_array_additions(array): """ Checks if a `parsing.Array` has "add" statements: >>> a = [""] @@ -115,19 +115,29 @@ def check_array_additions(array, is_list=True): position = c.parent_stmt.start_pos scope = c.parent_stmt.parent - print 'd', call_path e = evaluate.follow_call_path(backtrack_path, scope, position) - print 'e', e if not array in e: # the `append`, etc. belong to other arrays continue + params = call_path[separate_index + 1] + if not params.values: + continue # no params: just ignore it if add_name in ['append', 'add']: - result += evaluate.follow_call_list(call_path[separate_index + 1]) + result += evaluate.follow_call_list(params) + elif add_name in ['insert']: + try: + second_param = params[1] + except IndexError: + continue + else: + result += evaluate.follow_call_list([second_param]) elif add_name in ['extend', 'update']: - result += evaluate.follow_call_list(call_path[separate_index + 1]) + # TODO needs extensive work, because this are iterables + result += evaluate.follow_call_list(params) return result + is_list = array._array.type == 'list' stmt = array._array.parent_stmt current_module = stmt.get_parent_until() search_names = ['append', 'extend', 'insert'] if is_list else \ diff --git a/evaluate.py b/evaluate.py index cd042e74..6198589d 100644 --- a/evaluate.py +++ b/evaluate.py @@ -752,7 +752,10 @@ class Array(parsing.Base): return self.get_exact_index_types(i) except (IndexError, KeyError): pass - return self.follow_values(self._array.values) + + result = list(self.follow_values(self._array.values)) + result += dynamic.check_array_additions(self) + return set(result) def get_exact_index_types(self, index): """ Here the index is an int. Raises IndexError/KeyError """ @@ -1244,9 +1247,7 @@ def follow_path(path, scope, position=None): if isinstance(current, parsing.Array): # This must be an execution, either () or []. if current.type == parsing.Array.LIST: - result = list(scope.get_index_types(current)) - if isinstance(scope, Array): - result += dynamic.check_array_additions(scope) + result = scope.get_index_types(current) elif current.type not in [parsing.Array.DICT]: # Scope must be a class or func - make an instance or execution. debug.dbg('exe', scope) @@ -1264,4 +1265,4 @@ def follow_path(path, scope, position=None): # This is the typical lookup while chaining things. result = imports.strip_imports(get_scopes_for_name(scope, current, position=position)) - return follow_paths(path, result, position=position) + return follow_paths(path, set(result), position=position) diff --git a/imports.py b/imports.py index 26fceca0..c2d9b5c9 100644 --- a/imports.py +++ b/imports.py @@ -91,7 +91,7 @@ class ImportPath(object): if len(rest) > 1 or rest and self.is_like_search: scopes = [] elif rest: - scopes = evaluate.follow_path(iter(rest), scope) + scopes = list(evaluate.follow_path(iter(rest), scope)) else: scopes = [scope] diff --git a/mixin/builtins.py b/mixin/builtins.py index e7a6be63..2c18a00c 100644 --- a/mixin/builtins.py +++ b/mixin/builtins.py @@ -21,6 +21,7 @@ def iter(collection, sentinel=None): for c in collection: yield c + def range(start, stop=None, step=1): return [0] @@ -94,6 +95,7 @@ class list(): def pop(self): return self.__iterable[-1] + class tuple(): def __init__(self, iterable=[]): self.__iterable = [] @@ -107,6 +109,12 @@ class tuple(): def __getitem__(self, y): return self.__iterable[y] + def index(self): + return 1 + + def count(self): + return 1 + class set(): def __init__(self, iterable=[]): @@ -137,12 +145,6 @@ class frozenset(): def copy(self): return self -class tuple(): - def index(self): - return 1 - - def count(self): - return 1 #-------------------------------------------------------- # basic types diff --git a/test/completion/arrays.py b/test/completion/arrays.py index 65644b42..23670d57 100644 --- a/test/completion/arrays.py +++ b/test/completion/arrays.py @@ -162,13 +162,6 @@ dic2 = {'asdf': 3, 'b': 'str'} #? int() dic2[index] -# ----------------- -# chaining -# ----------------- - -#? int() -[tuple()].index() - # ----------------- # __getitem__ # ----------------- diff --git a/test/completion/dynamic.py b/test/completion/dynamic.py index ee842b13..8a12dd0f 100644 --- a/test/completion/dynamic.py +++ b/test/completion/dynamic.py @@ -95,6 +95,7 @@ for a in [1,2]: arr.append(a); arr.append # should not cause an exception +arr.append() # should not cause an exception #? int() arr[10] @@ -110,10 +111,48 @@ arr[10].index() arr = [""] arr.insert(0, 1.0) + +# on exception due to this, please! +arr.insert(0) +arr.insert() + #? float() str() arr[10] +for a in arr: + #? float() str() + a + +for a in list(arr): + #? float() str() + a + +for a in set(arr): + #? float() str() + a # ----------------- -# set.append +# set.add # ----------------- +st = {1.0} +for a in [1,2]: + st.add(a); + +st.add # should not cause an exception +st.add() + +for s in st: + #? float() int() + s + +# ----------------- +# list.extend / set.update +# ----------------- + +arr = [1.0] +arr.extend([1,2,3]) +arr.extend([]) +arr.extend("") # should ignore + +##? float() int() +arr[0]