mirror of
https://github.com/davidhalter/jedi.git
synced 2026-05-25 17:58:35 +08:00
Fix: py__iter__ in dynamic list/set usages with empy params.
This commit is contained in:
@@ -198,6 +198,17 @@ class CompiledObject(Base):
|
|||||||
pass # self.obj maynot have an __iter__ method.
|
pass # self.obj maynot have an __iter__ method.
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def py__iter__(self):
|
||||||
|
if not hasattr(self.obj, '__iter__'):
|
||||||
|
debug.warning('Tried to call __getitem__ on non-iterable.')
|
||||||
|
return
|
||||||
|
if type(self.obj) not in (str, list, tuple, unicode, bytes, bytearray, dict):
|
||||||
|
# Get rid of side effects, we won't call custom `__getitem__`s.
|
||||||
|
return
|
||||||
|
|
||||||
|
for obj in self.obj:
|
||||||
|
yield set([CompiledObject(obj)])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
# might not exist sometimes (raises AttributeError)
|
# might not exist sometimes (raises AttributeError)
|
||||||
|
|||||||
@@ -298,28 +298,27 @@ class NameFinder(object):
|
|||||||
|
|
||||||
@memoize_default(set(), evaluator_is_first_arg=True)
|
@memoize_default(set(), evaluator_is_first_arg=True)
|
||||||
def _name_to_types(evaluator, name, scope):
|
def _name_to_types(evaluator, name, scope):
|
||||||
types = set()
|
|
||||||
typ = name.get_definition()
|
typ = name.get_definition()
|
||||||
if typ.isinstance(tree.ForStmt, tree.CompFor):
|
if typ.isinstance(tree.ForStmt, tree.CompFor):
|
||||||
container_types = evaluator.eval_element(typ.children[3])
|
container_types = evaluator.eval_element(typ.children[3])
|
||||||
for_types = common.unite(iterable.py__iter__(evaluator, container_types))
|
for_types = common.unite(iterable.py__iter__(evaluator, container_types))
|
||||||
types |= check_tuple_assignments(for_types, name)
|
types = check_tuple_assignments(for_types, name)
|
||||||
elif isinstance(typ, tree.Param):
|
elif isinstance(typ, tree.Param):
|
||||||
types |= _eval_param(evaluator, typ, scope)
|
types = _eval_param(evaluator, typ, scope)
|
||||||
elif typ.isinstance(tree.ExprStmt):
|
elif typ.isinstance(tree.ExprStmt):
|
||||||
types |= _remove_statements(evaluator, typ, name)
|
types = _remove_statements(evaluator, typ, name)
|
||||||
elif typ.isinstance(tree.WithStmt):
|
elif typ.isinstance(tree.WithStmt):
|
||||||
types |= evaluator.eval_element(typ.node_from_name(name))
|
types = evaluator.eval_element(typ.node_from_name(name))
|
||||||
elif isinstance(typ, tree.Import):
|
elif isinstance(typ, tree.Import):
|
||||||
types |= imports.ImportWrapper(evaluator, name).follow()
|
types = imports.ImportWrapper(evaluator, name).follow()
|
||||||
elif isinstance(typ, tree.GlobalStmt):
|
elif isinstance(typ, tree.GlobalStmt):
|
||||||
# TODO theoretically we shouldn't be using search_global here, it
|
# TODO theoretically we shouldn't be using search_global here, it
|
||||||
# doesn't make sense, because it's a local search (for that name)!
|
# doesn't make sense, because it's a local search (for that name)!
|
||||||
# However, globals are not that important and resolving them doesn't
|
# However, globals are not that important and resolving them doesn't
|
||||||
# guarantee correctness in any way, because we don't check for when
|
# guarantee correctness in any way, because we don't check for when
|
||||||
# something is executed.
|
# something is executed.
|
||||||
types |= evaluator.find_types(typ.get_parent_scope(), str(name),
|
types = evaluator.find_types(typ.get_parent_scope(), str(name),
|
||||||
search_global=True)
|
search_global=True)
|
||||||
elif isinstance(typ, tree.TryStmt):
|
elif isinstance(typ, tree.TryStmt):
|
||||||
# TODO an exception can also be a tuple. Check for those.
|
# TODO an exception can also be a tuple. Check for those.
|
||||||
# TODO check for types that are not classes and add it to
|
# TODO check for types that are not classes and add it to
|
||||||
@@ -329,7 +328,7 @@ def _name_to_types(evaluator, name, scope):
|
|||||||
else:
|
else:
|
||||||
if typ.isinstance(er.Function):
|
if typ.isinstance(er.Function):
|
||||||
typ = typ.get_decorated_func()
|
typ = typ.get_decorated_func()
|
||||||
types.add(typ)
|
types = set([typ])
|
||||||
return types
|
return types
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -316,6 +316,8 @@ class Array(IterableWrapper, ArrayMixin):
|
|||||||
for value in iterate:
|
for value in iterate:
|
||||||
yield self._evaluator.eval_element(value)
|
yield self._evaluator.eval_element(value)
|
||||||
|
|
||||||
|
yield check_array_additions(self._evaluator, self)
|
||||||
|
|
||||||
def _values(self):
|
def _values(self):
|
||||||
"""Returns a list of a list of node."""
|
"""Returns a list of a list of node."""
|
||||||
if self.type == 'dict':
|
if self.type == 'dict':
|
||||||
@@ -485,9 +487,15 @@ def unpack_tuple_to_dict(evaluator, types, exprlist):
|
|||||||
|
|
||||||
|
|
||||||
def py__iter__(evaluator, types):
|
def py__iter__(evaluator, types):
|
||||||
|
debug.dbg('py__iter__')
|
||||||
for typ in types:
|
for typ in types:
|
||||||
for result in typ.py__iter__():
|
try:
|
||||||
yield result
|
iter_method = typ.py__iter__
|
||||||
|
except AttributeError:
|
||||||
|
raise NotImplementedError
|
||||||
|
else:
|
||||||
|
for result in iter_method():
|
||||||
|
yield result
|
||||||
|
|
||||||
|
|
||||||
def get_iterator_types(evaluator, element):
|
def get_iterator_types(evaluator, element):
|
||||||
@@ -690,15 +698,18 @@ class _ArrayInstance(IterableWrapper):
|
|||||||
return items
|
return items
|
||||||
|
|
||||||
def py__iter__(self):
|
def py__iter__(self):
|
||||||
_, first_nodes = next(self.var_args.unpack())
|
try:
|
||||||
types = unite(self._evaluator.eval_element(node) for node in first_nodes)
|
_, first_nodes = next(self.var_args.unpack())
|
||||||
|
except StopIteration:
|
||||||
|
types = set()
|
||||||
|
else:
|
||||||
|
types = unite(self._evaluator.eval_element(node) for node in first_nodes)
|
||||||
|
|
||||||
for typ in py__iter__(self._evaluator, types):
|
for types in py__iter__(self._evaluator, types):
|
||||||
yield typ
|
yield types
|
||||||
module = self.var_args.get_parent_until()
|
module = self.var_args.get_parent_until()
|
||||||
is_list = str(self.instance.name) == 'list'
|
is_list = str(self.instance.name) == 'list'
|
||||||
for typ in _check_array_additions(self._evaluator, self.instance, module, is_list):
|
yield _check_array_additions(self._evaluator, self.instance, module, is_list)
|
||||||
yield typ
|
|
||||||
|
|
||||||
|
|
||||||
class Slice(object):
|
class Slice(object):
|
||||||
|
|||||||
Reference in New Issue
Block a user