diff --git a/jedi/api.py b/jedi/api.py index 691d259d..72c0376f 100644 --- a/jedi/api.py +++ b/jedi/api.py @@ -27,7 +27,6 @@ from __future__ import with_statement __all__ = ['Script', 'NotFoundError', 'set_debug_function'] import re -import weakref import parsing import dynamic @@ -93,12 +92,12 @@ class Script(object): """ def follow_imports_if_possible(name): # TODO remove this, or move to another place (not used) - par = name.parent() + par = name.parent if isinstance(par, parsing.Import) and not \ isinstance(self.parser.user_stmt, parsing.Import): new = imports.ImportPath(par).follow(is_goto=True) # Only remove the old entry if a new one has been found. - #print par, new, par.parent() + #print par, new, par.parent if new: try: return new @@ -198,7 +197,7 @@ class Script(object): except IndexError: raise NotFoundError() stmt.start_pos = self.pos - stmt.parent = weakref.ref(self.parser.user_scope) + stmt.parent = self.parser.user_scope return stmt def get_definition(self): diff --git a/jedi/api_classes.py b/jedi/api_classes.py index 93fde646..d2a3567a 100644 --- a/jedi/api_classes.py +++ b/jedi/api_classes.py @@ -48,7 +48,7 @@ class BaseOutput(object): self.path.insert(0, par.name) except AttributeError: pass - par = par.parent() + par = par.parent @property def module_name(self): @@ -113,7 +113,7 @@ class Completion(BaseOutput): """ `Completion` objects are returned from `Script.complete`. Providing some useful functions for IDE's. """ def __init__(self, name, needs_dot, like_name_length, base): - super(Completion, self).__init__(name.parent(), name.start_pos) + super(Completion, self).__init__(name.parent, name.start_pos) self.name = name self.needs_dot = needs_dot @@ -154,7 +154,7 @@ class Completion(BaseOutput): def description(self): """ Provides a description of the completion object TODO return value is just __repr__ of some objects, improve! """ - parent = self.name.parent() + parent = self.name.parent if parent is None: return '' t = self.type @@ -175,7 +175,7 @@ class Definition(BaseOutput): `Script.get_definition`. """ def __init__(self, definition): super(Definition, self).__init__(definition, definition.start_pos) - self._def_parent = definition.parent() # just here to limit gc + self._def_parent = definition.parent # just here to limit gc @property def description(self): @@ -185,7 +185,7 @@ class Definition(BaseOutput): if isinstance(d, evaluate.InstanceElement): d = d.var if isinstance(d, evaluate.parsing.Name): - d = d.parent() + d = d.parent if isinstance(d, evaluate.Array): d = 'class ' + d.type diff --git a/jedi/builtin.py b/jedi/builtin.py index dabfc52b..5f1da04f 100644 --- a/jedi/builtin.py +++ b/jedi/builtin.py @@ -463,7 +463,7 @@ class Builtin(object): parser = parsing.PyFuzzyParser(source, None) # needed for caching (because of weakref) module = self.magic_func_module = parser.module - module.parent = lambda: self.scope + module.parent = self.scope typ = evaluate.follow_path(iter(['FunctionType']), module, module) self._magic_function_scope = s = typ.pop() diff --git a/jedi/docstrings.py b/jedi/docstrings.py index cf9ad84e..29bf0d29 100644 --- a/jedi/docstrings.py +++ b/jedi/docstrings.py @@ -7,8 +7,8 @@ import evaluate #@evaluate.memoize_default() # TODO add def follow_param(param): - func = param.parent_function() - #print func, param, param.parent_function() + func = param.parent_function + #print func, param, param.parent_function param_str = search_param_in_docstr(func.docstr, str(param.get_name())) if param_str is not None: diff --git a/jedi/dynamic.py b/jedi/dynamic.py index e06d35c6..7c8a0481 100644 --- a/jedi/dynamic.py +++ b/jedi/dynamic.py @@ -128,7 +128,7 @@ def search_params(param): # no execution means that params cannot be set call_path = c.generate_call_path() pos = c.start_pos - scope = stmt.parent() + scope = stmt.parent evaluate.follow_call_path(call_path, scope, pos) return listener.param_possibilities @@ -136,14 +136,14 @@ def search_params(param): for params in get_posibilities(module, func_name): for p in params: if str(p) == param_name: - result += evaluate.follow_statement(p.parent()) + result += evaluate.follow_statement(p.parent) return result func = param.get_parent_until(parsing.Function) current_module = param.get_parent_until() func_name = str(func.name) - if func_name == '__init__' and isinstance(func.parent(), parsing.Class): - func_name = str(func.parent().name) + if func_name == '__init__' and isinstance(func.parent, parsing.Class): + func_name = str(func.parent.name) # get the param name if param.assignment_details: @@ -177,7 +177,7 @@ def check_array_additions(array): return [] is_list = array._array.type == 'list' - current_module = array._array.parent_stmt().get_parent_until() + current_module = array._array.parent_stmt.get_parent_until() res = _check_array_additions(array, current_module, is_list) return res @@ -209,10 +209,10 @@ def dec(func): global counter element = args[0] if isinstance(element, evaluate.Array): - stmt = element._array.parent_stmt() + stmt = element._array.parent_stmt else: # must be instance - stmt = element.var_args.parent_stmt() + stmt = element.var_args.parent_stmt print(' ' * counter + 'recursion,', stmt) counter += 1 res = func(*args, **kwargs) @@ -249,7 +249,7 @@ def _check_array_additions(compare_array, module, is_list): backtrack_path = iter(call_path[:separate_index]) position = c.start_pos - scope = c.parent_stmt().parent() + scope = c.parent_stmt.parent found = evaluate.follow_call_path(backtrack_path, scope, position) if not compare_array in found: @@ -275,10 +275,10 @@ def _check_array_additions(compare_array, module, is_list): def get_execution_parent(element, *stop_classes): """ Used to get an Instance/Execution parent """ if isinstance(element, evaluate.Array): - stmt = element._array.parent_stmt() + stmt = element._array.parent_stmt else: # must be instance - stmt = element.var_args.parent_stmt() + stmt = element.var_args.parent_stmt if isinstance(stmt, evaluate.InstanceElement): stop_classes = list(stop_classes) + [evaluate.Function] return stmt.get_parent_until(stop_classes) @@ -326,7 +326,7 @@ def check_array_instances(instance): if not settings.dynamic_arrays_instances: return instance.var_args ai = ArrayInstance(instance) - return helpers.generate_param_array([ai], instance.var_args.parent_stmt()) + return helpers.generate_param_array([ai], instance.var_args.parent_stmt) class ArrayInstance(parsing.Base): @@ -358,10 +358,10 @@ class ArrayInstance(parsing.Base): continue items += evaluate.get_iterator_types([array]) - if self.var_args.parent_stmt() is None: + if self.var_args.parent_stmt is None: return [] # generated var_args should not be checked for arrays - module = self.var_args.parent_stmt().get_parent_until() + module = self.var_args.parent_stmt.get_parent_until() is_list = str(self.instance.name) == 'list' items += _check_array_additions(self.instance, module, is_list) return items @@ -378,13 +378,13 @@ def related_names(definitions, search_name, mods): follow.append(call_path[:i + 1]) for f in follow: - follow_res, search = evaluate.goto(call.parent_stmt(), f) + follow_res, search = evaluate.goto(call.parent_stmt, f) follow_res = related_name_add_import_modules(follow_res, search) - #print follow_res, [d.parent() for d in follow_res] + #print follow_res, [d.parent for d in follow_res] # compare to see if they match if any(r in definitions for r in follow_res): - scope = call.parent_stmt() + scope = call.parent_stmt result.append(api_classes.RelatedName(search, scope)) return result @@ -442,8 +442,8 @@ def related_name_add_import_modules(definitions, search_name): """ Adds the modules of the imports """ new = set() for d in definitions: - if isinstance(d.parent(), parsing.Import): - s = imports.ImportPath(d.parent(), direct_resolve=True) + if isinstance(d.parent, parsing.Import): + s = imports.ImportPath(d.parent, direct_resolve=True) try: new.add(s.follow(is_goto=True)[0]) except IndexError: diff --git a/jedi/evaluate.py b/jedi/evaluate.py index 3e65bc09..5b3d2126 100644 --- a/jedi/evaluate.py +++ b/jedi/evaluate.py @@ -17,7 +17,6 @@ from _compatibility import next, property, hasattr, is_py3k, use_metaclass, \ import sys import itertools import copy -import weakref import parsing import debug @@ -136,8 +135,9 @@ class Executable(parsing.Base): def get_parent_until(self, *args, **kwargs): return self.base.get_parent_until(*args, **kwargs) + @property def parent(self): - return self.base.parent() + return self.base.parent class Instance(use_metaclass(CachedMetaClass, Executable)): @@ -215,8 +215,8 @@ class Instance(use_metaclass(CachedMetaClass, Executable)): if args is None: args = helpers.generate_param_array([]) method = self.get_subscope_by_name(name) - if args.parent_stmt() is None: - args.parent_stmt = weakref.ref(method) + if args.parent_stmt is None: + args.parent_stmt = method return Execution(method, args).get_return_types() def get_descriptor_return(self, obj): @@ -287,9 +287,10 @@ class InstanceElement(use_metaclass(CachedMetaClass)): self.var = var self.is_class_var = is_class_var + @property @memoize_default() def parent(self): - par = self.var.parent() + par = self.var.parent if isinstance(par, Class) and par == self.instance.base \ or isinstance(par, parsing.Class) \ and par == self.instance.base.base: @@ -313,9 +314,9 @@ class InstanceElement(use_metaclass(CachedMetaClass)): origin = self.var.get_assignment_calls() # Delete parent, because it isn't used anymore. new = helpers.fast_parent_copy(origin) - par = InstanceElement(self.instance, origin.parent_stmt(), + par = InstanceElement(self.instance, origin.parent_stmt, self.is_class_var) - new.parent_stmt = weakref.ref(par) + new.parent_stmt = par faked_scopes.append(par) faked_scopes.append(new) return new @@ -485,7 +486,7 @@ class Execution(Executable): def get_return_types(self, evaluate_generator=False): """ Get the return types of a function. """ stmts = [] - if self.base.parent() == builtin.Builtin.scope \ + if self.base.parent == builtin.Builtin.scope \ and not isinstance(self.base, (Generator, Array)): func_name = str(self.base.name) @@ -566,7 +567,7 @@ class Execution(Executable): """ Create a param with the original scope (of varargs) as parent. """ - parent_stmt = self.var_args.parent_stmt() + parent_stmt = self.var_args.parent_stmt pos = parent_stmt.start_pos if parent_stmt else None calls = parsing.Array(pos, parsing.Array.NOARRAY, parent_stmt) calls.values = values @@ -574,12 +575,12 @@ class Execution(Executable): calls.type = array_type new_param = copy.copy(param) if parent_stmt is not None: - new_param.parent = weakref.ref(parent_stmt) + new_param.parent = parent_stmt new_param._assignment_calls_calculated = True new_param._assignment_calls = calls new_param.is_generated = True name = copy.copy(param.get_name()) - name.parent = weakref.ref(new_param) + name.parent = new_param faked_scopes.append(new_param) return name @@ -589,7 +590,7 @@ class Execution(Executable): # Care for self -> just exclude it and add the instance start_offset = 1 self_name = copy.copy(self.base.params[0].get_name()) - self_name.parent = weakref.ref(self.base.instance) + self_name.parent = self.base.instance result.append(self_name) param_dict = {} @@ -732,7 +733,7 @@ class Execution(Executable): objects = [] for element in attr: copied = helpers.fast_parent_copy(element) - copied.parent = weakref.ref(self._scope_copy(copied.parent())) + copied.parent = self._scope_copy(copied.parent) if isinstance(copied, parsing.Function): copied = Function(copied) objects.append(copied) @@ -756,9 +757,7 @@ class Execution(Executable): return self else: copied = helpers.fast_parent_copy(scope) - #copied.parent = self._scope_copy(copied.parent()) - copied.parent = weakref.ref(self._scope_copy(copied.parent())) - #copied.parent = weakref.ref(self) + copied.parent = self._scope_copy(copied.parent) faked_scopes.append(copied) return copied except AttributeError: @@ -810,7 +809,7 @@ class Generator(use_metaclass(CachedMetaClass, parsing.Base)): for n in ('close', 'throw') + executes_generator: name = parsing.Name([(n, none_pos)], none_pos, none_pos) if n in executes_generator: - name.parent = weakref.ref(self) + name.parent = self names.append(name) debug.dbg('generator names', names) return names @@ -823,8 +822,9 @@ class Generator(use_metaclass(CachedMetaClass, parsing.Base)): debug.warning('Tried to get array access on a generator', self) return [] + @property def parent(self): - return self.func.parent() + return self.func.parent def __repr__(self): return "<%s of %s>" % (type(self).__name__, self.func) @@ -906,6 +906,7 @@ class Array(use_metaclass(CachedMetaClass, parsing.Base)): def get_contents(self): return self._array + @property def parent(self): """ Return the builtin scope as parent, because the arrays are builtins @@ -998,7 +999,7 @@ def get_names_for_scope(scope, position=None, star_search=True, # is a list comprehension yield scope, scope.get_set_vars(is_internal_call=True) - scope = scope.parent() + scope = scope.parent # This is used, because subscopes (Flow scopes) would distort the # results. if scope and scope.isinstance(Function, parsing.Function, Execution): @@ -1047,14 +1048,14 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False, if r.is_global(): for token_name in r.token_list[1:]: if isinstance(token_name, parsing.Name): - add = get_scopes_for_name(r.parent(), + add = get_scopes_for_name(r.parent, str(token_name)) else: # generated objects are used within executions, but these # objects are in functions, and we have to dynamically # execute first. if isinstance(r, parsing.Param): - func = r.parent() + func = r.parent # Instances are typically faked, if the instance is not # called from outside. Here we check it for __init__ # functions and return. @@ -1124,7 +1125,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False, """ result = [] no_break_scope = False - par = name.parent() + par = name.parent if par.isinstance(parsing.Flow): if par.command == 'for': @@ -1132,8 +1133,8 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False, else: debug.warning('Flow: Why are you here? %s' % par.command) elif par.isinstance(parsing.Param) \ - and par.parent() is not None \ - and par.parent().parent().isinstance(parsing.Class) \ + and par.parent is not None \ + and par.parent.parent.isinstance(parsing.Class) \ and par.position_nr == 0: # This is where self gets added - this happens at another # place, if the var_args are clear. But sometimes the class is @@ -1142,7 +1143,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False, if isinstance(scope, InstanceElement): inst = scope.instance else: - inst = Instance(Class(par.parent().parent())) + inst = Instance(Class(par.parent.parent)) inst.is_generated = True result.append(inst) elif par.isinstance(parsing.Statement): @@ -1188,7 +1189,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False, break_scopes = [] # here is the position stuff happening (sorting of variables) for name in sorted(name_list, key=comparison_func, reverse=True): - p = name.parent().parent() if name.parent() else None + p = name.parent.parent if name.parent else None if isinstance(p, InstanceElement) \ and isinstance(p.var, parsing.Class): p = p.var @@ -1206,7 +1207,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False, # this means that a definition was found and is not e.g. # in if/else. if result and not no_break_scope: - if not name.parent() or p == s: + if not name.parent or p == s: break break_scopes.append(p) @@ -1222,7 +1223,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False, break if flow_scope == nscope: break - flow_scope = flow_scope.parent() + flow_scope = flow_scope.parent flow_scope = nscope if result: break @@ -1427,9 +1428,9 @@ def follow_call_list(call_list): loop = parsing.ForFlow([input], lc.stmt.start_pos, lc.middle, True) if parent is None: - loop.parent = weakref.ref(lc.stmt.parent()) + loop.parent = lc.stmt.parent else: - loop.parent = lambda: parent + loop.parent = parent if isinstance(nested_lc, parsing.ListComprehension): loop = evaluate_list_comprehension(nested_lc, loop) @@ -1450,7 +1451,7 @@ def follow_call_list(call_list): elif isinstance(call, parsing.ListComprehension): loop = evaluate_list_comprehension(call) stmt = copy.copy(call.stmt) - stmt.parent = lambda: loop + stmt.parent = loop # create a for loop which does the same as list # comprehensions result += follow_statement(stmt) @@ -1486,9 +1487,9 @@ def follow_call_list(call_list): def follow_call(call): """ Follow a call is following a function, variable, string, etc. """ - scope = call.parent_stmt().parent() + scope = call.parent_stmt.parent path = call.generate_call_path() - position = call.parent_stmt().start_pos + position = call.parent_stmt.start_pos return follow_call_path(path, scope, position) @@ -1596,7 +1597,7 @@ def goto(stmt, call_path=None): call = arr.get_only_subelement() call_path = list(call.generate_call_path()) - scope = stmt.parent() + scope = stmt.parent pos = stmt.start_pos call_path, search = call_path[:-1], call_path[-1] if call_path: diff --git a/jedi/helpers.py b/jedi/helpers.py index ce09652d..fe1c927e 100644 --- a/jedi/helpers.py +++ b/jedi/helpers.py @@ -1,5 +1,4 @@ import copy -import weakref import contextlib import parsing @@ -164,10 +163,10 @@ def fast_parent_copy(obj): # parent can be a property continue try: - setattr(new_obj, key, weakref.ref(new_elements[value()])) + setattr(new_obj, key, new_elements[value]) except KeyError: pass - elif key == 'parent_stmt': + elif key in ['parent_stmt', 'parent_function']: continue elif isinstance(value, list): setattr(new_obj, key, list_rec(value)) diff --git a/jedi/imports.py b/jedi/imports.py index d23f0208..8f95350b 100644 --- a/jedi/imports.py +++ b/jedi/imports.py @@ -4,7 +4,6 @@ import os import pkgutil import imp import sys -import weakref import time import builtin @@ -84,7 +83,7 @@ class ImportPath(parsing.Base): zero = (0, 0) n = parsing.Name(i.namespace.names[1:], zero, zero, self.import_stmt) new = parsing.Import(zero, zero, n) - new.parent = weakref.ref(parent) + new.parent = parent evaluate.faked_scopes.append(new) debug.dbg('Generated a nested import: %s' % new) return new diff --git a/jedi/keywords.py b/jedi/keywords.py index bea27f4c..8821b500 100644 --- a/jedi/keywords.py +++ b/jedi/keywords.py @@ -36,11 +36,10 @@ class Keyword(object): def __init__(self, name, pos): self.name = name self.start_pos = pos + self.parent = builtin.Builtin.scope - def parent(self): - return builtin.Builtin.scope - - get_parent_until = parent + def get_parent_until(self): + return self.parent @property def names(self): diff --git a/jedi/parsing.py b/jedi/parsing.py index 5494c885..d760053e 100644 --- a/jedi/parsing.py +++ b/jedi/parsing.py @@ -34,7 +34,6 @@ from _compatibility import (next, literal_eval, StringIO, import tokenize import re import keyword -import weakref import os import debug @@ -97,7 +96,7 @@ class Simple(Base): def __init__(self, start_pos, end_pos=(None, None)): self.start_pos = start_pos self.end_pos = end_pos - self.parent = lambda: None + self.parent = None @Python3Method def get_parent_until(self, classes=(), reverse=False, @@ -106,12 +105,12 @@ class Simple(Base): if type(classes) not in (tuple, list): classes = (classes,) scope = self - while not scope.parent() is None: + while scope.parent is not None: if classes and reverse != scope.isinstance(*classes): if include_current: return scope break - scope = scope.parent() + scope = scope.parent return scope def __repr__(self): @@ -142,7 +141,7 @@ class Scope(Simple): self.asserts = [] def add_scope(self, sub, decorators): - sub.parent = weakref.ref(self) + sub.parent = self sub.decorators = decorators for d in decorators: # the parent is the same, because the decorator has not the scope @@ -156,7 +155,7 @@ class Scope(Simple): Used to add a Statement or a Scope. A statement would be a normal command (Statement) or a Scope (Flow). """ - stmt.parent = weakref.ref(self) + stmt.parent = self self.statements.append(stmt) return stmt @@ -166,7 +165,7 @@ class Scope(Simple): def add_import(self, imp): self.imports.append(imp) - imp.parent = weakref.ref(self) + imp.parent = self def get_imports(self): """ Gets also the imports within flow statements """ @@ -330,10 +329,10 @@ class Class(Scope): def __init__(self, name, supers, start_pos, docstr=''): super(Class, self).__init__(start_pos, docstr) self.name = name - name.parent = weakref.ref(self) + name.parent = self self.supers = supers for s in self.supers: - s.parent = weakref.ref(self) + s.parent = self self.decorators = [] def get_code(self, first_indent=False, indention=' '): @@ -365,18 +364,18 @@ class Function(Scope): def __init__(self, name, params, start_pos, annotation): Scope.__init__(self, start_pos) self.name = name - name.parent = weakref.ref(self) + name.parent = self self.params = params for p in params: - p.parent = weakref.ref(self) - p.parent_function = weakref.ref(self) + p.parent = self + p.parent_function = self self.decorators = [] self.returns = [] self.is_generator = False self.listeners = set() # not used here, but in evaluation. if annotation is not None: - annotation.parent = weakref.ref(self) + annotation.parent = self self.annotation = annotation def get_code(self, first_indent=False, indention=' '): @@ -459,14 +458,14 @@ class Flow(Scope): # These have to be statements, because of with, which takes multiple. self.inits = inits for s in inits: - s.parent = weakref.ref(self) + s.parent = self if set_vars is None: self.set_vars = [] else: self.set_vars = set_vars for s in self.set_vars: - s.parent().parent = lambda: self - s.parent = weakref.ref(self) + s.parent.parent = self + s.parent = self @property def parent(self): @@ -573,7 +572,7 @@ class Import(Simple): self.from_ns = from_ns for n in [namespace, alias, from_ns]: if n: - n.parent = weakref.ref(self) + n.parent = self self.star = star self.relative_count = relative_count @@ -609,7 +608,7 @@ class Import(Simple): if len(self.namespace) > 1: o = self.namespace n = Name([(o.names[0], o.start_pos)], o.start_pos, o.end_pos, - parent=o.parent()) + parent=o.parent) return [n] else: return [self.namespace] @@ -656,7 +655,7 @@ class Statement(Simple): self.used_vars = used_vars self.token_list = token_list for s in set_vars + used_funcs + used_vars: - s.parent = weakref.ref(self) + s.parent = self self.set_vars = self._remove_executions_from_set_vars(set_vars) # cache @@ -793,10 +792,10 @@ class Statement(Simple): close_brackets = False else: if close_brackets: - result = result.parent() + result = result.parent close_brackets = False if type(result) == Call: - result = result.parent() + result = result.parent call = Call(tok, c_type, start_pos, parent=result) result.add_to_current_field(call) result = call @@ -804,28 +803,28 @@ class Statement(Simple): level += 1 if is_call_or_close(): result = Array(start_pos, brackets[tok], parent=result) - result = result.parent().add_execution(result) + result = result.parent.add_execution(result) close_brackets = False else: result = Array(start_pos, brackets[tok], parent=result) - result.parent().add_to_current_field(result) + result.parent.add_to_current_field(result) elif tok == ':': while is_call_or_close(): - result = result.parent() + result = result.parent close_brackets = False if result.type == Array.LIST: # [:] lookups result.add_to_current_field(tok) else: result.add_dictionary_key() elif tok == '.': - if close_brackets and result.parent() != top: + if close_brackets and result.parent != top: # only get out of the array, if it is a array execution - result = result.parent() + result = result.parent close_brackets = False is_chain = True elif tok == ',': while is_call_or_close(): - result = result.parent() + result = result.parent close_brackets = False result.add_field((start_pos[0], start_pos[1] + 1)) # important - it cannot be empty anymore @@ -833,7 +832,7 @@ class Statement(Simple): result.type = Array.TUPLE elif tok in [')', '}', ']']: while is_call_or_close(): - result = result.parent() + result = result.parent close_brackets = False if tok == '}' and not len(result): # this is a really special case - empty brackets {} are @@ -844,7 +843,7 @@ class Statement(Simple): close_brackets = True else: while is_call_or_close(): - result = result.parent() + result = result.parent close_brackets = False if tok != '\n': result.add_to_current_field(tok) @@ -876,7 +875,7 @@ class Param(Statement): self.parent_function = None def add_annotation(self, annotation_stmt): - annotation_stmt.parent = weakref.ref(self) + annotation_stmt.parent = self self.annotation_stmt = annotation_stmt def get_name(self): @@ -900,22 +899,22 @@ class Call(Base): self.name = name # parent is not the oposite of next. The parent of c: a = [b.c] would # be an array. - self.parent = weakref.ref(parent) if parent is not None else None + self.parent = parent self.type = type self.start_pos = start_pos self.next = None self.execution = None - self._parent_stmt = weakref.ref(parent_stmt) if parent_stmt else None + self._parent_stmt = parent_stmt @property def parent_stmt(self): if self._parent_stmt is not None: return self._parent_stmt elif self.parent: - return self.parent().parent_stmt + return self.parent.parent_stmt else: - return lambda: None + return None @parent_stmt.setter def parent_stmt(self, value): @@ -935,10 +934,10 @@ class Call(Base): self.execution = call # there might be multiple executions, like a()[0], in that case, they # have the same parent. Otherwise it's not possible to parse proper. - if self.parent().execution == self: + if self.parent.execution == self: call.parent = self.parent else: - call.parent = weakref.ref(self) + call.parent = self return call def generate_call_path(self): @@ -1126,7 +1125,7 @@ class Name(Simple): self.names = tuple(n if isinstance(n, NamePart) else NamePart(*n) for n in names) if parent is not None: - self.parent = weakref.ref(parent) + self.parent = parent def get_code(self): """ Returns the names in a full string format """ @@ -1497,7 +1496,7 @@ class PyFuzzyParser(object): if middle is None: level -= 1 else: - middle.parent = weakref.ref(self.scope) + middle.parent = self.scope debug.warning('list comprehension formatting @%s' % self.start_pos[0]) continue @@ -1506,12 +1505,12 @@ class PyFuzzyParser(object): in_clause, tok = self._parse_statement(added_breaks=b, list_comp=True) if tok not in b or in_clause is None: - middle.parent = weakref.ref(self.scope) + middle.parent = self.scope if in_clause is None: self.gen.push_back(self._current_full) else: - in_clause.parent = weakref.ref(self.scope) - in_clause.parent = weakref.ref(self.scope) + in_clause.parent = self.scope + in_clause.parent = self.scope debug.warning('list comprehension in_clause %s@%s' % (tok, self.start_pos[0])) continue @@ -1539,7 +1538,7 @@ class PyFuzzyParser(object): toks, first_pos, self.end_pos) for s in [st, middle, in_clause]: - s.parent = weakref.ref(self.scope) + s.parent = self.scope tok = ListComprehension(st, middle, in_clause) tok_list.append(tok) if list_comp: @@ -1633,7 +1632,7 @@ class PyFuzzyParser(object): s = self.scope while s is not None: s.end_pos = self.end_pos - s = s.parent() + s = s.parent raise type, tok, self._tokenize_start_pos, self._tokenize_end_pos, \ @@ -1679,7 +1678,7 @@ class PyFuzzyParser(object): token_type, tok = self.next() if self.start_pos[1] <= self.scope.start_pos[1]: self.scope.end_pos = self.start_pos - self.scope = self.scope.parent() + self.scope = self.scope.parent # check again for unindented stuff. this is true for syntax # errors. only check for names, because thats relevant here. If @@ -1688,7 +1687,7 @@ class PyFuzzyParser(object): and (token_type == tokenize.NAME or tok in ['(', '['])\ and self.scope != self.module: self.scope.end_pos = self.start_pos - self.scope = self.scope.parent() + self.scope = self.scope.parent first_pos = self.start_pos if tok == 'def': @@ -1763,14 +1762,14 @@ class PyFuzzyParser(object): debug.warning('syntax err, for flow started @%s', self.start_pos[0]) if statement is not None: - statement.parent = weakref.ref(self.scope) + statement.parent = self.scope if set_stmt is not None: - set_stmt.parent = weakref.ref(self.scope) + set_stmt.parent = self.scope else: debug.warning('syntax err, for flow incomplete @%s', self.start_pos[0]) if set_stmt is not None: - set_stmt.parent = weakref.ref(self.scope) + set_stmt.parent = self.scope elif tok in ['if', 'while', 'try', 'with'] + extended_flow: added_breaks = [] @@ -1811,7 +1810,7 @@ class PyFuzzyParser(object): self.scope = s else: for i in inits: - i.parent = weakref.ref(self.scope) + i.parent = self.scope debug.warning('syntax err, flow started @%s', self.start_pos[0]) # globals @@ -1831,7 +1830,7 @@ class PyFuzzyParser(object): continue elif tok == 'assert': stmt, tok = self._parse_statement() - stmt.parent = weakref.ref(self.scope) + stmt.parent = self.scope self.scope.asserts.append(stmt) # default elif token_type in [tokenize.NAME, tokenize.STRING, diff --git a/test/run.py b/test/run.py index db8b2c2f..be086c29 100755 --- a/test/run.py +++ b/test/run.py @@ -267,7 +267,6 @@ print('\nSummary: (%s fails)' % tests_fail) for s in summary: print(s) - exit_code = 1 if tests_fail else 0 if sys.hexversion < 0x02060000 and tests_fail <= 5: # Python 2.5 has major incompabillities (e.g. no property.setter),