mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 14:04:26 +08:00
Fix: iterators are working smoothly now. Finally tests are passing again.
This commit is contained in:
@@ -631,6 +631,7 @@ class Interpreter(Script):
|
|||||||
if isinstance(user_stmt, tree.Import) or not is_simple_path:
|
if isinstance(user_stmt, tree.Import) or not is_simple_path:
|
||||||
return super(Interpreter, self)._simple_complete(path, dot, like)
|
return super(Interpreter, self)._simple_complete(path, dot, like)
|
||||||
else:
|
else:
|
||||||
|
# TODO Remove this branch? The above branch should be fast enough IMO.
|
||||||
class NamespaceModule(object):
|
class NamespaceModule(object):
|
||||||
def __getattr__(_, name):
|
def __getattr__(_, name):
|
||||||
for n in self.namespaces:
|
for n in self.namespaces:
|
||||||
|
|||||||
@@ -10,16 +10,15 @@ CODES = {
|
|||||||
'attribute-error': (1, AttributeError, 'Potential AttributeError.'),
|
'attribute-error': (1, AttributeError, 'Potential AttributeError.'),
|
||||||
'name-error': (2, NameError, 'Potential NameError.'),
|
'name-error': (2, NameError, 'Potential NameError.'),
|
||||||
'import-error': (3, ImportError, 'Potential ImportError.'),
|
'import-error': (3, ImportError, 'Potential ImportError.'),
|
||||||
'type-error-generator': (4, TypeError, "TypeError: 'generator' object is not subscriptable."),
|
'type-error-too-many-arguments': (4, TypeError, None),
|
||||||
'type-error-too-many-arguments': (5, TypeError, None),
|
'type-error-too-few-arguments': (5, TypeError, None),
|
||||||
'type-error-too-few-arguments': (6, TypeError, None),
|
'type-error-keyword-argument': (6, TypeError, None),
|
||||||
'type-error-keyword-argument': (7, TypeError, None),
|
'type-error-multiple-values': (7, TypeError, None),
|
||||||
'type-error-multiple-values': (8, TypeError, None),
|
'type-error-star-star': (8, TypeError, None),
|
||||||
'type-error-star-star': (9, TypeError, None),
|
'type-error-star': (9, TypeError, None),
|
||||||
'type-error-star': (10, TypeError, None),
|
'type-error-operation': (10, TypeError, None),
|
||||||
'type-error-operation': (11, TypeError, None),
|
'type-error-not-iterable': (11, TypeError, None),
|
||||||
'type-error-not-iterable': (12, TypeError, None),
|
'type-error-isinstance': (12, TypeError, None),
|
||||||
'type-error-isinstance': (13, TypeError, None),
|
|
||||||
'type-error-not-subscriptable': (13, TypeError, None),
|
'type-error-not-subscriptable': (13, TypeError, None),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -250,6 +250,7 @@ class NameFinder(object):
|
|||||||
def _names_to_types(self, names, search_global):
|
def _names_to_types(self, names, search_global):
|
||||||
types = set()
|
types = set()
|
||||||
|
|
||||||
|
debug.warning('start nt %s', names)
|
||||||
# Add isinstance and other if/assert knowledge.
|
# Add isinstance and other if/assert knowledge.
|
||||||
if isinstance(self.name_str, tree.Name):
|
if isinstance(self.name_str, tree.Name):
|
||||||
# Ignore FunctionExecution parents for now.
|
# Ignore FunctionExecution parents for now.
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ It is important to note that:
|
|||||||
from jedi.common import unite, ignored, safe_property
|
from jedi.common import unite, ignored, safe_property
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi import settings
|
from jedi import settings
|
||||||
from jedi._compatibility import use_metaclass, unicode
|
from jedi._compatibility import use_metaclass, unicode, zip_longest
|
||||||
from jedi.parser import tree
|
from jedi.parser import tree
|
||||||
from jedi.evaluate import compiled
|
from jedi.evaluate import compiled
|
||||||
from jedi.evaluate import helpers
|
from jedi.evaluate import helpers
|
||||||
@@ -51,14 +51,12 @@ class GeneratorMixin(object):
|
|||||||
dct[name.value] = [name]
|
dct[name.value] = [name]
|
||||||
yield dct
|
yield dct
|
||||||
|
|
||||||
def get_index_types(self, evaluator, index_array):
|
|
||||||
#debug.warning('Tried to get array access on a generator: %s', self)
|
|
||||||
analysis.add(self._evaluator, 'type-error-generator', index_array)
|
|
||||||
return set()
|
|
||||||
|
|
||||||
def py__bool__(self):
|
def py__bool__(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def get_index_types(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def py__class__(self, evaluator):
|
def py__class__(self, evaluator):
|
||||||
gen_obj = compiled.get_special_object(self._evaluator, 'GENERATOR_OBJECT')
|
gen_obj = compiled.get_special_object(self._evaluator, 'GENERATOR_OBJECT')
|
||||||
return gen_obj.py__class__(evaluator)
|
return gen_obj.py__class__(evaluator)
|
||||||
@@ -76,6 +74,7 @@ class Generator(use_metaclass(CachedMetaClass, IterableWrapper, GeneratorMixin))
|
|||||||
""" returns the content of __iter__ """
|
""" returns the content of __iter__ """
|
||||||
# Directly execute it, because with a normal call to py__call__ a
|
# Directly execute it, because with a normal call to py__call__ a
|
||||||
# Generator will be returned.
|
# Generator will be returned.
|
||||||
|
raise NotImplementedError
|
||||||
from jedi.evaluate.representation import FunctionExecution
|
from jedi.evaluate.representation import FunctionExecution
|
||||||
f = FunctionExecution(self._evaluator, self.func, self.var_args)
|
f = FunctionExecution(self._evaluator, self.func, self.var_args)
|
||||||
return f.get_return_types(check_yields=True)
|
return f.get_return_types(check_yields=True)
|
||||||
@@ -90,6 +89,7 @@ class Generator(use_metaclass(CachedMetaClass, IterableWrapper, GeneratorMixin))
|
|||||||
Exact lookups are used for tuple lookups, which are perfectly fine if
|
Exact lookups are used for tuple lookups, which are perfectly fine if
|
||||||
used with generators.
|
used with generators.
|
||||||
"""
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
return list(self.py__iter__())[index]
|
return list(self.py__iter__())[index]
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
@@ -112,7 +112,7 @@ class GeneratorMethod(IterableWrapper):
|
|||||||
|
|
||||||
def py__call__(self, evaluator, params):
|
def py__call__(self, evaluator, params):
|
||||||
# TODO add TypeError if params are given.
|
# TODO add TypeError if params are given.
|
||||||
return self._generator.iter_content()
|
return unite(self._generator.py__iter__())
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
return getattr(self._builtin_func, name)
|
return getattr(self._builtin_func, name)
|
||||||
@@ -152,27 +152,27 @@ class Comprehension(IterableWrapper):
|
|||||||
return helpers.deep_ast_copy(self._get_comprehension().children[0], parent=last_comp)
|
return helpers.deep_ast_copy(self._get_comprehension().children[0], parent=last_comp)
|
||||||
|
|
||||||
def py__iter__(self):
|
def py__iter__(self):
|
||||||
def nested(input_types, comp_fors, node):
|
def nested(comp_fors):
|
||||||
iterated = py__iter__(evaluator, input_types, node)
|
|
||||||
comp_for = comp_fors[0]
|
comp_for = comp_fors[0]
|
||||||
|
input_node = comp_for.children[3]
|
||||||
|
input_types = evaluator.eval_element(input_node)
|
||||||
|
|
||||||
|
iterated = py__iter__(evaluator, input_types, input_node)
|
||||||
exprlist = comp_for.children[1]
|
exprlist = comp_for.children[1]
|
||||||
for types in iterated:
|
for types in iterated:
|
||||||
evaluator.predefined_if_name_dict_dict[comp_for] = \
|
evaluator.predefined_if_name_dict_dict[comp_for] = \
|
||||||
unpack_tuple_to_dict(evaluator, types, exprlist)
|
unpack_tuple_to_dict(evaluator, types, exprlist)
|
||||||
try:
|
try:
|
||||||
if len(comp_fors) > 1:
|
for result in nested(comp_fors[1:]):
|
||||||
for result in nested(types, comp_fors[1:], exprlist):
|
|
||||||
yield result
|
yield result
|
||||||
else:
|
except IndexError:
|
||||||
yield evaluator.eval_element(self.eval_node())
|
yield evaluator.eval_element(self.eval_node())
|
||||||
finally:
|
finally:
|
||||||
del evaluator.predefined_if_name_dict_dict[comp_for]
|
del evaluator.predefined_if_name_dict_dict[comp_for]
|
||||||
|
|
||||||
evaluator = self._evaluator
|
evaluator = self._evaluator
|
||||||
comp_fors = list(self._get_comp_for().get_comp_fors())
|
comp_fors = list(self._get_comp_for().get_comp_fors())
|
||||||
input_node = comp_fors[0].children[3]
|
for result in nested(comp_fors):
|
||||||
input_types = evaluator.eval_element(input_node)
|
|
||||||
for result in nested(input_types, comp_fors, input_node):
|
|
||||||
yield result
|
yield result
|
||||||
|
|
||||||
def get_exact_index_types(self, index):
|
def get_exact_index_types(self, index):
|
||||||
@@ -203,9 +203,11 @@ class ListComprehension(Comprehension, ArrayMixin):
|
|||||||
type = 'list'
|
type = 'list'
|
||||||
|
|
||||||
def get_index_types(self, evaluator, index):
|
def get_index_types(self, evaluator, index):
|
||||||
|
raise NotImplementedError
|
||||||
return self.iter_content()
|
return self.iter_content()
|
||||||
|
|
||||||
def iter_content(self):
|
def iter_content(self):
|
||||||
|
raise NotImplementedError
|
||||||
return self._evaluator.eval_element(self.eval_node())
|
return self._evaluator.eval_element(self.eval_node())
|
||||||
|
|
||||||
def py__getitem__(self, index):
|
def py__getitem__(self, index):
|
||||||
@@ -219,6 +221,7 @@ class ListComprehension(Comprehension, ArrayMixin):
|
|||||||
|
|
||||||
class GeneratorComprehension(Comprehension, GeneratorMixin):
|
class GeneratorComprehension(Comprehension, GeneratorMixin):
|
||||||
def iter_content(self):
|
def iter_content(self):
|
||||||
|
raise NotImplementedError
|
||||||
return self._evaluator.eval_element(self.eval_node())
|
return self._evaluator.eval_element(self.eval_node())
|
||||||
|
|
||||||
|
|
||||||
@@ -251,6 +254,7 @@ class Array(IterableWrapper, ArrayMixin):
|
|||||||
|
|
||||||
:param index: A subscriptlist node (or subnode).
|
:param index: A subscriptlist node (or subnode).
|
||||||
"""
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
indexes = create_index_types(evaluator, index)
|
indexes = create_index_types(evaluator, index)
|
||||||
lookup_done = False
|
lookup_done = False
|
||||||
types = set()
|
types = set()
|
||||||
@@ -296,6 +300,7 @@ class Array(IterableWrapper, ArrayMixin):
|
|||||||
return self._evaluator.eval_element(self._items()[index])
|
return self._evaluator.eval_element(self._items()[index])
|
||||||
|
|
||||||
def iter_content(self):
|
def iter_content(self):
|
||||||
|
raise NotImplementedError
|
||||||
return self.values()
|
return self.values()
|
||||||
|
|
||||||
@safe_property
|
@safe_property
|
||||||
@@ -489,6 +494,7 @@ def unpack_tuple_to_dict(evaluator, types, exprlist):
|
|||||||
|
|
||||||
def py__iter__(evaluator, types, node=None):
|
def py__iter__(evaluator, types, node=None):
|
||||||
debug.dbg('py__iter__')
|
debug.dbg('py__iter__')
|
||||||
|
type_iters = []
|
||||||
for typ in types:
|
for typ in types:
|
||||||
try:
|
try:
|
||||||
iter_method = typ.py__iter__
|
iter_method = typ.py__iter__
|
||||||
@@ -497,8 +503,12 @@ def py__iter__(evaluator, types, node=None):
|
|||||||
analysis.add(evaluator, 'type-error-not-iterable', node,
|
analysis.add(evaluator, 'type-error-not-iterable', node,
|
||||||
message="TypeError: '%s' object is not iterable" % typ)
|
message="TypeError: '%s' object is not iterable" % typ)
|
||||||
else:
|
else:
|
||||||
for result in iter_method():
|
type_iters.append(iter_method())
|
||||||
yield result
|
#for result in iter_method():
|
||||||
|
#yield result
|
||||||
|
|
||||||
|
for t in zip_longest(*type_iters, fillvalue=set()):
|
||||||
|
yield unite(t)
|
||||||
|
|
||||||
|
|
||||||
def py__iter__types(evaluator, types, node=None):
|
def py__iter__types(evaluator, types, node=None):
|
||||||
@@ -696,6 +706,7 @@ class _ArrayInstance(IterableWrapper):
|
|||||||
The index is here just ignored, because of all the appends, etc.
|
The index is here just ignored, because of all the appends, etc.
|
||||||
lists/sets are too complicated too handle that.
|
lists/sets are too complicated too handle that.
|
||||||
"""
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
items = set()
|
items = set()
|
||||||
for key, nodes in self.var_args.unpack():
|
for key, nodes in self.var_args.unpack():
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
|
|||||||
@@ -383,8 +383,8 @@ def _iterate_star_args(evaluator, array, input_node, func=None):
|
|||||||
for field_stmt in array: # yield from plz!
|
for field_stmt in array: # yield from plz!
|
||||||
yield field_stmt
|
yield field_stmt
|
||||||
elif isinstance(array, iterable.Generator):
|
elif isinstance(array, iterable.Generator):
|
||||||
for field_stmt in array.iter_content():
|
for types in array.py__iter__():
|
||||||
yield iterable.AlreadyEvaluated([field_stmt])
|
yield iterable.AlreadyEvaluated(types)
|
||||||
elif isinstance(array, Instance) and array.name.get_code() == 'tuple':
|
elif isinstance(array, Instance) and array.name.get_code() == 'tuple':
|
||||||
debug.warning('Ignored a tuple *args input %s' % array)
|
debug.warning('Ignored a tuple *args input %s' % array)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ def gen():
|
|||||||
a, b = next(gen())
|
a, b = next(gen())
|
||||||
#? int()
|
#? int()
|
||||||
a
|
a
|
||||||
#? str()
|
#? str() float()
|
||||||
b
|
b
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
def generator():
|
def generator():
|
||||||
yield 1
|
yield 1
|
||||||
|
|
||||||
#! 12 type-error-generator
|
#! 11 type-error-not-subscriptable
|
||||||
generator()[0]
|
generator()[0]
|
||||||
|
|
||||||
list(generator())[0]
|
list(generator())[0]
|
||||||
|
|||||||
Reference in New Issue
Block a user