mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-09 23:34:45 +08:00
Improve dict comprehension support.
This commit is contained in:
@@ -38,7 +38,7 @@ class IterableWrapper(tree.Base):
|
|||||||
@memoize_default()
|
@memoize_default()
|
||||||
def _get_names_dict(self, names_dict):
|
def _get_names_dict(self, names_dict):
|
||||||
try:
|
try:
|
||||||
builtin_methods = self._builtin_methods
|
builtin_methods = self.builtin_methods
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return names_dict
|
return names_dict
|
||||||
|
|
||||||
@@ -71,10 +71,10 @@ class BuiltinMethod(IterableWrapper):
|
|||||||
|
|
||||||
|
|
||||||
def has_builtin_methods(cls):
|
def has_builtin_methods(cls):
|
||||||
cls._builtin_methods = {}
|
cls.builtin_methods = {}
|
||||||
for func in cls.__dict__.values():
|
for func in cls.__dict__.values():
|
||||||
try:
|
try:
|
||||||
cls._builtin_methods.update(func.registered_builtin_methods)
|
cls.builtin_methods.update(func.registered_builtin_methods)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
return cls
|
return cls
|
||||||
@@ -166,7 +166,7 @@ class Comprehension(IterableWrapper):
|
|||||||
return self._get_comprehension().children[1]
|
return self._get_comprehension().children[1]
|
||||||
|
|
||||||
@memoize_default()
|
@memoize_default()
|
||||||
def eval_node(self):
|
def _eval_node(self, index=0):
|
||||||
"""
|
"""
|
||||||
The first part `x + 1` of the list comprehension:
|
The first part `x + 1` of the list comprehension:
|
||||||
|
|
||||||
@@ -175,9 +175,10 @@ class Comprehension(IterableWrapper):
|
|||||||
comp_for = self._get_comp_for()
|
comp_for = self._get_comp_for()
|
||||||
# For nested comprehensions we need to search the last one.
|
# For nested comprehensions we need to search the last one.
|
||||||
last_comp = list(comp_for.get_comp_fors())[-1]
|
last_comp = list(comp_for.get_comp_fors())[-1]
|
||||||
return helpers.deep_ast_copy(self._get_comprehension().children[0], parent=last_comp)
|
return helpers.deep_ast_copy(self._get_comprehension().children[index], parent=last_comp)
|
||||||
|
|
||||||
def py__iter__(self):
|
@memoize_default()
|
||||||
|
def _iterate(self):
|
||||||
def nested(comp_fors):
|
def nested(comp_fors):
|
||||||
comp_for = comp_fors[0]
|
comp_for = comp_fors[0]
|
||||||
input_node = comp_for.children[3]
|
input_node = comp_for.children[3]
|
||||||
@@ -192,7 +193,11 @@ class Comprehension(IterableWrapper):
|
|||||||
for result in nested(comp_fors[1:]):
|
for result in nested(comp_fors[1:]):
|
||||||
yield result
|
yield result
|
||||||
except IndexError:
|
except IndexError:
|
||||||
yield evaluator.eval_element(self.eval_node())
|
iterated = evaluator.eval_element(self._eval_node())
|
||||||
|
if self.type == 'dict':
|
||||||
|
yield iterated, evaluator.eval_element(self._eval_node(2))
|
||||||
|
else:
|
||||||
|
yield iterated
|
||||||
finally:
|
finally:
|
||||||
del evaluator.predefined_if_name_dict_dict[comp_for]
|
del evaluator.predefined_if_name_dict_dict[comp_for]
|
||||||
|
|
||||||
@@ -201,10 +206,14 @@ class Comprehension(IterableWrapper):
|
|||||||
for result in nested(comp_fors):
|
for result in nested(comp_fors):
|
||||||
yield result
|
yield result
|
||||||
|
|
||||||
|
def py__iter__(self):
|
||||||
|
return self._iterate()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s of %s>" % (type(self).__name__, self._atom)
|
return "<%s of %s>" % (type(self).__name__, self._atom)
|
||||||
|
|
||||||
|
|
||||||
|
@has_builtin_methods
|
||||||
class ArrayMixin(object):
|
class ArrayMixin(object):
|
||||||
@memoize_default()
|
@memoize_default()
|
||||||
def names_dicts(self, search_global=False): # Always False.
|
def names_dicts(self, search_global=False): # Always False.
|
||||||
@@ -213,7 +222,7 @@ class ArrayMixin(object):
|
|||||||
# builtins only have one class -> [0]
|
# builtins only have one class -> [0]
|
||||||
scopes = self._evaluator.execute_evaluated(scope, self)
|
scopes = self._evaluator.execute_evaluated(scope, self)
|
||||||
names_dicts = list(scopes)[0].names_dicts(search_global)
|
names_dicts = list(scopes)[0].names_dicts(search_global)
|
||||||
yield names_dicts[0]
|
#yield names_dicts[0]
|
||||||
yield self._get_names_dict(names_dicts[1])
|
yield self._get_names_dict(names_dicts[1])
|
||||||
|
|
||||||
def py__bool__(self):
|
def py__bool__(self):
|
||||||
@@ -230,6 +239,23 @@ class ArrayMixin(object):
|
|||||||
def name(self):
|
def name(self):
|
||||||
return FakeSequence(self._evaluator, [], self.type).name
|
return FakeSequence(self._evaluator, [], self.type).name
|
||||||
|
|
||||||
|
@memoize_default()
|
||||||
|
def dict_values(self):
|
||||||
|
return unite(self._evaluator.eval_element(v) for k, v in self._items())
|
||||||
|
|
||||||
|
@register_builtin_method('values', type='dict')
|
||||||
|
def _imitate_values(self):
|
||||||
|
items = self.dict_values()
|
||||||
|
return create_evaluated_sequence_set(self._evaluator, items, type='list')
|
||||||
|
#return set([FakeSequence(self._evaluator, [AlreadyEvaluated(items)], 'tuple')])
|
||||||
|
|
||||||
|
@register_builtin_method('items', type='dict')
|
||||||
|
def _imitate_items(self):
|
||||||
|
items = [set([FakeSequence(self._evaluator, (k, v), 'tuple')])
|
||||||
|
for k, v in self._items()]
|
||||||
|
|
||||||
|
return create_evaluated_sequence_set(self._evaluator, *items, type='list')
|
||||||
|
|
||||||
|
|
||||||
class ListComprehension(Comprehension, ArrayMixin):
|
class ListComprehension(Comprehension, ArrayMixin):
|
||||||
type = 'list'
|
type = 'list'
|
||||||
@@ -243,18 +269,39 @@ class SetComprehension(Comprehension, ArrayMixin):
|
|||||||
type = 'set'
|
type = 'set'
|
||||||
|
|
||||||
|
|
||||||
|
@has_builtin_methods
|
||||||
class DictComprehension(Comprehension, ArrayMixin):
|
class DictComprehension(Comprehension, ArrayMixin):
|
||||||
type = 'dict'
|
type = 'dict'
|
||||||
|
|
||||||
def _get_comp_for(self):
|
def _get_comp_for(self):
|
||||||
return self._get_comprehension().children[3]
|
return self._get_comprehension().children[3]
|
||||||
|
|
||||||
|
def py__getitem__(self, index):
|
||||||
|
for keys, values in self._iterate():
|
||||||
|
for k in keys:
|
||||||
|
if isinstance(k, compiled.CompiledObject):
|
||||||
|
if k.obj == index:
|
||||||
|
return values
|
||||||
|
return self.dict_values()
|
||||||
|
|
||||||
|
def dict_values(self):
|
||||||
|
return unite(values for keys, values in self._iterate())
|
||||||
|
|
||||||
|
@register_builtin_method('items', type='dict')
|
||||||
|
def _imitate_items(self):
|
||||||
|
items = set(FakeSequence(self._evaluator,
|
||||||
|
(AlreadyEvaluated(keys), AlreadyEvaluated(values)), 'tuple')
|
||||||
|
for keys, values in self._iterate())
|
||||||
|
|
||||||
|
return create_evaluated_sequence_set(self._evaluator, items, type='list')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class GeneratorComprehension(Comprehension, GeneratorMixin):
|
class GeneratorComprehension(Comprehension, GeneratorMixin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@has_builtin_methods
|
|
||||||
class Array(IterableWrapper, ArrayMixin):
|
class Array(IterableWrapper, ArrayMixin):
|
||||||
mapping = {'(': 'tuple',
|
mapping = {'(': 'tuple',
|
||||||
'[': 'list',
|
'[': 'list',
|
||||||
@@ -277,23 +324,6 @@ class Array(IterableWrapper, ArrayMixin):
|
|||||||
def name(self):
|
def name(self):
|
||||||
return helpers.FakeName(self.type, parent=self)
|
return helpers.FakeName(self.type, parent=self)
|
||||||
|
|
||||||
@memoize_default()
|
|
||||||
def dict_values(self):
|
|
||||||
return unite(self._evaluator.eval_element(v) for k, v in self._items())
|
|
||||||
|
|
||||||
@register_builtin_method('values', type='dict')
|
|
||||||
def _imitate_values(self):
|
|
||||||
items = unite(self._evaluator.eval_element(v) for k, v in self._items())
|
|
||||||
return create_evaluated_sequence_set(self._evaluator, items, type='list')
|
|
||||||
#return set([FakeSequence(self._evaluator, [AlreadyEvaluated(items)], 'tuple')])
|
|
||||||
|
|
||||||
@register_builtin_method('items', type='dict')
|
|
||||||
def _imitate_items(self):
|
|
||||||
items = set(FakeSequence(self._evaluator, (k, v), 'tuple')
|
|
||||||
for k, v in self._items())
|
|
||||||
|
|
||||||
return create_evaluated_sequence_set(self._evaluator, items, type='list')
|
|
||||||
|
|
||||||
def py__getitem__(self, index):
|
def py__getitem__(self, index):
|
||||||
"""Here the index is an int/str. Raises IndexError/KeyError."""
|
"""Here the index is an int/str. Raises IndexError/KeyError."""
|
||||||
if self.type == 'dict':
|
if self.type == 'dict':
|
||||||
|
|||||||
@@ -126,13 +126,21 @@ right
|
|||||||
# dict comprehensions
|
# dict comprehensions
|
||||||
# -----------------
|
# -----------------
|
||||||
|
|
||||||
d = {a - 1: b for a, b in {1: 'a', 3: 1.0}.items()}
|
|
||||||
#? str()
|
|
||||||
list()[0]
|
|
||||||
|
|
||||||
#? int()
|
#? int()
|
||||||
list({a - 1: 3 for a in [1]})[0]
|
list({a - 1: 3 for a in [1]})[0]
|
||||||
|
|
||||||
|
d = {a - 1: b for a, b in {1: 'a', 3: 1.0}.items()}
|
||||||
|
#? int()
|
||||||
|
list(d)[0]
|
||||||
|
#? str()
|
||||||
|
d.values()[0]
|
||||||
|
#? str()
|
||||||
|
d[0]
|
||||||
|
#? float() str()
|
||||||
|
d[1]
|
||||||
|
#? float()
|
||||||
|
d[2]
|
||||||
|
|
||||||
# -----------------
|
# -----------------
|
||||||
# set comprehensions
|
# set comprehensions
|
||||||
# -----------------
|
# -----------------
|
||||||
|
|||||||
Reference in New Issue
Block a user