diff --git a/dynamic.py b/dynamic.py index 9f8d988b..d5d56864 100644 --- a/dynamic.py +++ b/dynamic.py @@ -215,7 +215,7 @@ def _check_array_additions(compare_array, module, is_list): stmt = element.var_args.parent_stmt() if isinstance(stmt, evaluate.InstanceElement): stop_classes = list(stop_classes) + [parsing.Function] - return stmt.get_parent_until(*stop_classes) + return stmt.get_parent_until(stop_classes) search_names = ['append', 'extend', 'insert'] if is_list else \ ['add', 'update'] diff --git a/evaluate.py b/evaluate.py index f97de143..72bd6169 100644 --- a/evaluate.py +++ b/evaluate.py @@ -134,8 +134,8 @@ class Executable(parsing.Base): # The param input array. self.var_args = var_args - def get_parent_until(self, *args): - return self.base.get_parent_until(*args) + def get_parent_until(self, *args, **kwargs): + return self.base.get_parent_until(*args, **kwargs) def parent(self): return self.base.parent() @@ -285,8 +285,8 @@ class InstanceElement(use_metaclass(CachedMetaClass)): par = InstanceElement(self.instance, par) return par - def get_parent_until(self, *classes): - return parsing.Simple.get_parent_until(self, *classes) + def get_parent_until(self, *args, **kwargs): + return parsing.Simple.get_parent_until(self, *args, **kwargs) def get_decorated_func(self): """ Needed because the InstanceElement should not be stripped """ @@ -817,7 +817,7 @@ class Array(use_metaclass(CachedMetaClass, parsing.Base)): """ return builtin.builtin_scope - def get_parent_until(self): + def get_parent_until(self, *args, **kwargs): return builtin.builtin_scope def __getattr__(self, name): @@ -875,26 +875,27 @@ def get_names_for_scope(scope, position=None, star_search=True, The star search option is only here to provide an optimization. Otherwise the whole thing would probably start a little recursive madness. """ - start_scope = scope - in_scope = scope + start_scope = in_scope = scope while scope: # `parsing.Class` is used, because the parent is never `Class`. # Ignore the Flows, because the classes and functions care for that. # InstanceElement of Class is ignored, if it is not the start scope. if not (scope != start_scope and scope.isinstance(parsing.Class) - or scope.isinstance(parsing.Flow)): + or scope.isinstance(parsing.Flow) + or scope.isinstance(Instance) and scope != in_scope): try: yield scope, get_defined_names_for_position(scope, position, in_scope) except StopIteration: raise MultiLevelStopIteration('StopIteration raised somewhere') if scope.isinstance(parsing.ForFlow) and scope.is_list_comp: + # is a list comprehension yield scope, scope.get_set_vars(is_internal_call=True) scope = scope.parent() # This is used, because subscopes (Flow scopes) would distort the # results. - if isinstance(scope, (Function, parsing.Function, Execution)): + if scope and scope.isinstance(Function, parsing.Function, Execution): in_scope = scope # Add star imports. diff --git a/parsing.py b/parsing.py index 97e44565..ce78a97a 100644 --- a/parsing.py +++ b/parsing.py @@ -99,10 +99,14 @@ class Simple(Base): self.parent = lambda: None @Python3Method - def get_parent_until(self, *classes): + def get_parent_until(self, classes=(), reverse=False): """ Takes always the parent, until one class (not a Class) """ + if type(classes) != tuple: + classes = (classes,) scope = self - while not (scope.parent() is None or scope.isinstance(*classes)): + while not scope.parent() is None: + if reverse != scope.isinstance(*classes): + break scope = scope.parent() return scope @@ -455,7 +459,7 @@ class Flow(Scope): n += super(Flow, self).get_set_vars() return n else: - return self.get_parent_until(Class, Function).get_set_vars() + return self.get_parent_until((Class, Function)).get_set_vars() def get_imports(self): i = super(Flow, self).get_imports()