Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a0d416f

Browse files
Issue #26482: Allowed pickling recursive dequeues.
1 parent 841b930 commit a0d416f

3 files changed

Lines changed: 56 additions & 50 deletions

File tree

Lib/test/test_deque.py

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -622,20 +622,22 @@ def test_roundtrip_iter_init(self):
622622
self.assertEqual(list(d), list(e))
623623

624624
def test_pickle(self):
625-
d = deque(range(200))
626-
for i in range(pickle.HIGHEST_PROTOCOL + 1):
627-
s = pickle.dumps(d, i)
628-
e = pickle.loads(s)
629-
self.assertNotEqual(id(d), id(e))
630-
self.assertEqual(list(d), list(e))
631-
632-
## def test_pickle_recursive(self):
633-
## d = deque('abc')
634-
## d.append(d)
635-
## for i in range(pickle.HIGHEST_PROTOCOL + 1):
636-
## e = pickle.loads(pickle.dumps(d, i))
637-
## self.assertNotEqual(id(d), id(e))
638-
## self.assertEqual(id(e), id(e[-1]))
625+
for d in deque(range(200)), deque(range(200), 100):
626+
for i in range(pickle.HIGHEST_PROTOCOL + 1):
627+
s = pickle.dumps(d, i)
628+
e = pickle.loads(s)
629+
self.assertNotEqual(id(e), id(d))
630+
self.assertEqual(list(e), list(d))
631+
self.assertEqual(e.maxlen, d.maxlen)
632+
633+
def test_pickle_recursive(self):
634+
for d in deque('abc'), deque('abc', 3):
635+
d.append(d)
636+
for i in range(pickle.HIGHEST_PROTOCOL + 1):
637+
e = pickle.loads(pickle.dumps(d, i))
638+
self.assertNotEqual(id(e), id(d))
639+
self.assertEqual(id(e[-1]), id(e))
640+
self.assertEqual(e.maxlen, d.maxlen)
639641

640642
def test_iterator_pickle(self):
641643
data = deque(range(200))
@@ -827,24 +829,26 @@ def test_copy_pickle(self):
827829
self.assertEqual(type(d), type(e))
828830
self.assertEqual(list(d), list(e))
829831

830-
## def test_pickle(self):
831-
## d = Deque('abc')
832-
## d.append(d)
833-
##
834-
## e = pickle.loads(pickle.dumps(d))
835-
## self.assertNotEqual(id(d), id(e))
836-
## self.assertEqual(type(d), type(e))
837-
## dd = d.pop()
838-
## ee = e.pop()
839-
## self.assertEqual(id(e), id(ee))
840-
## self.assertEqual(d, e)
841-
##
842-
## d.x = d
843-
## e = pickle.loads(pickle.dumps(d))
844-
## self.assertEqual(id(e), id(e.x))
845-
##
846-
## d = DequeWithBadIter('abc')
847-
## self.assertRaises(TypeError, pickle.dumps, d)
832+
def test_pickle_recursive(self):
833+
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
834+
for d in Deque('abc'), Deque('abc', 3):
835+
d.append(d)
836+
837+
e = pickle.loads(pickle.dumps(d, proto))
838+
self.assertNotEqual(id(e), id(d))
839+
self.assertEqual(type(e), type(d))
840+
self.assertEqual(e.maxlen, d.maxlen)
841+
dd = d.pop()
842+
ee = e.pop()
843+
self.assertEqual(id(ee), id(e))
844+
self.assertEqual(e, d)
845+
846+
d.x = d
847+
e = pickle.loads(pickle.dumps(d, proto))
848+
self.assertEqual(id(e.x), id(e))
849+
850+
for d in DequeWithBadIter('abc'), DequeWithBadIter('abc', 2):
851+
self.assertRaises(TypeError, pickle.dumps, d, proto)
848852

849853
def test_weakref(self):
850854
d = deque('gallahad')

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ Core and Builtins
201201
Library
202202
-------
203203

204+
- Issue #26482: Allowed pickling recursive dequeues.
205+
204206
- Issue #26335: Make mmap.write() return the number of bytes written like
205207
other write methods. Patch by Jakub Stasiak.
206208

Modules/_collectionsmodule.c

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,31 +1296,31 @@ deque_traverse(dequeobject *deque, visitproc visit, void *arg)
12961296
static PyObject *
12971297
deque_reduce(dequeobject *deque)
12981298
{
1299-
PyObject *dict, *result, *aslist;
1299+
PyObject *dict, *it;
13001300
_Py_IDENTIFIER(__dict__);
13011301

13021302
dict = _PyObject_GetAttrId((PyObject *)deque, &PyId___dict__);
1303-
if (dict == NULL)
1303+
if (dict == NULL) {
1304+
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
1305+
return NULL;
1306+
}
13041307
PyErr_Clear();
1305-
aslist = PySequence_List((PyObject *)deque);
1306-
if (aslist == NULL) {
1307-
Py_XDECREF(dict);
1308+
dict = Py_None;
1309+
Py_INCREF(dict);
1310+
}
1311+
1312+
it = PyObject_GetIter((PyObject *)deque);
1313+
if (it == NULL) {
1314+
Py_DECREF(dict);
13081315
return NULL;
13091316
}
1310-
if (dict == NULL) {
1311-
if (deque->maxlen < 0)
1312-
result = Py_BuildValue("O(O)", Py_TYPE(deque), aslist);
1313-
else
1314-
result = Py_BuildValue("O(On)", Py_TYPE(deque), aslist, deque->maxlen);
1315-
} else {
1316-
if (deque->maxlen < 0)
1317-
result = Py_BuildValue("O(OO)O", Py_TYPE(deque), aslist, Py_None, dict);
1318-
else
1319-
result = Py_BuildValue("O(On)O", Py_TYPE(deque), aslist, deque->maxlen, dict);
1317+
1318+
if (deque->maxlen < 0) {
1319+
return Py_BuildValue("O()NN", Py_TYPE(deque), dict, it);
1320+
}
1321+
else {
1322+
return Py_BuildValue("O(()n)NN", Py_TYPE(deque), deque->maxlen, dict, it);
13201323
}
1321-
Py_XDECREF(dict);
1322-
Py_DECREF(aslist);
1323-
return result;
13241324
}
13251325

13261326
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");

0 commit comments

Comments
 (0)