]> granicus.if.org Git - python/commitdiff
SF patch #1062279: deque pickling problems
authorRaymond Hettinger <python@rcn.com>
Tue, 9 Nov 2004 07:27:35 +0000 (07:27 +0000)
committerRaymond Hettinger <python@rcn.com>
Tue, 9 Nov 2004 07:27:35 +0000 (07:27 +0000)
(Contributed by Dima Dorfman.)

* Support pickling of dictionaries in instances of deque subclasses.
* Support pickling of recursive deques.

Lib/test/test_deque.py
Modules/collectionsmodule.c

index 19b0afcd846bf03a2b1b48815aa978cdedfbe1f8..0a6c1f97ff7a04cb07cd7fc8b961008bf3f70b65 100644 (file)
@@ -297,10 +297,19 @@ class TestBasic(unittest.TestCase):
 
     def test_pickle(self):
         d = deque(xrange(200))
-        s = pickle.dumps(d)
-        e = pickle.loads(s)
-        self.assertNotEqual(id(d), id(e))
-        self.assertEqual(list(d), list(e))
+        for i in (0, 1, 2):
+            s = pickle.dumps(d, i)
+            e = pickle.loads(s)
+            self.assertNotEqual(id(d), id(e))
+            self.assertEqual(list(d), list(e))
+
+    def test_pickle_recursive(self):
+        d = deque('abc')
+        d.append(d)
+        for i in (0, 1, 2):
+            e = pickle.loads(pickle.dumps(d, i))
+            self.assertNotEqual(id(d), id(e))
+            self.assertEqual(id(e), id(e[-1]))
 
     def test_deepcopy(self):
         mut = [10]
@@ -430,6 +439,10 @@ class TestVariousIteratorArgs(unittest.TestCase):
 class Deque(deque):
     pass
 
+class DequeWithBadIter(deque):
+    def __iter__(self):
+        raise TypeError
+
 class TestSubclass(unittest.TestCase):
 
     def test_basics(self):
@@ -472,6 +485,25 @@ class TestSubclass(unittest.TestCase):
         self.assertEqual(type(d), type(e))
         self.assertEqual(list(d), list(e))
 
+    def test_pickle(self):
+        d = Deque('abc')
+        d.append(d)
+
+        e = pickle.loads(pickle.dumps(d))
+        self.assertNotEqual(id(d), id(e))
+        self.assertEqual(type(d), type(e))
+        dd = d.pop()
+        ee = e.pop()
+        self.assertEqual(id(e), id(ee))
+        self.assertEqual(d, e)
+
+        d.x = d
+        e = pickle.loads(pickle.dumps(d))
+        self.assertEqual(id(e), id(e.x))
+
+        d = DequeWithBadIter('abc')
+        self.assertRaises(TypeError, pickle.dumps, d)
+
     def test_weakref(self):
         d = deque('gallahad')
         p = proxy(d)
index 10b08f941f9dd3873c268e415c455e148ec8d7e3..ed10999f01a08cffbc8a30019bc65a3b3492bc14 100644 (file)
@@ -550,19 +550,21 @@ PyDoc_STRVAR(copy_doc, "Return a shallow copy of a deque.");
 static PyObject *
 deque_reduce(dequeobject *deque)
 {
-       PyObject *seq, *args, *result;
+       PyObject *dict, *result, *it;
 
-       seq = PySequence_Tuple((PyObject *)deque);
-       if (seq == NULL)
-               return NULL;
-       args = PyTuple_Pack(1, seq);
-       if (args == NULL) {
-               Py_DECREF(seq);
+       dict = PyObject_GetAttrString((PyObject *)deque, "__dict__");
+       if (dict == NULL) {
+               PyErr_Clear();
+               dict = Py_None;
+               Py_INCREF(dict);
+       }
+       it = PyObject_GetIter((PyObject *)deque);
+       if (it == NULL) {
+               Py_DECREF(dict);
                return NULL;
        }
-       result = PyTuple_Pack(2, deque->ob_type, args);
-       Py_DECREF(seq);
-       Py_DECREF(args);
+       result = Py_BuildValue("O()ON", deque->ob_type, dict, it);
+       Py_DECREF(dict);
        return result;
 }