[pypy-commit] pypy speedup-unpackiterable: a major refactor - try to have different classes for iterkeys/itervalues/iteritems
fijal
noreply at buildbot.pypy.org
Fri Jul 13 01:25:49 CEST 2012
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: speedup-unpackiterable
Changeset: r56051:b08585390218
Date: 2012-07-13 01:25 +0200
http://bitbucket.org/pypy/pypy/changeset/b08585390218/
Log: a major refactor - try to have different classes for
iterkeys/itervalues/iteritems
diff --git a/pypy/objspace/std/celldict.py b/pypy/objspace/std/celldict.py
--- a/pypy/objspace/std/celldict.py
+++ b/pypy/objspace/std/celldict.py
@@ -4,7 +4,7 @@
"""
from pypy.interpreter.baseobjspace import W_Root
-from pypy.objspace.std.dictmultiobject import IteratorImplementation
+from pypy.objspace.std.dictmultiobject import create_itertor_classes
from pypy.objspace.std.dictmultiobject import DictStrategy, _never_equal_to_string
from pypy.objspace.std.dictmultiobject import ObjectDictStrategy
from pypy.rlib import jit, rerased
@@ -124,9 +124,6 @@
w_res = self.getdictvalue_no_unwrapping(w_dict, key)
return unwrap_cell(w_res)
- def iter(self, w_dict):
- return ModuleDictIteratorImplementation(self.space, self, w_dict)
-
def w_keys(self, w_dict):
space = self.space
l = self.unerase(w_dict.dstorage).keys()
@@ -161,15 +158,15 @@
w_dict.strategy = strategy
w_dict.dstorage = strategy.erase(d_new)
-class ModuleDictIteratorImplementation(IteratorImplementation):
- def __init__(self, space, strategy, dictimplementation):
- IteratorImplementation.__init__(
- self, space, strategy, dictimplementation)
- dict_w = strategy.unerase(dictimplementation.dstorage)
- self.iterator = dict_w.iteritems()
+ def getiterkeys(self, w_dict):
+ return self.unerase(w_dict.dstorage).iterkeys()
+ def getitervalues(self, w_dict):
+ return self.unerase(w_dict.dstorage).itervalues()
+ def getiteritems(self, w_dict):
+ return self.unerase(w_dict.dstorage).iteritems()
+ def wrapkey(space, key):
+ return space.wrap(key)
+ def wrapvalue(space, value):
+ return unwrap_cell(value)
- def next_entry(self):
- for key, cell in self.iterator:
- return (self.space.wrap(key), unwrap_cell(cell))
- else:
- return None, None
+create_itertor_classes(ModuleDictStrategy)
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
@@ -7,8 +7,10 @@
from pypy.interpreter.argument import Signature
from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.rlib.objectmodel import r_dict, we_are_translated, specialize
+from pypy.rlib.objectmodel import r_dict, we_are_translated, specialize,\
+ newlist_hint
from pypy.rlib.debug import mark_dict_non_null
+from pypy.tool.sourcetools import func_with_new_name
from pypy.rlib import rerased
@@ -94,7 +96,7 @@
dict_methods = "setitem setitem_str getitem \
getitem_str delitem length \
clear w_keys values \
- items iter setdefault \
+ items iterkeys itervalues iteritems setdefault \
popitem listview_str listview_int \
view_as_kwargs".split()
@@ -118,30 +120,30 @@
raise NotImplementedError
def w_keys(self, w_dict):
- iterator = self.iter(w_dict)
- result = []
+ iterator = self.iterkeys(w_dict)
+ result = newlist_hint(self.length(w_dict))
while 1:
- w_key, w_value = iterator.next()
+ w_key = iterator.next_key()
if w_key is not None:
result.append(w_key)
else:
return self.space.newlist(result)
def values(self, w_dict):
- iterator = self.iter(w_dict)
- result = []
+ iterator = self.itervalues(w_dict)
+ result = newlist_hint(self.length(w_dict))
while 1:
- w_key, w_value = iterator.next()
+ w_value = iterator.next_value()
if w_value is not None:
result.append(w_value)
else:
return result
def items(self, w_dict):
- iterator = self.iter(w_dict)
- result = []
+ iterator = self.iteritems(w_dict)
+ result = newlist_hint(self.length(w_dict))
while 1:
- w_key, w_value = iterator.next()
+ w_key, w_value = iterator.next_item()
if w_key is not None:
result.append(self.space.newtuple([w_key, w_value]))
else:
@@ -153,8 +155,8 @@
# will take longer and longer. But all interesting strategies
# provide a better one.
space = self.space
- iterator = self.iter(w_dict)
- w_key, w_value = iterator.next()
+ iterator = self.iteritems(w_dict)
+ w_key, w_value = iterator.next_item()
self.delitem(w_dict, w_key)
return (w_key, w_value)
@@ -253,9 +255,6 @@
def length(self, w_dict):
return 0
- def iter(self, w_dict):
- return EmptyIteratorImplementation(self.space, self, w_dict)
-
def clear(self, w_dict):
return
@@ -265,31 +264,32 @@
def view_as_kwargs(self, w_dict):
return ([], [])
-registerimplementation(W_DictMultiObject)
+ # ---------- iterator interface ----------------
-# DictImplementation lattice
-# XXX fix me
+ def getiterkeys(self, w_dict):
+ return iter([None])
+ getitervalues = getiterkeys
+ def getiteritems(self, w_dict):
+ return iter([(None, None)])
# Iterator Implementation base classes
-class IteratorImplementation(object):
- def __init__(self, space, strategy, implementation):
- self.space = space
- self.strategy = strategy
- self.dictimplementation = implementation
- self.len = implementation.length()
- self.pos = 0
-
+def _new_next(TP):
+ if TP == 'key' or TP == 'value':
+ EMPTY = None
+ else:
+ EMPTY = None, None
+
def next(self):
if self.dictimplementation is None:
- return None, None
+ return EMPTY
if self.len != self.dictimplementation.length():
self.len = -1 # Make this error state sticky
raise OperationError(self.space.w_RuntimeError,
self.space.wrap("dictionary changed size during iteration"))
# look for the next entry
if self.pos < self.len:
- result = self.next_entry()
+ result = getattr(self, 'next_' + TP + '_entry')()
self.pos += 1
if self.strategy is self.dictimplementation.strategy:
return result # common case
@@ -298,31 +298,112 @@
# length of the dict. The (key, value) pair in 'result'
# might be out-of-date. We try to explicitly look up
# the key in the dict.
+ if TP == 'key':
+ return result[0]
w_key = result[0]
w_value = self.dictimplementation.getitem(w_key)
if w_value is None:
self.len = -1 # Make this error state sticky
raise OperationError(self.space.w_RuntimeError,
self.space.wrap("dictionary changed during iteration"))
- return (w_key, w_value)
+ if TP == 'value':
+ return w_value
+ elif TP == 'item':
+ return (w_key, w_value)
+ else:
+ assert False # unreachable code
# no more entries
self.dictimplementation = None
- return None, None
+ return EMPTY
+ return func_with_new_name(next, 'next_' + TP)
- def next_entry(self):
- """ Purely abstract method
- """
- raise NotImplementedError
+class BaseIteratorImplementation(object):
+ def __init__(self, space, strategy, implementation):
+ self.space = space
+ self.strategy = strategy
+ self.dictimplementation = implementation
+ self.len = implementation.length()
+ self.pos = 0
def length(self):
if self.dictimplementation is not None:
return self.len - self.pos
return 0
-class EmptyIteratorImplementation(IteratorImplementation):
- def next(self):
- return (None, None)
+class BaseKeyIterator(BaseIteratorImplementation):
+ next_key = _new_next('key')
+class BaseValueIterator(BaseIteratorImplementation):
+ next_value = _new_next('value')
+
+class BaseItemIterator(BaseIteratorImplementation):
+ next_item = _new_next('item')
+
+def create_itertor_classes(dictimpl, override_next_item=None):
+ if not hasattr(dictimpl, 'wrapkey'):
+ wrapkey = lambda space, key : key
+ else:
+ wrapkey = dictimpl.wrapkey.im_func
+ if not hasattr(dictimpl, 'wrapvalue'):
+ wrapvalue = lambda space, key : key
+ else:
+ wrapvalue = dictimpl.wrapvalue.im_func
+
+ 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)
+ else:
+ 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)
+ else:
+ 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:
+ def next_item_entry(self):
+ for key, value in self.iterator:
+ return (wrapkey(self.space, key),
+ wrapvalue(self.space, value))
+ else:
+ return None, None
+
+ def iterkeys(self, w_dict):
+ return IterClassKeys(self.space, self, w_dict)
+
+ def itervalues(self, w_dict):
+ return IterClassValues(self.space, self, w_dict)
+
+ def iteritems(self, w_dict):
+ return IterClassItems(self.space, self, w_dict)
+ dictimpl.iterkeys = iterkeys
+ dictimpl.itervalues = itervalues
+ dictimpl.iteritems = iteritems
+
+create_itertor_classes(EmptyDictStrategy)
+
+registerimplementation(W_DictMultiObject)
+
+# DictImplementation lattice
+# XXX fix me
# concrete subclasses of the above
@@ -429,6 +510,15 @@
w_dict.strategy = strategy
w_dict.dstorage = strategy.erase(d_new)
+ # --------------- iterator interface -----------------
+
+ def getiterkeys(self, w_dict):
+ return self.unerase(w_dict.dstorage).iterkeys()
+ def getitervalues(self, w_dict):
+ return self.unerase(w_dict.dstorage).itervalues()
+ def getiteritems(self, w_dict):
+ return self.unerase(w_dict.dstorage).iteritems()
+
class ObjectDictStrategy(AbstractTypedStrategy, DictStrategy):
erase, unerase = rerased.new_erasing_pair("object")
@@ -452,12 +542,10 @@
def _never_equal_to(self, w_lookup_type):
return False
- def iter(self, w_dict):
- return ObjectIteratorImplementation(self.space, self, w_dict)
-
def w_keys(self, w_dict):
return self.space.newlist(self.unerase(w_dict.dstorage).keys())
+create_itertor_classes(ObjectDictStrategy)
class StringDictStrategy(AbstractTypedStrategy, DictStrategy):
@@ -502,44 +590,14 @@
def listview_str(self, w_dict):
return self.unerase(w_dict.dstorage).keys()
- def iter(self, w_dict):
- return StrIteratorImplementation(self.space, self, w_dict)
-
def w_keys(self, w_dict):
return self.space.newlist_str(self.listview_str(w_dict))
+ def wrapkey(space, key):
+ return space.wrap(key)
-class _WrappedIteratorMixin(object):
- _mixin_ = True
+create_itertor_classes(StringDictStrategy)
- def __init__(self, space, strategy, dictimplementation):
- IteratorImplementation.__init__(self, space, strategy, dictimplementation)
- self.iterator = strategy.unerase(dictimplementation.dstorage).iteritems()
-
- def next_entry(self):
- # note that this 'for' loop only runs once, at most
- for key, w_value in self.iterator:
- return self.space.wrap(key), w_value
- else:
- return None, None
-
-class _UnwrappedIteratorMixin:
- _mixin_ = True
-
- def __init__(self, space, strategy, dictimplementation):
- IteratorImplementation.__init__(self, space, strategy, dictimplementation)
- self.iterator = strategy.unerase(dictimplementation.dstorage).iteritems()
-
- def next_entry(self):
- # note that this 'for' loop only runs once, at most
- for w_key, w_value in self.iterator:
- return w_key, w_value
- else:
- return None, None
-
-
-class StrIteratorImplementation(_WrappedIteratorMixin, IteratorImplementation):
- pass
class IntDictStrategy(AbstractTypedStrategy, DictStrategy):
erase, unerase = rerased.new_erasing_pair("int")
@@ -567,19 +625,15 @@
space.is_w(w_lookup_type, space.w_unicode)
)
- def iter(self, w_dict):
- return IntIteratorImplementation(self.space, self, w_dict)
-
def listview_int(self, w_dict):
return self.unerase(w_dict.dstorage).keys()
+ def wrapkey(space, key):
+ return space.wrap(key)
+
# XXX there is no space.newlist_int yet to implement w_keys more efficiently
-class IntIteratorImplementation(_WrappedIteratorMixin, IteratorImplementation):
- pass
-
-class ObjectIteratorImplementation(_UnwrappedIteratorMixin, IteratorImplementation):
- pass
+create_itertor_classes(IntDictStrategy)
init_signature = Signature(['seq_or_map'], None, 'kwargs')
init_defaults = [None]
@@ -605,9 +659,9 @@
w_dict.setitem(w_key, w_value)
def update1_dict_dict(space, w_dict, w_data):
- iterator = w_data.iter()
+ iterator = w_data.iteritems()
while 1:
- w_key, w_value = iterator.next()
+ w_key, w_value = iterator.next_item()
if w_key is None:
break
w_dict.setitem(w_key, w_value)
@@ -657,7 +711,7 @@
dict_has_key__DictMulti_ANY = contains__DictMulti_ANY
def iter__DictMulti(space, w_dict):
- return W_DictMultiIterObject(space, w_dict.iter(), KEYSITER)
+ return W_DictMultiIterKeysObject(space, w_dict.iterkeys())
def eq__DictMulti_DictMulti(space, w_left, w_right):
if space.is_w(w_left, w_right):
@@ -665,9 +719,9 @@
if w_left.length() != w_right.length():
return space.w_False
- iteratorimplementation = w_left.iter()
+ iteratorimplementation = w_left.iteritems()
while 1:
- w_key, w_val = iteratorimplementation.next()
+ w_key, w_val = iteratorimplementation.next_item()
if w_key is None:
break
w_rightval = w_right.getitem(w_key)
@@ -682,9 +736,9 @@
returns the smallest key in acontent for which b's value is different or absent and this value """
w_smallest_diff_a_key = None
w_its_value = None
- iteratorimplementation = w_a.iter()
+ iteratorimplementation = w_a.iteritems()
while 1:
- w_key, w_val = iteratorimplementation.next()
+ w_key, w_val = iteratorimplementation.next_item()
if w_key is None:
break
if w_smallest_diff_a_key is None or space.is_true(space.lt(w_key, w_smallest_diff_a_key)):
@@ -735,13 +789,13 @@
return space.newlist(w_self.values())
def dict_iteritems__DictMulti(space, w_self):
- return W_DictMultiIterObject(space, w_self.iter(), ITEMSITER)
+ return W_DictMultiIterItemsObject(space, w_self.iteritems())
def dict_iterkeys__DictMulti(space, w_self):
- return W_DictMultiIterObject(space, w_self.iter(), KEYSITER)
+ return W_DictMultiIterKeysObject(space, w_self.iterkeys())
def dict_itervalues__DictMulti(space, w_self):
- return W_DictMultiIterObject(space, w_self.iter(), VALUESITER)
+ return W_DictMultiIterValuesObject(space, w_self.itervalues())
def dict_viewitems__DictMulti(space, w_self):
return W_DictViewItemsObject(space, w_self)
@@ -794,38 +848,73 @@
# Iteration
-KEYSITER = 0
-ITEMSITER = 1
-VALUESITER = 2
-
-class W_DictMultiIterObject(W_Object):
+class W_DictMultiIterKeysObject(W_Object):
from pypy.objspace.std.dicttype import dictiter_typedef as typedef
- _immutable_fields_ = ["iteratorimplementation", "itertype"]
+ _immutable_fields_ = ["iteratorimplementation"]
- def __init__(w_self, space, iteratorimplementation, itertype):
+ ignore_for_isinstance_cache = True
+
+ def __init__(w_self, space, iteratorimplementation):
w_self.space = space
w_self.iteratorimplementation = iteratorimplementation
- w_self.itertype = itertype
-registerimplementation(W_DictMultiIterObject)
+registerimplementation(W_DictMultiIterKeysObject)
-def iter__DictMultiIterObject(space, w_dictiter):
+class W_DictMultiIterValuesObject(W_Object):
+ from pypy.objspace.std.dicttype import dictiter_typedef as typedef
+
+ _immutable_fields_ = ["iteratorimplementation"]
+
+ ignore_for_isinstance_cache = True
+
+ def __init__(w_self, space, iteratorimplementation):
+ w_self.space = space
+ w_self.iteratorimplementation = iteratorimplementation
+
+registerimplementation(W_DictMultiIterValuesObject)
+
+class W_DictMultiIterItemsObject(W_Object):
+ from pypy.objspace.std.dicttype import dictiter_typedef as typedef
+
+ _immutable_fields_ = ["iteratorimplementation"]
+
+ ignore_for_isinstance_cache = True
+
+ def __init__(w_self, space, iteratorimplementation):
+ w_self.space = space
+ w_self.iteratorimplementation = iteratorimplementation
+
+registerimplementation(W_DictMultiIterItemsObject)
+
+def iter__DictMultiIterKeysObject(space, w_dictiter):
return w_dictiter
-def next__DictMultiIterObject(space, w_dictiter):
+def next__DictMultiIterKeysObject(space, w_dictiter):
iteratorimplementation = w_dictiter.iteratorimplementation
- w_key, w_value = iteratorimplementation.next()
+ w_key = iteratorimplementation.next_key()
if w_key is not None:
- itertype = w_dictiter.itertype
- if itertype == KEYSITER:
- return w_key
- elif itertype == VALUESITER:
- return w_value
- elif itertype == ITEMSITER:
- return space.newtuple([w_key, w_value])
- else:
- assert 0, "should be unreachable"
+ return w_key
+ raise OperationError(space.w_StopIteration, space.w_None)
+
+def iter__DictMultiIterValuesObject(space, w_dictiter):
+ return w_dictiter
+
+def next__DictMultiIterValuesObject(space, w_dictiter):
+ iteratorimplementation = w_dictiter.iteratorimplementation
+ w_value = iteratorimplementation.next_value()
+ if w_value is not None:
+ return w_value
+ raise OperationError(space.w_StopIteration, space.w_None)
+
+def iter__DictMultiIterItemsObject(space, w_dictiter):
+ return w_dictiter
+
+def next__DictMultiIterItemsObject(space, w_dictiter):
+ iteratorimplementation = w_dictiter.iteratorimplementation
+ w_key, w_value = iteratorimplementation.next_item()
+ if w_key is not None:
+ return space.newtuple([w_key, w_value])
raise OperationError(space.w_StopIteration, space.w_None)
# ____________________________________________________________
@@ -860,7 +949,6 @@
def all_contained_in(space, w_dictview, w_otherview):
w_iter = space.iter(w_dictview)
- assert isinstance(w_iter, W_DictMultiIterObject)
while True:
try:
diff --git a/pypy/objspace/std/dictproxyobject.py b/pypy/objspace/std/dictproxyobject.py
--- a/pypy/objspace/std/dictproxyobject.py
+++ b/pypy/objspace/std/dictproxyobject.py
@@ -1,6 +1,6 @@
from pypy.objspace.std.model import registerimplementation, W_Object
from pypy.objspace.std.register_all import register_all
-from pypy.objspace.std.dictmultiobject import W_DictMultiObject, IteratorImplementation
+from pypy.objspace.std.dictmultiobject import W_DictMultiObject, create_itertor_classes
from pypy.objspace.std.dictmultiobject import DictStrategy
from pypy.objspace.std.typeobject import unwrap_cell
from pypy.interpreter.error import OperationError, operationerrfmt
@@ -81,9 +81,6 @@
def length(self, w_dict):
return len(self.unerase(w_dict.dstorage).dict_w)
- def iter(self, w_dict):
- return DictProxyIteratorImplementation(self.space, self, w_dict)
-
def keys(self, w_dict):
space = self.space
return space.newlist_str(self.unerase(w_dict.dstorage).dict_w.keys())
@@ -106,15 +103,15 @@
w_type.dict_w.clear()
w_type.mutated(None)
-class DictProxyIteratorImplementation(IteratorImplementation):
- def __init__(self, space, strategy, dictimplementation):
- IteratorImplementation.__init__(
- self, space, strategy, dictimplementation)
- w_type = strategy.unerase(dictimplementation.dstorage)
- self.iterator = w_type.dict_w.iteritems()
+ def getiterkeys(self, w_dict):
+ return self.unerase(w_dict.dstorage).dict_w.iterkeys()
+ def getitervalues(self, w_dict):
+ return self.unerase(w_dict.dstorage).dict_w.itervalues()
+ def getiteritems(self, w_dict):
+ return self.unerase(w_dict.dstorage).dict_w.iteritems()
+ def wrapkey(space, key):
+ return space.wrap(key)
+ def wrapvalue(space, value):
+ return unwrap_cell(space, value)
- def next_entry(self):
- for key, w_value in self.iterator:
- return (self.space.wrap(key), unwrap_cell(self.space, w_value))
- else:
- return (None, None)
+create_itertor_classes(DictProxyStrategy)
diff --git a/pypy/objspace/std/identitydict.py b/pypy/objspace/std/identitydict.py
--- a/pypy/objspace/std/identitydict.py
+++ b/pypy/objspace/std/identitydict.py
@@ -5,8 +5,7 @@
from pypy.rlib.debug import mark_dict_non_null
from pypy.objspace.std.dictmultiobject import (AbstractTypedStrategy,
DictStrategy,
- IteratorImplementation,
- _UnwrappedIteratorMixin)
+ create_itertor_classes)
# this strategy is selected by EmptyDictStrategy.switch_to_correct_strategy
@@ -77,12 +76,7 @@
def _never_equal_to(self, w_lookup_type):
return False
- def iter(self, w_dict):
- return IdentityDictIteratorImplementation(self.space, self, w_dict)
-
def w_keys(self, w_dict):
return self.space.newlist(self.unerase(w_dict.dstorage).keys())
-
-class IdentityDictIteratorImplementation(_UnwrappedIteratorMixin, IteratorImplementation):
- pass
+create_itertor_classes(IdentityDictStrategy)
diff --git a/pypy/objspace/std/kwargsdict.py b/pypy/objspace/std/kwargsdict.py
--- a/pypy/objspace/std/kwargsdict.py
+++ b/pypy/objspace/std/kwargsdict.py
@@ -3,7 +3,7 @@
from pypy.rlib import rerased, jit
from pypy.objspace.std.dictmultiobject import (DictStrategy,
- IteratorImplementation,
+ create_itertor_classes,
ObjectDictStrategy,
StringDictStrategy)
@@ -30,9 +30,6 @@
def _never_equal_to(self, w_lookup_type):
return False
- def iter(self, w_dict):
- return KwargsDictIterator(self.space, self, w_dict)
-
def w_keys(self, w_dict):
return self.space.newlist([self.space.wrap(key) for key in self.unerase(w_dict.dstorage)[0]])
@@ -147,19 +144,22 @@
def view_as_kwargs(self, w_dict):
return self.unerase(w_dict.dstorage)
+ def getiterkeys(self, w_dict):
+ return self.unerase(w_dict.dstorage)[0]
+ def getitervalues(self, w_dict):
+ return self.unerase(w_dict.dstorage)[1]
+ def getiteritems(self, w_dict):
+ keys = self.unerase(w_dict.dstorage)[0]
+ return iter(range(len(keys)))
+ def wrapkey(space, key):
+ return space.wrap(key)
-class KwargsDictIterator(IteratorImplementation):
- def __init__(self, space, strategy, dictimplementation):
- IteratorImplementation.__init__(self, space, strategy, dictimplementation)
- keys, values_w = strategy.unerase(self.dictimplementation.dstorage)
- self.iterator = iter(range(len(keys)))
- # XXX this potentially leaks
- self.keys = keys
- self.values_w = values_w
+def next_item(self):
+ for i in self.iterator:
+ keys, values_w = self.strategy.unerase(
+ self.dictimplementation.dstorage)
+ return self.space.wrap(keys[i]), values_w[i]
+ else:
+ return None, None
- def next_entry(self):
- # note that this 'for' loop only runs once, at most
- for i in self.iterator:
- return self.space.wrap(self.keys[i]), self.values_w[i]
- else:
- return None, None
+create_itertor_classes(KwargsDictStrategy, override_next_item=next_item)
diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -5,7 +5,7 @@
from pypy.interpreter.baseobjspace import W_Root
from pypy.objspace.std.dictmultiobject import W_DictMultiObject, DictStrategy, ObjectDictStrategy
-from pypy.objspace.std.dictmultiobject import IteratorImplementation
+from pypy.objspace.std.dictmultiobject import BaseKeyIterator, BaseValueIterator, BaseItemIterator
from pypy.objspace.std.dictmultiobject import _never_equal_to_string
from pypy.objspace.std.objectobject import W_ObjectObject
from pypy.objspace.std.typeobject import TypeCell
@@ -676,9 +676,6 @@
res += 1
return res
- def iter(self, w_dict):
- return MapDictIteratorImplementation(self.space, self, w_dict)
-
def clear(self, w_dict):
w_obj = self.unerase(w_dict.dstorage)
new_obj = w_obj._get_mapdict_map().remove_dict_entries(w_obj)
@@ -696,32 +693,83 @@
# XXX could implement a more efficient w_keys based on space.newlist_str
+ def iterkeys(self, w_dict):
+ return MapDictIteratorKeys(self.space, self, w_dict)
+ def itervalues(self, w_dict):
+ return MapDictIteratorValues(self.space, self, w_dict)
+ def iteritems(self, w_dict):
+ return MapDictIteratorItems(self.space, self, w_dict)
+
+
def materialize_r_dict(space, obj, dict_w):
map = obj._get_mapdict_map()
new_obj = map.materialize_r_dict(space, obj, dict_w)
_become(obj, new_obj)
-class MapDictIteratorImplementation(IteratorImplementation):
- def __init__(self, space, strategy, dictimplementation):
- IteratorImplementation.__init__(
- self, space, strategy, dictimplementation)
- w_obj = strategy.unerase(dictimplementation.dstorage)
- self.w_obj = w_obj
- self.orig_map = self.curr_map = w_obj._get_mapdict_map()
+class MapDictIteratorKeys(BaseKeyIterator):
+ def __init__(self, space, strategy, dictimplementation):
+ BaseKeyIterator.__init__(
+ self, space, strategy, dictimplementation)
+ w_obj = strategy.unerase(dictimplementation.dstorage)
+ self.w_obj = w_obj
+ self.orig_map = self.curr_map = w_obj._get_mapdict_map()
- def next_entry(self):
- implementation = self.dictimplementation
- assert isinstance(implementation.strategy, MapDictStrategy)
- if self.orig_map is not self.w_obj._get_mapdict_map():
- return None, None
- if self.curr_map:
- curr_map = self.curr_map.search(DICT)
- if curr_map:
- self.curr_map = curr_map.back
- attr = curr_map.selector[0]
- w_attr = self.space.wrap(attr)
- return w_attr, self.w_obj.getdictvalue(self.space, attr)
- return None, None
+ def next_key_entry(self):
+ implementation = self.dictimplementation
+ assert isinstance(implementation.strategy, MapDictStrategy)
+ if self.orig_map is not self.w_obj._get_mapdict_map():
+ return None
+ if self.curr_map:
+ curr_map = self.curr_map.search(DICT)
+ if curr_map:
+ self.curr_map = curr_map.back
+ attr = curr_map.selector[0]
+ w_attr = self.space.wrap(attr)
+ return w_attr
+ return None
+
+class MapDictIteratorValues(BaseValueIterator):
+ def __init__(self, space, strategy, dictimplementation):
+ BaseValueIterator.__init__(
+ self, space, strategy, dictimplementation)
+ w_obj = strategy.unerase(dictimplementation.dstorage)
+ self.w_obj = w_obj
+ self.orig_map = self.curr_map = w_obj._get_mapdict_map()
+
+ def next_value_entry(self):
+ implementation = self.dictimplementation
+ assert isinstance(implementation.strategy, MapDictStrategy)
+ if self.orig_map is not self.w_obj._get_mapdict_map():
+ return None
+ if self.curr_map:
+ curr_map = self.curr_map.search(DICT)
+ if curr_map:
+ self.curr_map = curr_map.back
+ attr = curr_map.selector[0]
+ return self.w_obj.getdictvalue(self.space, attr)
+ return None
+
+class MapDictIteratorItems(BaseItemIterator):
+ def __init__(self, space, strategy, dictimplementation):
+ BaseItemIterator.__init__(
+ self, space, strategy, dictimplementation)
+ w_obj = strategy.unerase(dictimplementation.dstorage)
+ self.w_obj = w_obj
+ self.orig_map = self.curr_map = w_obj._get_mapdict_map()
+
+ def next_item_entry(self):
+ implementation = self.dictimplementation
+ assert isinstance(implementation.strategy, MapDictStrategy)
+ if self.orig_map is not self.w_obj._get_mapdict_map():
+ return None, None
+ if self.curr_map:
+ curr_map = self.curr_map.search(DICT)
+ if curr_map:
+ self.curr_map = curr_map.back
+ attr = curr_map.selector[0]
+ w_attr = self.space.wrap(attr)
+ return w_attr, self.w_obj.getdictvalue(self.space, attr)
+ return None, None
# ____________________________________________________________
# Magic caching
diff --git a/pypy/objspace/std/model.py b/pypy/objspace/std/model.py
--- a/pypy/objspace/std/model.py
+++ b/pypy/objspace/std/model.py
@@ -102,7 +102,9 @@
tupleobject.W_TupleObject: [],
listobject.W_ListObject: [],
dictmultiobject.W_DictMultiObject: [],
- dictmultiobject.W_DictMultiIterObject: [],
+ dictmultiobject.W_DictMultiIterKeysObject: [],
+ dictmultiobject.W_DictMultiIterValuesObject: [],
+ dictmultiobject.W_DictMultiIterItemsObject: [],
stringobject.W_StringObject: [],
bytearrayobject.W_BytearrayObject: [],
typeobject.W_TypeObject: [],
@@ -128,7 +130,9 @@
self.imported_but_not_registered = {
dictmultiobject.W_DictMultiObject: True, # XXXXXX
- dictmultiobject.W_DictMultiIterObject: True,
+ dictmultiobject.W_DictMultiIterKeysObject: True,
+ dictmultiobject.W_DictMultiIterValuesObject: True,
+ dictmultiobject.W_DictMultiIterItemsObject: True,
listobject.W_ListObject: True,
stringobject.W_StringObject: True,
tupleobject.W_TupleObject: True,
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
@@ -1035,10 +1035,10 @@
def test_iter(self):
self.fill_impl()
- iteratorimplementation = self.impl.iter()
+ iteratorimplementation = self.impl.iteritems()
items = []
while 1:
- item = iteratorimplementation.next()
+ item = iteratorimplementation.next_item()
if item == (None, None):
break
items.append(item)
More information about the pypy-commit
mailing list