Fix: iterators are working smoothly now. Finally tests are passing again.

This commit is contained in:
Dave Halter
2015-12-10 04:37:23 +01:00
parent e23f453a11
commit 9bd6e6c340
7 changed files with 45 additions and 33 deletions

View File

@@ -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:

View File

@@ -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),
} }

View File

@@ -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.

View File

@@ -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:

View File

@@ -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:

View File

@@ -120,7 +120,7 @@ def gen():
a, b = next(gen()) a, b = next(gen())
#? int() #? int()
a a
#? str() #? str() float()
b b

View File

@@ -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]