Author: Armin Rigo <[email protected]>
Branch: py3.5
Changeset: r89021:e47c8f353a9e
Date: 2016-12-12 14:54 +0100
http://bitbucket.org/pypy/pypy/changeset/e47c8f353a9e/

Log:    fix pickling deque_iterator and deque_reverse_iterator

diff --git a/pypy/module/_collections/interp_deque.py 
b/pypy/module/_collections/interp_deque.py
--- a/pypy/module/_collections/interp_deque.py
+++ b/pypy/module/_collections/interp_deque.py
@@ -610,6 +610,14 @@
         self.lock = deque.getlock()
         check_nonneg(self.index)
 
+    def _move_to(self, index):
+        if index < 0:
+            return
+        self.counter = self.deque.len - index
+        if self.counter <= 0:
+            return
+        self.block, self.index = self.deque.locate(index)
+
     def iter(self):
         return self.space.wrap(self)
 
@@ -621,7 +629,7 @@
         if self.lock is not self.deque.lock:
             self.counter = 0
             raise oefmt(space.w_RuntimeError, "deque mutated during iteration")
-        if self.counter == 0:
+        if self.counter <= 0:
             raise OperationError(space.w_StopIteration, space.w_None)
         self.counter -= 1
         ri = self.index
@@ -634,15 +642,19 @@
         return w_x
 
     def reduce(self):
+        w_i = self.space.wrap(self.deque.len - self.counter)
         return self.space.newtuple([self.space.gettypefor(W_DequeIter),
-                                    self.space.newtuple([self.deque])])
+                                    self.space.newtuple([self.deque, w_i])])
 
-def W_DequeIter__new__(space, w_subtype, w_deque):
+@unwrap_spec(index=int)
+def W_DequeIter__new__(space, w_subtype, w_deque, index=0):
     w_self = space.allocate_instance(W_DequeIter, w_subtype)
     if not isinstance(w_deque, W_Deque):
         raise oefmt(space.w_TypeError, "must be collections.deque, not %T", 
w_deque)
 
-    W_DequeIter.__init__(space.interp_w(W_DequeIter, w_self), w_deque)
+    self = space.interp_w(W_DequeIter, w_self)
+    W_DequeIter.__init__(self, w_deque)
+    self._move_to(index)
     return w_self
 
 W_DequeIter.typedef = TypeDef("_collections.deque_iterator",
@@ -666,6 +678,14 @@
         self.lock = deque.getlock()
         check_nonneg(self.index)
 
+    def _move_to(self, index):
+        if index < 0:
+            return
+        self.counter = self.deque.len - index
+        if self.counter <= 0:
+            return
+        self.block, self.index = self.deque.locate(self.counter - 1)
+
     def iter(self):
         return self.space.wrap(self)
 
@@ -677,7 +697,7 @@
         if self.lock is not self.deque.lock:
             self.counter = 0
             raise oefmt(space.w_RuntimeError, "deque mutated during iteration")
-        if self.counter == 0:
+        if self.counter <= 0:
             raise OperationError(space.w_StopIteration, space.w_None)
         self.counter -= 1
         ri = self.index
@@ -690,15 +710,19 @@
         return w_x
 
     def reduce(self):
+        w_i = self.space.wrap(self.deque.len - self.counter)
         return self.space.newtuple([self.space.gettypefor(W_DequeRevIter),
-                                    self.space.newtuple([self.deque])])
+                                    self.space.newtuple([self.deque, w_i])])
 
-def W_DequeRevIter__new__(space, w_subtype, w_deque):
+@unwrap_spec(index=int)
+def W_DequeRevIter__new__(space, w_subtype, w_deque, index=0):
     w_self = space.allocate_instance(W_DequeRevIter, w_subtype)
     if not isinstance(w_deque, W_Deque):
         raise oefmt(space.w_TypeError, "must be collections.deque, not %T", 
w_deque)
 
-    W_DequeRevIter.__init__(space.interp_w(W_DequeRevIter, w_self), w_deque)
+    self = space.interp_w(W_DequeRevIter, w_self)
+    W_DequeRevIter.__init__(self, w_deque)
+    self._move_to(index)
     return w_self
 
 W_DequeRevIter.typedef = TypeDef("_collections.deque_reverse_iterator",
diff --git a/pypy/module/_collections/test/test_deque.py 
b/pypy/module/_collections/test/test_deque.py
--- a/pypy/module/_collections/test/test_deque.py
+++ b/pypy/module/_collections/test/test_deque.py
@@ -331,18 +331,28 @@
     def test_DequeIter_pickle(self):
         from _collections import deque
         import pickle
-        d = deque([1,2,3])
-        iterator = iter(d)
-        copy = pickle.loads(pickle.dumps(iterator))
-        assert list(iterator) == list(copy)
+        for i in range(4):
+            d = deque([1,2,3])
+            iterator = iter(d)
+            assert iterator.__reduce__() == (type(iterator), (d, 0))
+            for j in range(i):
+                next(iterator)
+            assert iterator.__reduce__() == (type(iterator), (d, i))
+            copy = pickle.loads(pickle.dumps(iterator))
+            assert list(iterator) == list(copy)
 
     def test_DequeRevIter_pickle(self):
         from _collections import deque
         import pickle
-        d = deque([1,2,3])
-        iterator = reversed(d)
-        copy = pickle.loads(pickle.dumps(iterator))
-        assert list(iterator) == list(copy)
+        for i in range(4):
+            d = deque([1,2,3])
+            iterator = reversed(d)
+            assert iterator.__reduce__() == (type(iterator), (d, 0))
+            for j in range(i):
+                assert next(iterator)
+            assert iterator.__reduce__() == (type(iterator), (d, i))
+            copy = pickle.loads(pickle.dumps(iterator))
+            assert list(iterator) == list(copy)
 
     def test_deque_mul(self):
         from _collections import deque
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to