[Python-checkins] cpython (3.5): Issue #24359: Check for changed OrderedDict size during iteration.
eric.snow
python-checkins at python.org
Tue Jun 2 07:40:08 CEST 2015
https://hg.python.org/cpython/rev/141eb4d1b766
changeset: 96473:141eb4d1b766
branch: 3.5
parent: 96471:8631b88c23f6
user: Eric Snow <ericsnowcurrently at gmail.com>
date: Mon Jun 01 23:35:13 2015 -0600
summary:
Issue #24359: Check for changed OrderedDict size during iteration.
files:
Lib/test/test_collections.py | 4 ----
Misc/NEWS | 2 ++
Objects/odictobject.c | 10 ++++++++++
3 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py
--- a/Lib/test/test_collections.py
+++ b/Lib/test/test_collections.py
@@ -1746,10 +1746,6 @@
self.assertEqual(list(reversed(od.items())), list(reversed(pairs)))
def test_detect_deletion_during_iteration(self):
- # XXX This test should also work under cOrderedDict.
- if self.module is c_coll:
- raise unittest.SkipTest("only valid for pure Python OrderedDict")
-
OrderedDict = self.module.OrderedDict
od = OrderedDict.fromkeys('abc')
it = iter(od)
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -19,6 +19,8 @@
- Issue #24348: Drop superfluous incref/decref.
+- Issue #24359: Check for changed OrderedDict size during iteration.
+
What's New in Python 3.5.0 beta 2?
==================================
diff --git a/Objects/odictobject.c b/Objects/odictobject.c
--- a/Objects/odictobject.c
+++ b/Objects/odictobject.c
@@ -1796,6 +1796,7 @@
PyObject_HEAD
int kind;
PyODictObject *di_odict;
+ Py_ssize_t di_size;
PyObject *di_current;
PyObject *di_result; /* reusable result tuple for iteritems */
} odictiterobject;
@@ -1835,6 +1836,14 @@
if (di->di_current == NULL)
goto done; /* We're already done. */
+ /* Check for unsupported changes. */
+ if (di->di_size != PyODict_SIZE(di->di_odict)) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "OrderedDict changed size during iteration");
+ di->di_size = -1; /* Make this state sticky */
+ return NULL;
+ }
+
/* Get the key. */
node = _odict_find_node(di->di_odict, di->di_current);
if (node == NULL) {
@@ -2033,6 +2042,7 @@
node = reversed ? _odict_LAST(od) : _odict_FIRST(od);
di->di_current = node ? _odictnode_KEY(node) : NULL;
Py_XINCREF(di->di_current);
+ di->di_size = PyODict_SIZE(od);
di->di_odict = od;
Py_INCREF(od);
--
Repository URL: https://hg.python.org/cpython
More information about the Python-checkins
mailing list