[pypy-commit] pypy py3.5: iterobject.py:

arigo pypy.commits at gmail.com
Fri Oct 14 10:27:44 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r87792:867628382da5
Date: 2016-10-14 16:27 +0200
http://bitbucket.org/pypy/pypy/changeset/867628382da5/

Log:	iterobject.py:

	* go systematically with self.w_seq = (w_iterable or None), never
	space.w_None.

	* follow more exactly what CPython 3.5 does in reduce/setstate

diff --git a/pypy/module/_pickle_support/maker.py b/pypy/module/_pickle_support/maker.py
--- a/pypy/module/_pickle_support/maker.py
+++ b/pypy/module/_pickle_support/maker.py
@@ -42,19 +42,6 @@
     # simply create an iterator and that's it.
     return space.iter(w_lis)
 
-def seqiter_new(space, w_seq, w_index):
-    return W_SeqIterObject(w_seq, space.int_w(w_index))
-
-def reverseseqiter_new(space, w_seq, w_index):
-    w_rev = instantiate(W_ReverseSeqIterObject)
-    if space.is_w(w_seq, space.w_None):
-        w_rev.w_seq = space.w_None
-        w_rev.index = -1
-    else:
-        w_rev.w_seq = w_seq
-        w_rev.index = space.int_w(w_index)
-    return w_rev
-
 def frame_new(space):
     new_frame = instantiate(space.FrameClass)   # XXX fish
     return space.wrap(new_frame)
diff --git a/pypy/objspace/std/iterobject.py b/pypy/objspace/std/iterobject.py
--- a/pypy/objspace/std/iterobject.py
+++ b/pypy/objspace/std/iterobject.py
@@ -14,7 +14,7 @@
         self.index = index
 
     def getlength(self, space):
-        if space.is_none(self.w_seq):
+        if self.w_seq is None:
             return space.wrap(0)
         index = self.index
         w_length = space.len(self.w_seq)
@@ -30,17 +30,16 @@
         raise NotImplementedError
 
     def descr_reduce(self, space):
-        from pypy.interpreter.mixedmodule import MixedModule
-        w_mod = space.getbuiltinmodule('_pickle_support')
-        mod = space.interp_w(MixedModule, w_mod)
-        new_inst = mod.get('seqiter_new')
-        tup = [self.w_seq, space.wrap(self.index)]
-        # note that setstate is not called, because this setup already sets the index
-        return space.newtuple([new_inst, space.newtuple(tup)])
+        w_seq = self.w_seq
+        if w_seq is None:
+            return _empty_iterable(space)
+        w_callable = space.builtin.get('iter')
+        items = [w_callable, space.newtuple([w_seq]), space.wrap(self.index)]
+        return space.newtuple(items)
 
     def descr_setstate(self, space, w_state):
         index = space.int_w(w_state)
-        if self.w_seq is not space.w_None:
+        if self.w_seq is not None:
             if index < 0:
                 index = 0
             self.index = index
@@ -69,7 +68,7 @@
     """Sequence iterator implementation for general sequences."""
 
     def descr_next(self, space):
-        if space.is_none(self.w_seq):
+        if self.w_seq is None:
             raise OperationError(space.w_StopIteration, space.w_None)
         try:
             w_item = space.getitem(self.w_seq, space.wrap(self.index))
@@ -88,7 +87,7 @@
     def descr_next(self, space):
         from pypy.objspace.std.listobject import W_ListObject
         w_seq = self.w_seq
-        if space.is_none(w_seq):
+        if w_seq is None:
             raise OperationError(space.w_StopIteration, space.w_None)
         assert isinstance(w_seq, W_ListObject)
         index = self.index
@@ -150,24 +149,20 @@
 
 class W_ReverseSeqIterObject(W_Root):
     def __init__(self, space, w_seq, index=-1):
-        # w_seq is normally a list object, but can be space.w_None after
-        # the iterator is exhausted or after a reduce().  In that case,
-        # self.index == -1.
         self.w_seq = w_seq
         self.index = space.len_w(w_seq) + index
 
     def descr_reduce(self, space):
