Fix Tuple support

This commit is contained in:
Dave Halter
2018-08-29 10:18:58 +02:00
parent 762d56204f
commit 0edfe86d8b
3 changed files with 30 additions and 18 deletions
+14 -10
View File
@@ -293,7 +293,7 @@ class SequenceLiteralContext(Sequence):
"""Here the index is an int/str. Raises IndexError/KeyError.""" """Here the index is an int/str. Raises IndexError/KeyError."""
if self.array_type == u'dict': if self.array_type == u'dict':
compiled_obj_index = compiled.create_simple_object(self.evaluator, index) 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): for k in self._defining_context.eval_node(key):
if isinstance(k, compiled.CompiledObject) \ if isinstance(k, compiled.CompiledObject) \
and k.execute_operation(compiled_obj_index, u'==').get_safe_value(): and k.execute_operation(compiled_obj_index, u'==').get_safe_value():
@@ -304,7 +304,7 @@ class SequenceLiteralContext(Sequence):
return ContextSet(self) return ContextSet(self)
else: else:
with reraise_getitem_errors(TypeError, KeyError, IndexError): with reraise_getitem_errors(TypeError, KeyError, IndexError):
node = self._items()[index] node = self.get_tree_entries()[index]
return self._defining_context.eval_node(node) return self._defining_context.eval_node(node)
def py__iter__(self): def py__iter__(self):
@@ -315,26 +315,30 @@ class SequenceLiteralContext(Sequence):
if self.array_type == u'dict': if self.array_type == u'dict':
# Get keys. # Get keys.
types = ContextSet() types = ContextSet()
for k, _ in self._items(): for k, _ in self.get_tree_entries():
types |= self._defining_context.eval_node(k) types |= self._defining_context.eval_node(k)
# We don't know which dict index comes first, therefore always # We don't know which dict index comes first, therefore always
# yield all the types. # yield all the types.
for _ in types: for _ in types:
yield LazyKnownContexts(types) yield LazyKnownContexts(types)
else: else:
for node in self._items(): for node in self.get_tree_entries():
yield LazyTreeContext(self._defining_context, node) yield LazyTreeContext(self._defining_context, node)
for addition in check_array_additions(self._defining_context, self): for addition in check_array_additions(self._defining_context, self):
yield addition 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): def _dict_values(self):
return ContextSet.from_sets( return ContextSet.from_sets(
self._defining_context.eval_node(v) 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 c = self.atom.children
if self.atom.type in self._TUPLE_LIKE: 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 Returns a generator of tuples like dict.items(), where the key is
resolved (as a string) and the values are still lazy contexts. 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): for key in self._defining_context.eval_node(key_node):
if is_string(key): if is_string(key):
yield key.get_safe_value(), LazyTreeContext(self._defining_context, value) yield key.get_safe_value(), LazyTreeContext(self._defining_context, value)
@@ -395,7 +399,7 @@ class DictLiteralContext(SequenceLiteralContext):
self.evaluator, u'tuple', self.evaluator, u'tuple',
(LazyTreeContext(self._defining_context, key_node), (LazyTreeContext(self._defining_context, key_node),
LazyTreeContext(self._defining_context, value_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)) return ContextSet(FakeSequence(self.evaluator, u'list', lazy_contexts))
@@ -488,9 +492,9 @@ class MergedArray(_FakeArray):
def py__simple_getitem__(self, index): def py__simple_getitem__(self, index):
return ContextSet.from_sets(lazy_context.infer() for lazy_context in self.py__iter__()) 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 array in self._arrays:
for a in array._items(): for a in array.get_tree_entries():
yield a yield a
def __len__(self): def __len__(self):
+14 -2
View File
@@ -7,6 +7,7 @@ from jedi import debug
from jedi.evaluate.cache import evaluator_method_cache from jedi.evaluate.cache import evaluator_method_cache
from jedi.evaluate.compiled import builtin_from_name, CompiledObject 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.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.context.iterable import SequenceLiteralContext
from jedi.evaluate.arguments import repack_with_argument_clinic, unpack_arglist from jedi.evaluate.arguments import repack_with_argument_clinic, unpack_arglist
from jedi.evaluate.utils import to_list 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, ...] # To specify a variable-length tuple of homogeneous type, Tuple[T, ...]
# is used. # is used.
if isinstance(self._index_context, SequenceLiteralContext): 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 return False
def py__simple_getitem__(self, index): def py__simple_getitem__(self, index):
if self._is_homogenous(): if self._is_homogenous():
return self._get_getitem_contexts(0) return self._get_getitem_contexts(0).execute_annotation()
else: else:
if isinstance(index, int): if isinstance(index, int):
return self._get_getitem_contexts(index).execute_annotation() 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) debug.dbg('The getitem type on Tuple was %s' % index)
return NO_CONTEXTS 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): def py__getitem__(self):
if self._is_homogenous(): if self._is_homogenous():
return self._get_getitem_contexts(0).execute_annotation() return self._get_getitem_contexts(0).execute_annotation()
+2 -6
View File
@@ -116,13 +116,9 @@ def tuple(p, q, r):
i, s, f = q i, s, f = q
#? int() #? int()
i i
##? str() --- TODO fix support for tuple assignment #? str()
# https://github.com/davidhalter/jedi/pull/663#issuecomment-172317854
#?
s s
##? float() --- TODO fix support for tuple assignment #? float()
# https://github.com/davidhalter/jedi/pull/663#issuecomment-172317854
#?
f f
class Key: class Key: