mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 22:14:27 +08:00
Restructure yield code to make it less error prone.
This commit is contained in:
@@ -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):
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
2
sith.py
2
sith.py
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user