Author: Antonio Cuni <anto.c...@gmail.com> Branch: Changeset: r56811:773c11368fb7 Date: 2012-08-22 18:52 +0200 http://bitbucket.org/pypy/pypy/changeset/773c11368fb7/
Log: merge heads diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py --- a/pypy/interpreter/argument.py +++ b/pypy/interpreter/argument.py @@ -301,10 +301,7 @@ if num_kwds: # kwds_mapping maps target indexes in the scope (minus input_argcount) # to positions in the keywords_w list - cnt = (co_argcount - input_argcount) - if cnt < 0: - cnt = 0 - kwds_mapping = [0] * cnt + kwds_mapping = [0] * (co_argcount - input_argcount) # initialize manually, for the JIT :-( for i in range(len(kwds_mapping)): kwds_mapping[i] = -1 diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -20,6 +20,9 @@ UINT_MAX_32_BITS = r_uint(4294967295) +unpackiterable_driver = jit.JitDriver(name = 'unpackiterable', + greens = ['tp'], + reds = ['items', 'w_iterator']) class W_Root(object): """This is the abstract root class of all wrapped objects that live @@ -224,6 +227,23 @@ def __spacebind__(self, space): return self +class W_InterpIterable(W_Root): + def __init__(self, space, w_iterable): + self.w_iter = space.iter(w_iterable) + self.space = space + + def __iter__(self): + return self + + def next(self): + space = self.space + try: + return space.next(self.w_iter) + except OperationError, e: + if not e.match(space, space.w_StopIteration): + raise + raise StopIteration + class InternalSpaceCache(Cache): """A generic cache for an object space. Arbitrary information can be attached to the space by defining a function or class 'f' which @@ -831,6 +851,9 @@ expected_length) return lst_w[:] # make the resulting list resizable + def iteriterable(self, w_iterable): + return W_InterpIterable(self, w_iterable) + @jit.dont_look_inside def _unpackiterable_unknown_length(self, w_iterator, w_iterable): # Unpack a variable-size list of unknown length. @@ -851,7 +874,11 @@ except MemoryError: items = [] # it might have lied # + tp = self.type(w_iterator) while True: + unpackiterable_driver.jit_merge_point(tp=tp, + w_iterator=w_iterator, + items=items) try: w_item = self.next(w_iterator) except OperationError, e: diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py --- a/pypy/jit/metainterp/warmspot.py +++ b/pypy/jit/metainterp/warmspot.py @@ -14,6 +14,7 @@ from pypy.rlib.debug import fatalerror from pypy.rlib.rstackovf import StackOverflow from pypy.translator.simplify import get_functype +from pypy.translator.backendopt import removenoops from pypy.translator.unsimplify import call_final_function from pypy.jit.metainterp import history, pyjitpl, gc, memmgr @@ -260,6 +261,10 @@ graph = copygraph(graph) [jmpp] = find_jit_merge_points([graph]) graph.startblock = support.split_before_jit_merge_point(*jmpp) + # XXX this is incredibly obscure, but this is sometiems necessary + # so we don't explode in checkgraph. for reasons unknown this + # is not contanied within simplify_graph + removenoops.remove_same_as(graph) # a crash in the following checkgraph() means that you forgot # to list some variable in greens=[] or reds=[] in JitDriver, # or that a jit_merge_point() takes a constant as an argument. diff --git a/pypy/module/itertools/test/test_itertools.py b/pypy/module/itertools/test/test_itertools.py --- a/pypy/module/itertools/test/test_itertools.py +++ b/pypy/module/itertools/test/test_itertools.py @@ -88,6 +88,13 @@ list(it) assert repr(it) == "repeat('foobar', 0)" + def test_repeat_len(self): + import itertools + + r = itertools.repeat('a', 15) + r.next() + raises(TypeError, "len(itertools.repeat('xkcd'))") + def test_takewhile(self): import itertools 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_iterator_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_iterator_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 from pypy.rlib import jit @@ -110,7 +112,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".split() def make_method(method): @@ -119,6 +121,9 @@ f.func_name = method return f + def view_as_kwargs(self): + return self.strategy.view_as_kwargs(self) + for method in dict_methods: setattr(W_DictMultiObject, method, make_method(method)) @@ -133,30 +138,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: @@ -168,8 +173,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) @@ -268,9 +273,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 @@ -280,31 +282,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 @@ -313,6 +316,8 @@ # 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' or TP == 'value': + return result w_key = result[0] w_value = self.dictimplementation.getitem(w_key) if w_value is None: @@ -322,22 +327,96 @@ return (w_key, w_value) # 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_iterator_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_iterator_classes(EmptyDictStrategy) + +registerimplementation(W_DictMultiObject) + +# DictImplementation lattice +# XXX fix me # concrete subclasses of the above @@ -444,6 +523,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") @@ -467,12 +555,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_iterator_classes(ObjectDictStrategy) class StringDictStrategy(AbstractTypedStrategy, DictStrategy): @@ -517,12 +603,12 @@ 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) + @jit.look_inside_iff(lambda self, w_dict: w_dict_unrolling_heuristic(w_dict)) def view_as_kwargs(self, w_dict): @@ -536,37 +622,8 @@ i += 1 return keys, values -class _WrappedIteratorMixin(object): - _mixin_ = True +create_iterator_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") @@ -594,19 +651,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_iterator_classes(IntDictStrategy) init_signature = Signature(['seq_or_map'], None, 'kwargs') init_defaults = [None] @@ -632,9 +685,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) @@ -684,7 +737,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): @@ -692,9 +745,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) @@ -709,9 +762,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)): @@ -762,13 +815,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) @@ -821,38 +874,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) # ____________________________________________________________ @@ -887,7 +975,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_iterator_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_iterator_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_iterator_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_iterator_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,8 +3,8 @@ from pypy.rlib import rerased, jit from pypy.objspace.std.dictmultiobject import (DictStrategy, + create_iterator_classes, EmptyDictStrategy, - IteratorImplementation, ObjectDictStrategy, StringDictStrategy) @@ -39,9 +39,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]]) @@ -157,19 +154,24 @@ keys, values_w = self.unerase(w_dict.dstorage) return keys[:], values_w[:] # copy to make non-resizable + def getiterkeys(self, w_dict): + return iter(self.unerase(w_dict.dstorage)[0]) + def getitervalues(self, w_dict): + return iter(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): + strategy = self.strategy + assert isinstance(strategy, KwargsDictStrategy) + for i in self.iterator: + keys, values_w = 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_iterator_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 @@ -454,6 +454,8 @@ class E(dict): pass assert isinstance(D.fromkeys([1, 2]), E) + assert dict.fromkeys({"a": 2, "b": 3}) == {"a": None, "b": None} + assert dict.fromkeys({"a": 2, 1: 3}) == {"a": None, 1: None} def test_str_uses_repr(self): class D(dict): @@ -1038,10 +1040,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) diff --git a/pypy/objspace/std/test/test_kwargsdict.py b/pypy/objspace/std/test/test_kwargsdict.py --- a/pypy/objspace/std/test/test_kwargsdict.py +++ b/pypy/objspace/std/test/test_kwargsdict.py @@ -141,3 +141,9 @@ d = f() assert "EmptyKwargsDictStrategy" in self.get_strategy(d) + def test_iterator(self): + def f(**args): + return args + + assert dict.fromkeys(f(a=2, b=3)) == {"a": None, "b": None} + assert sorted(f(a=2, b=3).itervalues()) == [2, 3] diff --git a/pypy/rpython/lltypesystem/rbuilder.py b/pypy/rpython/lltypesystem/rbuilder.py --- a/pypy/rpython/lltypesystem/rbuilder.py +++ b/pypy/rpython/lltypesystem/rbuilder.py @@ -59,7 +59,7 @@ @classmethod def ll_new(cls, init_size): - if init_size < 0 or init_size > MAX: + if init_size < 0: init_size = MAX ll_builder = lltype.malloc(cls.lowleveltype.TO) ll_builder.allocated = init_size _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit