with self.assertRaises(RuntimeError):
for i in d:
del d[0]
- d[1] = 1
+ d[0] = 0
+
+ def test_mutating_iteration_delete_over_values(self):
+ # change dict content during iteration
+ d = {}
+ d[0] = 0
+ with self.assertRaises(RuntimeError):
+ for i in d.values():
+ del d[0]
+ d[0] = 0
+
+ def test_mutating_iteration_delete_over_items(self):
+ # change dict content during iteration
+ d = {}
+ d[0] = 0
+ with self.assertRaises(RuntimeError):
+ for i in d.items():
+ del d[0]
+ d[0] = 0
def test_mutating_lookup(self):
# changing dict during a lookup (issue #14417)
-Changing `dict` keys during iteration will now be detected in certain corner cases where the number of keys isn't changed (but they keys themselves are), and a `RuntimeError` will be raised.
\ No newline at end of file
+Changing ``dict`` keys during iteration of the dict itself, ``keys()``,
+``values()``, or ``items()`` will now be detected in certain corner cases where
+keys are deleted/added so that the number of keys isn't changed.
+A `RuntimeError` will be raised after ``len(dict)`` iterations.
+Contributed by Thomas Perl.
goto fail;
value = entry_ptr->me_value;
}
+ // We found an element, but did not expect it
+ if (di->len == 0) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "dictionary keys changed during iteration");
+ goto fail;
+ }
di->di_pos = i+1;
di->len--;
Py_INCREF(value);
key = entry_ptr->me_key;
value = entry_ptr->me_value;
}
+ // We found an element, but did not expect it
+ if (di->len == 0) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "dictionary keys changed during iteration");
+ goto fail;
+ }
di->di_pos = i+1;
di->len--;
Py_INCREF(key);