diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index fcb8797e..9ea011bf 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -355,7 +355,7 @@ class Evaluator(object): new_types = set() if trailer_op == '[': - for trailer_typ in self.eval_element(node): + for trailer_typ in iterable.create_index_types(self, node): new_types |= iterable.py__getitem__(self, types, trailer_typ, trailer_op) else: for typ in types: diff --git a/jedi/evaluate/finder.py b/jedi/evaluate/finder.py index 3f74d964..edaf9e85 100644 --- a/jedi/evaluate/finder.py +++ b/jedi/evaluate/finder.py @@ -548,13 +548,15 @@ def check_tuple_assignments(evaluator, types, name): """ for index, node in name.assignment_indexes(): iterated = iterable.py__iter__(evaluator, types, node) - all_types = set() for _ in range(index + 1): try: types = next(iterated) - all_types |= types except StopIteration: - types = all_types + # We could do this with the default param in next. But this + # would allow this loop to run for a very long time if the + # index number is high. Therefore break if the loop is + # finished. + types = set() break return types diff --git a/jedi/evaluate/iterable.py b/jedi/evaluate/iterable.py index 0732415d..3847a31f 100644 --- a/jedi/evaluate/iterable.py +++ b/jedi/evaluate/iterable.py @@ -245,7 +245,7 @@ class Array(IterableWrapper, ArrayMixin): :param index: A subscriptlist node (or subnode). """ - indexes = create_indexes_or_slices(evaluator, index) + indexes = create_index_types(evaluator, index) lookup_done = False types = set() for index in indexes: @@ -283,7 +283,10 @@ class Array(IterableWrapper, ArrayMixin): raise KeyError('No key found in dictionary %s.' % self) # Can raise an IndexError - return self._evaluator.eval_element(self._items()[index]) + if isinstance(index, slice): + return set([self]) + else: + return self._evaluator.eval_element(self._items()[index]) def iter_content(self): return self.values() @@ -308,16 +311,22 @@ class Array(IterableWrapper, ArrayMixin): """ if self.type == 'dict': # Get keys. - iterate = set(k for k, v in self._items()) + types = set() + for k, _ in self._items(): + types |= self._evaluator.eval_element(k) + # We don't know which dict index comes first, therefore always + # yield all the types. + for _ in types: + yield types else: iterate = self._items() - for value in iterate: - yield self._evaluator.eval_element(value) + for value in iterate: + yield self._evaluator.eval_element(value) - additions = check_array_additions(self._evaluator, self) - if additions: - yield additions + additions = check_array_additions(self._evaluator, self) + if additions: + yield additions def _values(self): """Returns a list of a list of node.""" @@ -472,7 +481,8 @@ def py__iter__(evaluator, types, node=None): iter_method = typ.py__iter__ except AttributeError: if node is not 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) else: for result in iter_method(): yield result @@ -490,11 +500,10 @@ def py__getitem__(evaluator, types, index, node): result = set() # Index handling. - if isinstance(index, compiled.CompiledObject): - pure_index = index.obj - elif not type(index) in (float, int, str, unicode): - pure_index = index - else: + if isinstance(index, (compiled.CompiledObject, Slice)): + index = index.obj + + if type(index) not in (float, int, str, unicode, slice): # If the index is not clearly defined, we have to get all the # possiblities. return py__iter__types(evaluator, types) @@ -504,12 +513,16 @@ def py__getitem__(evaluator, types, index, node): try: getitem = typ.py__getitem__ except AttributeError: - analysis.add(evaluator, 'type-error-not-subscriptable', node) + analysis.add(evaluator, 'type-error-not-subscriptable', node, + message="TypeError: '%s' object is not subscriptable" % typ) else: try: - result |= getitem(pure_index) + result |= getitem(index) except IndexError: return py__iter__types(evaluator, set([typ])) + except KeyError: + # Must be a dict. Lists don't raise IndexErrors. + return typ.values() return result @@ -727,7 +740,10 @@ class Slice(object): return slice(None, None, None) -def create_indexes_or_slices(evaluator, index): +def create_index_types(evaluator, index): + """ + Handles slices in subscript nodes. + """ if tree.is_node(index, 'subscript'): # subscript is a slice operation. start, stop, step = None, None, None result = [] diff --git a/test/completion/arrays.py b/test/completion/arrays.py index 720d2ec9..14ef990b 100644 --- a/test/completion/arrays.py +++ b/test/completion/arrays.py @@ -216,6 +216,8 @@ a a, b = {1: 'x', 2.0: 1j} #? int() float() a +#? int() float() +b def f():