mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 14:04:26 +08:00
Fix the first issue in #1010
Somehow it was still possible with lists to recurse.
This commit is contained in:
@@ -64,7 +64,7 @@ class Context(BaseContext):
|
||||
return self.execute(arguments)
|
||||
|
||||
def iterate(self, contextualized_node=None, is_async=False):
|
||||
debug.dbg('iterate')
|
||||
debug.dbg('iterate %s', self)
|
||||
try:
|
||||
if is_async:
|
||||
iter_method = self.py__aiter__
|
||||
|
||||
@@ -212,6 +212,8 @@ class CompiledInstance(AbstractInstanceContext):
|
||||
super(CompiledInstance, self).__init__(*args, **kwargs)
|
||||
# I don't think that dynamic append lookups should happen here. That
|
||||
# sounds more like something that should go to py__iter__.
|
||||
self._original_var_args = self.var_args
|
||||
|
||||
if self.class_context.name.string_name in ['list', 'set'] \
|
||||
and self.parent_context.get_root_context() == self.evaluator.builtins_module:
|
||||
# compare the module path with the builtin name.
|
||||
@@ -227,6 +229,13 @@ class CompiledInstance(AbstractInstanceContext):
|
||||
else:
|
||||
return super(CompiledInstance, self).create_instance_context(class_context, node)
|
||||
|
||||
def get_first_non_keyword_argument_contexts(self):
|
||||
key, lazy_context = next(self._original_var_args.unpack(), ('', None))
|
||||
if key is not None:
|
||||
return None
|
||||
|
||||
return lazy_context.infer()
|
||||
|
||||
|
||||
class TreeInstance(AbstractInstanceContext):
|
||||
def __init__(self, evaluator, parent_context, class_context, var_args):
|
||||
|
||||
@@ -257,7 +257,21 @@ def eval_atom(context, atom):
|
||||
@_limit_context_infers
|
||||
def eval_expr_stmt(context, stmt, seek_name=None):
|
||||
with recursion.execution_allowed(context.evaluator, stmt) as allowed:
|
||||
if allowed or context.get_root_context() == context.evaluator.builtins_module:
|
||||
# Here we allow list/set to recurse under certain conditions. To make
|
||||
# it possible to resolve stuff like list(set(list(x))), this is
|
||||
# necessary.
|
||||
if not allowed and context.get_root_context() == context.evaluator.builtins_module:
|
||||
try:
|
||||
instance = context.instance
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
if instance.name.string_name in ('list', 'set'):
|
||||
c = instance.get_first_non_keyword_argument_contexts()
|
||||
if instance not in c:
|
||||
allowed = True
|
||||
|
||||
if allowed:
|
||||
return _eval_expr_stmt(context, stmt, seek_name)
|
||||
return NO_CONTEXTS
|
||||
|
||||
|
||||
@@ -401,6 +401,18 @@ for x in [1] + ['']:
|
||||
#? int() str()
|
||||
x
|
||||
|
||||
# -----------------
|
||||
# Potential Recursion Issues
|
||||
# -----------------
|
||||
class X():
|
||||
def y(self):
|
||||
self.a = [1]
|
||||
|
||||
def x(self):
|
||||
self.a = list(self.a)
|
||||
#? int()
|
||||
self.a[0]
|
||||
|
||||
# -----------------
|
||||
# For loops with attribute assignment.
|
||||
# -----------------
|
||||
|
||||
Reference in New Issue
Block a user