diff --git a/jedi/evaluate/context/iterable.py b/jedi/evaluate/context/iterable.py index 10a4dc2f..2d2ff1bf 100644 --- a/jedi/evaluate/context/iterable.py +++ b/jedi/evaluate/context/iterable.py @@ -293,7 +293,7 @@ class SequenceLiteralContext(Sequence): """Here the index is an int/str. Raises IndexError/KeyError.""" if self.array_type == u'dict': compiled_obj_index = compiled.create_simple_object(self.evaluator, index) - for key, value in self._items(): + for key, value in self.get_tree_entries(): for k in self._defining_context.eval_node(key): if isinstance(k, compiled.CompiledObject) \ and k.execute_operation(compiled_obj_index, u'==').get_safe_value(): @@ -304,7 +304,7 @@ class SequenceLiteralContext(Sequence): return ContextSet(self) else: with reraise_getitem_errors(TypeError, KeyError, IndexError): - node = self._items()[index] + node = self.get_tree_entries()[index] return self._defining_context.eval_node(node) def py__iter__(self): @@ -315,26 +315,30 @@ class SequenceLiteralContext(Sequence): if self.array_type == u'dict': # Get keys. types = ContextSet() - for k, _ in self._items(): + for k, _ in self.get_tree_entries(): types |= self._defining_context.eval_node(k) # We don't know which dict index comes first, therefore always # yield all the types. for _ in types: yield LazyKnownContexts(types) else: - for node in self._items(): + for node in self.get_tree_entries(): yield LazyTreeContext(self._defining_context, node) for addition in check_array_additions(self._defining_context, self): yield addition + def py__len__(self): + # This function is not really used often. It's more of a try. + return len(self.get_tree_entries()) + def _dict_values(self): return ContextSet.from_sets( self._defining_context.eval_node(v) - for k, v in self._items() + for k, v in self.get_tree_entries() ) - def _items(self): + def get_tree_entries(self): c = self.atom.children if self.atom.type in self._TUPLE_LIKE: @@ -366,7 +370,7 @@ class SequenceLiteralContext(Sequence): Returns a generator of tuples like dict.items(), where the key is resolved (as a string) and the values are still lazy contexts. """ - for key_node, value in self._items(): + for key_node, value in self.get_tree_entries(): for key in self._defining_context.eval_node(key_node): if is_string(key): yield key.get_safe_value(), LazyTreeContext(self._defining_context, value) @@ -395,7 +399,7 @@ class DictLiteralContext(SequenceLiteralContext): self.evaluator, u'tuple', (LazyTreeContext(self._defining_context, key_node), LazyTreeContext(self._defining_context, value_node)) - )) for key_node, value_node in self._items() + )) for key_node, value_node in self.get_tree_entries() ] return ContextSet(FakeSequence(self.evaluator, u'list', lazy_contexts)) @@ -488,9 +492,9 @@ class MergedArray(_FakeArray): def py__simple_getitem__(self, index): return ContextSet.from_sets(lazy_context.infer() for lazy_context in self.py__iter__()) - def _items(self): + def get_tree_entries(self): for array in self._arrays: - for a in array._items(): + for a in array.get_tree_entries(): yield a def __len__(self): diff --git a/jedi/evaluate/context/typing.py b/jedi/evaluate/context/typing.py index 264ce992..f47ada32 100644 --- a/jedi/evaluate/context/typing.py +++ b/jedi/evaluate/context/typing.py @@ -7,6 +7,7 @@ from jedi import debug from jedi.evaluate.cache import evaluator_method_cache from jedi.evaluate.compiled import builtin_from_name, CompiledObject from jedi.evaluate.base_context import ContextSet, NO_CONTEXTS, Context, iterator_to_context_set +from jedi.evaluate.lazy_context import LazyKnownContexts from jedi.evaluate.context.iterable import SequenceLiteralContext from jedi.evaluate.arguments import repack_with_argument_clinic, unpack_arglist from jedi.evaluate.utils import to_list @@ -267,12 +268,14 @@ class Tuple(_ContainerBase): # To specify a variable-length tuple of homogeneous type, Tuple[T, ...] # is used. if isinstance(self._index_context, SequenceLiteralContext): - pass + entries = self._index_context.get_tree_entries() + if len(entries) == 2 and entries[1] == '...': + return True return False def py__simple_getitem__(self, index): if self._is_homogenous(): - return self._get_getitem_contexts(0) + return self._get_getitem_contexts(0).execute_annotation() else: if isinstance(index, int): return self._get_getitem_contexts(index).execute_annotation() @@ -280,6 +283,15 @@ class Tuple(_ContainerBase): debug.dbg('The getitem type on Tuple was %s' % index) return NO_CONTEXTS + def py__iter__(self): + if self._is_homogenous(): + while True: + yield LazyKnownContexts(self._get_getitem_contexts(0).execute_annotation()) + else: + if isinstance(self._index_context, SequenceLiteralContext): + for i in range(self._index_context.py__len__()): + yield LazyKnownContexts(self._get_getitem_contexts(i).execute_annotation()) + def py__getitem__(self): if self._is_homogenous(): return self._get_getitem_contexts(0).execute_annotation() diff --git a/test/completion/pep0484_typing.py b/test/completion/pep0484_typing.py index 0417ce3b..7309ded4 100644 --- a/test/completion/pep0484_typing.py +++ b/test/completion/pep0484_typing.py @@ -116,13 +116,9 @@ def tuple(p, q, r): i, s, f = q #? int() i - ##? str() --- TODO fix support for tuple assignment - # https://github.com/davidhalter/jedi/pull/663#issuecomment-172317854 - #? + #? str() s - ##? float() --- TODO fix support for tuple assignment - # https://github.com/davidhalter/jedi/pull/663#issuecomment-172317854 - #? + #? float() f class Key: