mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 22:14:27 +08:00
Fix a recursion error, fixes #1173
This commit is contained in:
@@ -28,8 +28,8 @@ from jedi.evaluate.helpers import is_stdlib_path
|
|||||||
from jedi.evaluate.utils import to_list
|
from jedi.evaluate.utils import to_list
|
||||||
from jedi.parser_utils import get_parent_scope
|
from jedi.parser_utils import get_parent_scope
|
||||||
from jedi.evaluate.context import ModuleContext, instance
|
from jedi.evaluate.context import ModuleContext, instance
|
||||||
from jedi.evaluate.base_context import ContextSet
|
from jedi.evaluate.base_context import ContextSet, NO_CONTEXTS
|
||||||
|
from jedi.evaluate import recursion
|
||||||
|
|
||||||
|
|
||||||
MAX_PARAM_SEARCHES = 20
|
MAX_PARAM_SEARCHES = 20
|
||||||
@@ -39,11 +39,19 @@ class MergedExecutedParams(object):
|
|||||||
"""
|
"""
|
||||||
Simulates being a parameter while actually just being multiple params.
|
Simulates being a parameter while actually just being multiple params.
|
||||||
"""
|
"""
|
||||||
def __init__(self, executed_params):
|
|
||||||
|
def __init__(self, evaluator, executed_params):
|
||||||
|
self.evaluator = evaluator
|
||||||
self._executed_params = executed_params
|
self._executed_params = executed_params
|
||||||
|
|
||||||
def infer(self):
|
def infer(self):
|
||||||
return ContextSet.from_sets(p.infer() for p in self._executed_params)
|
with recursion.execution_allowed(self.evaluator, self) as allowed:
|
||||||
|
# We need to catch recursions that may occur, because an
|
||||||
|
# anonymous functions can create an anonymous parameter that is
|
||||||
|
# more or less self referencing.
|
||||||
|
if allowed:
|
||||||
|
return ContextSet.from_sets(p.infer() for p in self._executed_params)
|
||||||
|
return NO_CONTEXTS
|
||||||
|
|
||||||
|
|
||||||
@debug.increase_indent
|
@debug.increase_indent
|
||||||
@@ -90,15 +98,11 @@ def search_params(evaluator, execution_context, funcdef):
|
|||||||
string_name=string_name,
|
string_name=string_name,
|
||||||
)
|
)
|
||||||
if function_executions:
|
if function_executions:
|
||||||
if len(function_executions) == 1:
|
|
||||||
# Don't need to wrap this one.
|
|
||||||
return function_executions[0].get_params()
|
|
||||||
|
|
||||||
zipped_params = zip(*list(
|
zipped_params = zip(*list(
|
||||||
function_execution.get_params()
|
function_execution.get_params()
|
||||||
for function_execution in function_executions
|
for function_execution in function_executions
|
||||||
))
|
))
|
||||||
params = [MergedExecutedParams(executed_params) for executed_params in zipped_params]
|
params = [MergedExecutedParams(evaluator, executed_params) for executed_params in zipped_params]
|
||||||
# Evaluate the ExecutedParams to types.
|
# Evaluate the ExecutedParams to types.
|
||||||
else:
|
else:
|
||||||
return create_default_params(execution_context, funcdef)
|
return create_default_params(execution_context, funcdef)
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ def execution_allowed(evaluator, node):
|
|||||||
|
|
||||||
if node in pushed_nodes:
|
if node in pushed_nodes:
|
||||||
debug.warning('catched stmt recursion: %s @%s', node,
|
debug.warning('catched stmt recursion: %s @%s', node,
|
||||||
node.start_pos)
|
getattr(node, 'start_pos', None))
|
||||||
yield False
|
yield False
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
@@ -77,14 +77,14 @@ def execution_allowed(evaluator, node):
|
|||||||
|
|
||||||
def execution_recursion_decorator(default=NO_CONTEXTS):
|
def execution_recursion_decorator(default=NO_CONTEXTS):
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
def wrapper(execution, **kwargs):
|
def wrapper(self, **kwargs):
|
||||||
detector = execution.evaluator.execution_recursion_detector
|
detector = self.evaluator.execution_recursion_detector
|
||||||
allowed = detector.push_execution(execution)
|
allowed = detector.push_execution(self)
|
||||||
try:
|
try:
|
||||||
if allowed:
|
if allowed:
|
||||||
result = default
|
result = default
|
||||||
else:
|
else:
|
||||||
result = func(execution, **kwargs)
|
result = func(self, **kwargs)
|
||||||
finally:
|
finally:
|
||||||
detector.pop_execution()
|
detector.pop_execution()
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -76,3 +76,18 @@ class InstanceAttributeIfs:
|
|||||||
InstanceAttributeIfs().a1
|
InstanceAttributeIfs().a1
|
||||||
#? int() str()
|
#? int() str()
|
||||||
InstanceAttributeIfs().a2
|
InstanceAttributeIfs().a2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class A:
|
||||||
|
def a(self, b):
|
||||||
|
for x in [self.a(i) for i in b]:
|
||||||
|
#?
|
||||||
|
x
|
||||||
|
|
||||||
|
class B:
|
||||||
|
def a(self, b):
|
||||||
|
for i in b:
|
||||||
|
for i in self.a(i):
|
||||||
|
#?
|
||||||
|
yield i
|
||||||
|
|||||||
Reference in New Issue
Block a user