pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/a5259fb05d03f4871837c14fed704541a20896c0

aa60c69660fa.css" /> bpo-34574: Prevent OrderedDict iterators from exhaustion during pickl… · python/cpython@a5259fb · GitHub
Skip to content

Commit a5259fb

Browse files
sir-sigurdserhiy-storchaka
authored andcommitted
bpo-34574: Prevent OrderedDict iterators from exhaustion during pickling. (GH-9051)
1 parent 8c9fd9c commit a5259fb

3 files changed

Lines changed: 28 additions & 28 deletions

File tree

Lib/test/test_ordered_dict.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,23 @@ def test_key_change_during_iteration(self):
732732
del od['c']
733733
self.assertEqual(list(od), list('bdeaf'))
734734

735+
def test_iterators_pickling(self):
736+
OrderedDict = self.OrderedDict
737+
pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
738+
od = OrderedDict(pairs)
739+
740+
for method_name in ('keys', 'values', 'items'):
741+
meth = getattr(od, method_name)
742+
expected = list(meth())[1:]
743+
for i in range(pickle.HIGHEST_PROTOCOL + 1):
744+
with self.subTest(method_name=method_name, protocol=i):
745+
it = iter(meth())
746+
next(it)
747+
p = pickle.dumps(it, i)
748+
unpickled = pickle.loads(p)
749+
self.assertEqual(list(unpickled), expected)
750+
self.assertEqual(list(it), expected)
751+
735752

736753
class PurePythonOrderedDictSubclassTests(PurePythonOrderedDictTests):
737754

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
OrderedDict iterators are not exhausted during pickling anymore. Patch by
2+
Sergey Fedoseev.

Objects/odictobject.c

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1805,38 +1805,19 @@ PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
18051805
static PyObject *
18061806
odictiter_reduce(odictiterobject *di)
18071807
{
1808-
PyObject *list, *iter;
1809-
1810-
list = PyList_New(0);
1811-
if (!list)
1812-
return NULL;
1808+
/* copy the iterator state */
1809+
odictiterobject tmp = *di;
1810+
Py_XINCREF(tmp.di_odict);
1811+
Py_XINCREF(tmp.di_current);
18131812

18141813
/* iterate the temporary into a list */
1815-
for(;;) {
1816-
PyObject *element = odictiter_iternext(di);
1817-
if (element) {
1818-
if (PyList_Append(list, element)) {
1819-
Py_DECREF(element);
1820-
Py_DECREF(list);
1821-
return NULL;
1822-
}
1823-
Py_DECREF(element);
1824-
}
1825-
else {
1826-
/* done iterating? */
1827-
break;
1828-
}
1829-
}
1830-
if (PyErr_Occurred()) {
1831-
Py_DECREF(list);
1832-
return NULL;
1833-
}
1834-
iter = _PyObject_GetBuiltin("iter");
1835-
if (iter == NULL) {
1836-
Py_DECREF(list);
1814+
PyObject *list = PySequence_List((PyObject*)&tmp);
1815+
Py_XDECREF(tmp.di_odict);
1816+
Py_XDECREF(tmp.di_current);
1817+
if (list == NULL) {
18371818
return NULL;
18381819
}
1839-
return Py_BuildValue("N(N)", iter, list);
1820+
return Py_BuildValue("N(N)", _PyObject_GetBuiltin("iter"), list);
18401821
}
18411822

18421823
static PyMethodDef odictiter_methods[] = {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy