diff --git a/jedi/api/usages.py b/jedi/api/usages.py index e18dc955..6cccbc9a 100644 --- a/jedi/api/usages.py +++ b/jedi/api/usages.py @@ -22,7 +22,7 @@ def usages(evaluator, definitions, search_name, mods): while not stmt.parent.is_scope(): stmt = stmt.parent # New definition, call cannot be a part of stmt - if len(call.name) == 1 and call.execution is None \ + if len(call.name) == 1 and call.next is None \ and call.name in stmt.get_defined_names(): # Class params are not definitions (like function params). They # are super classes, that need to be resolved. diff --git a/jedi/cache.py b/jedi/cache.py index e0533150..b8784c51 100644 --- a/jedi/cache.py +++ b/jedi/cache.py @@ -243,7 +243,7 @@ def save_parser(path, name, parser, pickling=True): class ParserPickling(object): - version = 14 + version = 15 """ Version number (integer) for file system cache. diff --git a/jedi/evaluate/analysis.py b/jedi/evaluate/analysis.py index 64c457ce..4ecfee0d 100644 --- a/jedi/evaluate/analysis.py +++ b/jedi/evaluate/analysis.py @@ -161,7 +161,8 @@ def _check_for_exception_catch(evaluator, jedi_obj, exception, payload=None): assert len(expression_list) == 1 call = expression_list[0] assert isinstance(call, pr.Call) and str(call.name) == 'hasattr' - execution = call.execution + assert call.next_is_execution() + execution = call.next assert execution and len(execution) == 2 # check if the names match diff --git a/jedi/evaluate/finder.py b/jedi/evaluate/finder.py index e01c5d17..7a139046 100644 --- a/jedi/evaluate/finder.py +++ b/jedi/evaluate/finder.py @@ -187,7 +187,7 @@ class NameFinder(object): # Compare start_pos, because names may be different # because of executions. if c.name.start_pos == name.start_pos \ - and c.execution: + and isinstance(c.next, pr.Array): return True return False @@ -391,10 +391,10 @@ def _check_isinstance_type(evaluator, stmt, search_name_part): assert len(expression_list) == 1 call = expression_list[0] assert isinstance(call, pr.Call) and str(call.name) == 'isinstance' - assert bool(call.execution) + assert call.next_is_execution() # isinstance check - isinst = call.execution.values + isinst = call.next.values assert len(isinst) == 2 # has two params obj, classes = [statement.expression_list() for statement in isinst] assert len(obj) == 1 diff --git a/jedi/evaluate/helpers.py b/jedi/evaluate/helpers.py index 71611ce4..0b1d0307 100644 --- a/jedi/evaluate/helpers.py +++ b/jedi/evaluate/helpers.py @@ -96,11 +96,11 @@ def call_signature_array_for_pos(stmt, pos): # Since we need the index, we duplicate efforts (with empty # arrays). if arr.start_pos < pos <= stmt.end_pos: - if arr.type in accepted_types and isinstance(origin_call, pr.Call): + if arr.type in accepted_types and origin_call: return arr, i, origin_call if len(arr) == 0 and arr.start_pos < pos < arr.end_pos: - if arr.type in accepted_types and isinstance(origin_call, pr.Call): + if arr.type in accepted_types and origin_call: return arr, 0, origin_call return None, 0, None @@ -109,8 +109,6 @@ def call_signature_array_for_pos(stmt, pos): if call.next is not None: method = search_array if isinstance(call.next, pr.Array) else search_call tup = method(call.next, pos, origin_call or call) - if not tup[0] and call.execution is not None: - tup = search_array(call.execution, pos, origin_call) return tup if stmt.start_pos >= pos >= stmt.end_pos: @@ -142,11 +140,9 @@ def search_call_signatures(user_stmt, position): # statement. stmt_el = call while isinstance(stmt_el, pr.StatementElement): - if stmt_el.execution == arr: - stmt_el.execution = None + if stmt_el.next == arr: stmt_el.next = None break - stmt_el = stmt_el.next debug.speed('func_call parsed') @@ -178,13 +174,14 @@ def scan_statement_for_calls(stmt, search_name, assignment_details=False): elif isinstance(c, pr.Call): s_new = c while s_new is not None: - n = s_new.name - if isinstance(n, pr.Name) \ - and search_name in [str(x) for x in n.names]: - result.append(c) + if isinstance(s_new, pr.Array): + result += scan_array(s_new, search_name) + else: + n = s_new.name + if isinstance(n, pr.Name) \ + and search_name in [str(x) for x in n.names]: + result.append(c) - if s_new.execution is not None: - result += scan_array(s_new.execution, search_name) s_new = s_new.next elif isinstance(c, pr.ListComprehension): for s in c.stmt, c.middle, c.input: diff --git a/jedi/evaluate/sys_path.py b/jedi/evaluate/sys_path.py index 23ae0d37..24f877cb 100644 --- a/jedi/evaluate/sys_path.py +++ b/jedi/evaluate/sys_path.py @@ -71,17 +71,20 @@ def _paths_from_insert(module_path, exe): """ extract the inserted module path from an "sys.path.insert" statement """ exe_type, exe.type = exe.type, pr.Array.NOARRAY - exe_pop = exe.values.pop(0) - res = _execute_code(module_path, exe.get_code()) - exe.type = exe_type + try: + exe_pop = exe.values.pop(0) + res = _execute_code(module_path, exe.get_code()) + finally: + exe.type = exe_type exe.values.insert(0, exe_pop) return res def _paths_from_call_expression(module_path, call): """ extract the path from either "sys.path.append" or "sys.path.insert" """ - if call.execution is None: + if not call.next_is_execution(): return + n = call.name if not isinstance(n, pr.Name) or len(n.names) != 3: return @@ -89,7 +92,7 @@ def _paths_from_call_expression(module_path, call): if names[:2] != ['sys', 'path']: return cmd = names[2] - exe = call.execution + exe = call.next if cmd == 'insert' and len(exe) == 2: path = _paths_from_insert(module_path, exe) elif cmd == 'append' and len(exe) == 1: @@ -109,10 +112,8 @@ def _check_module(module): if len(expressions) == 1 and isinstance(expressions[0], pr.Call): sys_path.extend( _paths_from_call_expression(module.path, expressions[0]) or []) - elif ( - hasattr(stmt, 'assignment_details') and - len(stmt.assignment_details) == 1 - ): + elif hasattr(stmt, 'assignment_details') \ + and len(stmt.assignment_details) == 1: sys_path.extend(_paths_from_assignment(stmt) or []) return sys_path diff --git a/jedi/parser/representation.py b/jedi/parser/representation.py index 1296bc81..4e2612b1 100644 --- a/jedi/parser/representation.py +++ b/jedi/parser/representation.py @@ -952,7 +952,8 @@ class Statement(Simple, DocstringMixin): # not a set_var. is_execution = False while c: - if Array.is_type(c.execution, Array.TUPLE): + # TODO use StatementElement.next_is_execution + if Array.is_type(c.next, Array.TUPLE): is_execution = True c = c.next if is_execution: @@ -1194,7 +1195,7 @@ class Statement(Simple, DocstringMixin): token_iterator, brackets[tok.string], tok.start_pos ) if result and isinstance(result[-1], StatementElement): - result[-1].set_execution(arr) + result[-1].set_next(arr) else: arr.parent = self result.append(arr) @@ -1264,7 +1265,7 @@ class Param(Statement): class StatementElement(Simple): - __slots__ = ('parent', 'next', 'execution') + __slots__ = ('parent', 'next') def __init__(self, module, start_pos, end_pos, parent): super(StatementElement, self).__init__(module, start_pos, end_pos) @@ -1273,7 +1274,6 @@ class StatementElement(Simple): # be an array. self.parent = parent self.next = None - self.execution = None def set_next(self, call): """ Adds another part of the statement""" @@ -1283,18 +1283,8 @@ class StatementElement(Simple): else: self.next = call - def set_execution(self, call): - """ - An execution is nothing else than brackets, with params in them, which - shows access on the internals of this name. - """ - call.parent = self.parent - if self.next is not None: - self.next.set_execution(call) - elif self.execution is not None: - self.execution.set_execution(call) - else: - self.execution = call + def next_is_execution(self): + return Array.is_type(self.next, Array.TUPLE, Array.NOARRAY) def generate_call_path(self): """ Helps to get the order in which statements are executed. """ @@ -1303,20 +1293,15 @@ class StatementElement(Simple): yield name_part except AttributeError: yield self - if self.execution is not None: - for y in self.execution.generate_call_path(): - yield y if self.next is not None: for y in self.next.generate_call_path(): yield y def get_code(self): - s = '' - if self.execution is not None: - s += self.execution.get_code() if self.next is not None: - s += '.' + self.next.get_code() - return s + s = '.' if isinstance(self, Array) else '' + return s + self.next.get_code() + return '' class Call(StatementElement):