1
0
forked from VimPlug/jedi

Restructure yield code to make it less error prone.

This commit is contained in:
Dave Halter
2017-01-07 12:43:15 +01:00
parent 1f15ee8bc7
commit d3c437e891
3 changed files with 23 additions and 18 deletions

View File

@@ -27,7 +27,7 @@ def execution_allowed(evaluator, node):
pushed_nodes = evaluator.recursion_detector.pushed_nodes pushed_nodes = evaluator.recursion_detector.pushed_nodes
if node in pushed_nodes: if node in pushed_nodes:
debug.warning('catched stmt recursion: %s against %s @%s', node, debug.warning('catched stmt recursion: %s @%s', node,
node.start_pos) node.start_pos)
yield False yield False
else: else:
@@ -36,17 +36,21 @@ def execution_allowed(evaluator, node):
pushed_nodes.pop() pushed_nodes.pop()
def execution_recursion_decorator(func): def execution_recursion_decorator(default=set()):
def run(execution, **kwargs): def decorator(func):
detector = execution.evaluator.execution_recursion_detector def wrapper(execution, **kwargs):
if detector.push_execution(execution): detector = execution.evaluator.execution_recursion_detector
result = set() allowed = detector.push_execution(execution)
else: try:
result = func(execution, **kwargs) if allowed:
detector.pop_execution() result = default
return result else:
result = func(execution, **kwargs)
return run finally:
detector.pop_execution()
return result
return wrapper
return decorator
class ExecutionRecursionDetector(object): class ExecutionRecursionDetector(object):

View File

@@ -295,7 +295,7 @@ class FunctionExecutionContext(Executed):
self.tree_node = function_context.tree_node self.tree_node = function_context.tree_node
@memoize_default(default=set()) @memoize_default(default=set())
@recursion.execution_recursion_decorator @recursion.execution_recursion_decorator()
def get_return_values(self, check_yields=False): def get_return_values(self, check_yields=False):
funcdef = self.tree_node funcdef = self.tree_node
if funcdef.type == 'lambda': if funcdef.type == 'lambda':
@@ -321,8 +321,6 @@ class FunctionExecutionContext(Executed):
if check is flow_analysis.REACHABLE: if check is flow_analysis.REACHABLE:
debug.dbg('Return reachable: %s', r) debug.dbg('Return reachable: %s', r)
break break
if check_yields:
return context.get_merged_lazy_context(list(types))
return types return types
def _eval_yield(self, yield_expr): def _eval_yield(self, yield_expr):
@@ -334,7 +332,7 @@ class FunctionExecutionContext(Executed):
else: else:
yield context.LazyTreeContext(self, node) yield context.LazyTreeContext(self, node)
@recursion.execution_recursion_decorator @recursion.execution_recursion_decorator(default=iter([]))
def get_yield_values(self): def get_yield_values(self):
for_parents = [(y, tree.search_ancestor(y, ('for_stmt', 'funcdef', for_parents = [(y, tree.search_ancestor(y, ('for_stmt', 'funcdef',
'while_stmt', 'if_stmt'))) 'while_stmt', 'if_stmt')))
@@ -358,7 +356,9 @@ class FunctionExecutionContext(Executed):
elif for_stmt == self.tree_node: elif for_stmt == self.tree_node:
yields_order.append((None, [yield_])) yields_order.append((None, [yield_]))
else: else:
yield self.get_return_values(check_yields=True) types = self.get_return_values(check_yields=True)
if types:
yield context.get_merged_lazy_context(list(types))
return return
last_for_stmt = for_stmt last_for_stmt = for_stmt
@@ -373,6 +373,7 @@ class FunctionExecutionContext(Executed):
input_node = for_stmt.get_input_node() input_node = for_stmt.get_input_node()
for_types = self.eval_node(input_node) for_types = self.eval_node(input_node)
ordered = iterable.py__iter__(evaluator, for_types, input_node) ordered = iterable.py__iter__(evaluator, for_types, input_node)
ordered = list(ordered)
for lazy_context in ordered: for lazy_context in ordered:
dct = {str(for_stmt.children[1]): lazy_context.infer()} dct = {str(for_stmt.children[1]): lazy_context.infer()}
with helpers.predefine_names(self, for_stmt, dct): with helpers.predefine_names(self, for_stmt, dct):

View File

@@ -173,7 +173,7 @@ class TestCase(object):
self.show_location(completion.line, completion.column) self.show_location(completion.line, completion.column)
def show_errors(self): def show_errors(self):
print(self.traceback) sys.stderr.write(self.traceback)
print(("Error with running Script(...).{operation}() with\n" print(("Error with running Script(...).{operation}() with\n"
"\tpath: {path}\n" "\tpath: {path}\n"
"\tline: {line}\n" "\tline: {line}\n"