Implement imitate_items(), which helps if you use {}.items().

This commit is contained in:
Dave Halter
2016-01-01 12:43:07 +01:00
parent 4e93fb344b
commit 0acc5256ea
3 changed files with 38 additions and 14 deletions

View File

@@ -279,21 +279,29 @@ class Array(IterableWrapper, ArrayMixin):
@memoize_default()
def dict_values(self):
return unite(self._evaluator.eval_element(v) for v in self._values())
return unite(self._evaluator.eval_element(v) for k, v in self._items())
@register_builtin_method('values', type='dict')
def py_values(self):
return set([FakeSequence(self._evaluator, [AlreadyEvaluated(self.dict_values())], 'tuple')])
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):
"""Here the index is an int/str. Raises IndexError/KeyError."""
if self.type == 'dict':
for key, values in self._items():
for key, value in self._items():
for k in self._evaluator.eval_element(key):
if isinstance(k, compiled.CompiledObject) \
and index == k.obj:
for value in values:
return self._evaluator.eval_element(value)
return self._evaluator.eval_element(value)
raise KeyError('No key found in dictionary %s.' % self)
# Can raise an IndexError
@@ -353,11 +361,10 @@ class Array(IterableWrapper, ArrayMixin):
op = next(iterator, None)
if op is None or op == ',':
kv.append(key) # A set.
elif op == ':': # A dict.
kv.append((key, [next(iterator)]))
next(iterator, None) # Possible comma.
else:
raise NotImplementedError('dict/set comprehensions')
assert op == ':' # A dict.
kv.append((key, next(iterator)))
next(iterator, None) # Possible comma.
return kv
else:
return [array_node]
@@ -391,6 +398,16 @@ class FakeSequence(_FakeArray):
return self._sequence_values
def create_evaluated_sequence_set(evaluator, *types_order, **kwargs):
"""
``sequence_type`` is a named argument, that doesn't work in Python2. For backwards
compatibility reasons, we're now using kwargs.
"""
sequence_type = kwargs.get('sequence_type')
sets = tuple(AlreadyEvaluated(types) for types in types_order)
return set([FakeSequence(evaluator, sets, sequence_type)])
class AlreadyEvaluated(frozenset):
"""A simple container to add already evaluated objects to an array."""
def get_code(self, normalized=False):
@@ -414,7 +431,9 @@ class FakeDict(_FakeArray):
return unite(self._evaluator.eval_element(v) for v in self._dct[index])
def _items(self):
return self._dct.items()
for key, values in self._dct.items():
# TODO this is not proper. The values could be multiple values?!
yield key, values[0]
class MergedArray(_FakeArray):

View File

@@ -269,7 +269,7 @@ def get_params(evaluator, func, var_args):
try:
key_param = param_dict[unicode(key)]
except KeyError:
non_matching_keys[key] += va_values
non_matching_keys[key] = va_values
else:
param_names.append(ExecutedParam(key_param, var_args, va_values).name)
@@ -407,10 +407,10 @@ def _star_star_dict(evaluator, array, input_node, func):
return array._dct
elif isinstance(array, iterable.Array) and array.type == 'dict':
# TODO bad call to non-public API
for key_node, values in array._items():
for key_node, value in array._items():
for key in evaluator.eval_element(key_node):
if precedence.is_string(key):
dct[key.obj] += values
dct[key.obj].append(value)
else:
if func is not None:

View File

@@ -86,6 +86,11 @@ d.values()[0]
##? int() list
dict(d).values()[0]
#? str() float()
d.items()[0][0]
#? int() list
d.items()[0][1]
# -----------------
# set
# -----------------