[pypy-commit] pypy all_ordered_dicts: Implement __pypy__.reversed_dict()
arigo
noreply at buildbot.pypy.org
Tue Jan 13 18:40:58 CET 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: all_ordered_dicts
Changeset: r75317:d6780844383e
Date: 2015-01-13 18:40 +0100
http://bitbucket.org/pypy/pypy/changeset/d6780844383e/
Log: Implement __pypy__.reversed_dict()
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -78,6 +78,7 @@
'newlist_hint' : 'interp_magic.newlist_hint',
'add_memory_pressure' : 'interp_magic.add_memory_pressure',
'newdict' : 'interp_dict.newdict',
+ 'reversed_dict' : 'interp_dict.reversed_dict',
'strategy' : 'interp_magic.strategy', # dict,set,list
'set_debug' : 'interp_magic.set_debug',
'locals_to_fast' : 'interp_magic.locals_to_fast',
diff --git a/pypy/module/__pypy__/interp_dict.py b/pypy/module/__pypy__/interp_dict.py
--- a/pypy/module/__pypy__/interp_dict.py
+++ b/pypy/module/__pypy__/interp_dict.py
@@ -30,3 +30,9 @@
return space.newdict(strdict=True)
else:
raise oefmt(space.w_TypeError, "unknown type of dict %s", type)
+
+def reversed_dict(space, w_obj):
+ from pypy.objspace.std.dictmultiobject import W_DictMultiObject
+ if not isinstance(w_obj, W_DictMultiObject):
+ raise OperationError(space.w_TypeError, space.w_None)
+ return w_obj.nondescr_reversed_dict(space)
diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -258,6 +258,17 @@
"""D.itervalues() -> an iterator over the values of D"""
return W_DictMultiIterValuesObject(space, self.itervalues())
+ def nondescr_reversed_dict(self, space):
+ """Not exposed directly to app-level, but via __pypy__.reversed_dict().
+ """
+ if self.strategy.getiterreversed is not None:
+ it = self.strategy.iterreversed(self)
+ return W_DictMultiIterKeysObject(space, it)
+ else:
+ # fall-back
+ w_keys = self.w_keys()
+ return space.call_method(w_keys, '__reversed__')
+
def descr_viewitems(self, space):
"""D.viewitems() -> a set-like object providing a view on D's items"""
return W_DictViewItemsObject(space, self)
@@ -501,6 +512,8 @@
def getiteritems(self, w_dict):
raise NotImplementedError
+ getiterreversed = None # means no implementation is available
+
def rev_update1_dict_dict(self, w_dict, w_updatedict):
iteritems = self.iteritems(w_dict)
while True:
@@ -621,6 +634,9 @@
def getiteritems(self, w_dict):
return iter([])
+ def getiterreversed(self, w_dict):
+ return iter([])
+
# Iterator Implementation base classes
@@ -709,10 +725,6 @@
'setitem_untyped_%s' % dictimpl.__name__)
class IterClassKeys(BaseKeyIterator):
- def __init__(self, space, strategy, impl):
- self.iterator = strategy.getiterkeys(impl)
- BaseIteratorImplementation.__init__(self, space, strategy, impl)
-
def next_key_entry(self):
for key in self.iterator:
return wrapkey(self.space, key)
@@ -720,10 +732,6 @@
return None
class IterClassValues(BaseValueIterator):
- def __init__(self, space, strategy, impl):
- self.iterator = strategy.getitervalues(impl)
- BaseIteratorImplementation.__init__(self, space, strategy, impl)
-
def next_value_entry(self):
for value in self.iterator:
return wrapvalue(self.space, value)
@@ -731,10 +739,6 @@
return None
class IterClassItems(BaseItemIterator):
- def __init__(self, space, strategy, impl):
- self.iterator = strategy.getiteritems(impl)
- BaseIteratorImplementation.__init__(self, space, strategy, impl)
-
if override_next_item is not None:
next_item_entry = override_next_item
else:
@@ -746,13 +750,26 @@
return None, None
def iterkeys(self, w_dict):
- return IterClassKeys(self.space, self, w_dict)
+ it = IterClassKeys(self.space, self, w_dict)
+ it.iterator = self.getiterkeys(w_dict)
+ return it
def itervalues(self, w_dict):
- return IterClassValues(self.space, self, w_dict)
+ it = IterClassValues(self.space, self, w_dict)
+ it.iterator = self.getitervalues(w_dict)
+ return it
def iteritems(self, w_dict):
- return IterClassItems(self.space, self, w_dict)
+ it = IterClassItems(self.space, self, w_dict)
+ it.iterator = self.getiteritems(w_dict)
+ return it
+
+ if dictimpl.getiterreversed is not None:
+ def iterreversed(self, w_dict):
+ it = IterClassKeys(self.space, self, w_dict)
+ it.iterator = self.getiterreversed(w_dict)
+ return it
+ dictimpl.iterreversed = iterreversed
@jit.look_inside_iff(lambda self, w_dict, w_updatedict:
w_dict_unrolling_heuristic(w_dict))
@@ -763,6 +780,7 @@
# this is very similar to the general version, but the difference
# is that it is specialized to call a specific next_item()
iteritems = IterClassItems(self.space, self, w_dict)
+ iteritems.iterator = self.getiteritems(w_dict)
w_key, w_value = iteritems.next_item()
if w_key is None:
return
@@ -930,6 +948,9 @@
def getiteritems(self, w_dict):
return self.unerase(w_dict.dstorage).iteritems()
+ def getiterreversed(self, w_dict):
+ return objectmodel.reversed_dict(self.unerase(w_dict.dstorage))
+
def prepare_update(self, w_dict, num_extra):
objectmodel.prepare_dict_update(self.unerase(w_dict.dstorage),
num_extra)
diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py
--- a/pypy/objspace/std/test/test_dictmultiobject.py
+++ b/pypy/objspace/std/test/test_dictmultiobject.py
@@ -254,6 +254,12 @@
values.append(k)
assert values == d.values()
+ def test_reversed_dict(self):
+ import __pypy__
+ for d in [{}, {1: 2, 3: 4, 5: 6}, {"a": 5, "b": 2, "c": 6}]:
+ assert list(__pypy__.reversed_dict(d)) == d.keys()[::-1]
+ raises(TypeError, __pypy__.reversed_dict, 42)
+
def test_keys(self):
d = {1: 2, 3: 4}
kys = d.keys()
diff --git a/pypy/objspace/std/test/test_mapdict.py b/pypy/objspace/std/test/test_mapdict.py
--- a/pypy/objspace/std/test/test_mapdict.py
+++ b/pypy/objspace/std/test/test_mapdict.py
@@ -700,6 +700,15 @@
del a.x
raises(AttributeError, "a.x")
+ def test_reversed_dict(self):
+ import __pypy__
+ class X(object):
+ pass
+ x = X(); x.a = 10; x.b = 20; x.c = 30
+ d = x.__dict__
+ assert list(__pypy__.reversed_dict(d)) == d.keys()[::-1]
+
+
class AppTestWithMapDictAndCounters(object):
spaceconfig = {"objspace.std.withmapdict": True,
"objspace.std.withmethodcachecounter": True}
More information about the pypy-commit
mailing list