-        from pypy.interpreter.mixedmodule import MixedModule
-        w_mod = space.getbuiltinmodule('_pickle_support')
-        mod = space.interp_w(MixedModule, w_mod)
-        new_inst = mod.get('reverseseqiter_new')
-        tup = [self.w_seq, space.wrap(self.index)]
-        # note that setstate is not called, because this setup already sets the index
-        return space.newtuple([new_inst, space.newtuple(tup)])
+        w_seq = self.w_seq
+        if w_seq is None:
+            return _empty_iterable(space)
+        w_callable = space.builtin.get('reversed')
+        items = [w_callable, space.newtuple([w_seq]), space.wrap(self.index)]
+        return space.newtuple(items)
 
     def descr_setstate(self, space, w_state):
         index = space.int_w(w_state)
-        if self.w_seq is not space.w_None:
+        if self.w_seq is not None:
             length = space.int_w(space.len(self.w_seq))
             if index < 0: index = 0
             if index >= length: index = length-1
@@ -175,7 +170,7 @@
 
     def descr_length_hint(self, space):
         length = self.index + 1
-        if self.w_seq is space.w_None or space.len_w(self.w_seq) < length:
+        if self.w_seq is None or space.len_w(self.w_seq) < length:
             length = 0
         return space.wrap(length)
 
@@ -200,7 +195,7 @@
 
         # Done
         self.index = -1
-        self.w_seq = space.w_None
+        self.w_seq = None
         raise OperationError(space.w_StopIteration, space.w_None)
 
 W_ReverseSeqIterObject.typedef = TypeDef(
@@ -212,3 +207,8 @@
     __length_hint__ = interp2app(W_ReverseSeqIterObject.descr_length_hint),
 )
 W_ReverseSeqIterObject.typedef.acceptable_as_base_class = False
+
+
+def _empty_iterable(space):
+    w_callable = space.builtin.get('iter')
+    return space.newtuple([w_callable, space.newtuple([space.newtuple([])])])
diff --git a/pypy/objspace/std/test/test_iterobject.py b/pypy/objspace/std/test/test_iterobject.py
--- a/pypy/objspace/std/test/test_iterobject.py
+++ b/pypy/objspace/std/test/test_iterobject.py
@@ -83,6 +83,36 @@
         iterable.__setstate__(3)
         assert next(iterable) == 4
 
+    def test_forward_iter_reduce(self):
+        T = "abc"
+        iterable = iter(T)
+        assert iterable.__reduce__() == (iter, (T, ), 0)
+        assert next(iterable) == "a"
+        assert iterable.__reduce__() == (iter, (T, ), 1)
+        assert next(iterable) == "b"
+        assert iterable.__reduce__() == (iter, (T, ), 2)
+        assert next(iterable) == "c"
+        assert iterable.__reduce__() == (iter, (T, ), 3)
+        raises(StopIteration, next, iterable)
+        assert (iterable.__reduce__() == (iter, ((), )) or   # pypy
+                iterable.__reduce__() == (iter, ("", )))     # cpython
+
+    def test_reversed_iter_reduce(self):
+        T = [1, 2, 3, 4]
+        iterable = reversed(T)
+        assert iterable.__reduce__() == (reversed, (T, ), 3)
+        assert next(iterable) == 4
+        assert iterable.__reduce__() == (reversed, (T, ), 2)
+        assert next(iterable) == 3
+        assert iterable.__reduce__() == (reversed, (T, ), 1)
+        assert next(iterable) == 2
+        assert iterable.__reduce__() == (reversed, (T, ), 0)
+        assert next(iterable) == 1
+        assert iterable.__reduce__() == (reversed, (T, ), -1)
+        raises(StopIteration, next, iterable)
+        assert (iterable.__reduce__() == (iter, ((), )) or   # pypy
+                iterable.__reduce__() == (iter, ([], )))     # cpython
+
     def test_no_len_on_tuple_iter(self):
         iterable = (1,2,3,4)
         raises(TypeError, len, iter(iterable))
@@ -126,7 +156,7 @@
 
     def test_reversed_frees_empty(self):
         import gc
-        for typ in list, unicode:
+        for typ in list, str:
             free = [False]
             class U(typ):
                 def __del__(self):
@@ -138,7 +168,7 @@
 
     def test_reversed_mutation(self):
         n = 10
-        d = range(n)
+        d = list(range(n))
         it = reversed(d)
         next(it)
         next(it)
@@ -148,7 +178,7 @@
         d[1:] = []
         assert it.__length_hint__() == 0
         assert list(it) == []
-        d.extend(xrange(20))
+        d.extend(range(20))
         assert it.__length_hint__() == 0
 
     def test_no_len_on_set_iter(self):


More information about the pypy-commit mailing list