Commit 9a234903 authored by Antoine Pitrou's avatar Antoine Pitrou

Issue #14417: Mutating a dict during lookup now restarts the lookup instead of...

Issue #14417: Mutating a dict during lookup now restarts the lookup instead of raising a RuntimeError (undoes issue #14205).
parent 7feb9f42
...@@ -2210,10 +2210,6 @@ pairs within braces, for example: ``{'jack': 4098, 'sjoerd': 4127}`` or ``{4098: ...@@ -2210,10 +2210,6 @@ pairs within braces, for example: ``{'jack': 4098, 'sjoerd': 4127}`` or ``{4098:
See :class:`collections.Counter` for a complete implementation including See :class:`collections.Counter` for a complete implementation including
other methods helpful for accumulating and managing tallies. other methods helpful for accumulating and managing tallies.
.. versionchanged:: 3.3
If the dict is modified during the lookup, a :exc:`RuntimeError`
exception is now raised.
.. describe:: d[key] = value .. describe:: d[key] = value
Set ``d[key]`` to *value*. Set ``d[key]`` to *value*.
......
...@@ -557,13 +557,6 @@ Some smaller changes made to the core Python language are: ...@@ -557,13 +557,6 @@ Some smaller changes made to the core Python language are:
(:issue:`12170`) (:issue:`12170`)
* A dict lookup now raises a :exc:`RuntimeError` if the dict is modified during
the lookup. If you implement your own comparison function for objects used
as dict keys and the dict is shared by multiple threads, access to the dict
should be protected by a lock.
(:issue:`14205`)
* New methods have been added to :class:`list` and :class:`bytearray`: * New methods have been added to :class:`list` and :class:`bytearray`:
``copy()`` and ``clear()``. ``copy()`` and ``clear()``.
......
...@@ -411,7 +411,7 @@ class DictTest(unittest.TestCase): ...@@ -411,7 +411,7 @@ class DictTest(unittest.TestCase):
d[i+1] = 1 d[i+1] = 1
def test_mutating_lookup(self): def test_mutating_lookup(self):
# changing dict during a lookup # changing dict during a lookup (issue #14417)
class NastyKey: class NastyKey:
mutate_dict = None mutate_dict = None
...@@ -433,9 +433,8 @@ class DictTest(unittest.TestCase): ...@@ -433,9 +433,8 @@ class DictTest(unittest.TestCase):
key2 = NastyKey(2) key2 = NastyKey(2)
d = {key1: 1} d = {key1: 1}
NastyKey.mutate_dict = (d, key1) NastyKey.mutate_dict = (d, key1)
with self.assertRaisesRegex(RuntimeError, d[key2] = 2
'dictionary changed size during lookup'): self.assertEqual(d, {key2: 2})
d[key2] = 2
def test_repr(self): def test_repr(self):
d = {} d = {}
......
...@@ -10,6 +10,9 @@ What's New in Python 3.3.0 Alpha 4? ...@@ -10,6 +10,9 @@ What's New in Python 3.3.0 Alpha 4?
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #14417: Mutating a dict during lookup now restarts the lookup instead
of raising a RuntimeError (undoes issue #14205).
- Issue #14738: Speed-up UTF-8 decoding on non-ASCII data. Patch by Serhiy - Issue #14738: Speed-up UTF-8 decoding on non-ASCII data. Patch by Serhiy
Storchaka. Storchaka.
......
...@@ -439,12 +439,15 @@ lookdict(PyDictObject *mp, PyObject *key, ...@@ -439,12 +439,15 @@ lookdict(PyDictObject *mp, PyObject *key,
register size_t i; register size_t i;
register size_t perturb; register size_t perturb;
register PyDictKeyEntry *freeslot; register PyDictKeyEntry *freeslot;
register size_t mask = DK_MASK(mp->ma_keys); register size_t mask;
PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0]; PyDictKeyEntry *ep0;
register PyDictKeyEntry *ep; register PyDictKeyEntry *ep;
register int cmp; register int cmp;
PyObject *startkey; PyObject *startkey;
top:
mask = DK_MASK(mp->ma_keys);
ep0 = &mp->ma_keys->dk_entries[0];
i = (size_t)hash & mask; i = (size_t)hash & mask;
ep = &ep0[i]; ep = &ep0[i];
if (ep->me_key == NULL || ep->me_key == key) { if (ep->me_key == NULL || ep->me_key == key) {
...@@ -468,9 +471,8 @@ lookdict(PyDictObject *mp, PyObject *key, ...@@ -468,9 +471,8 @@ lookdict(PyDictObject *mp, PyObject *key,
} }
} }
else { else {
PyErr_SetString(PyExc_RuntimeError, /* The dict was mutated, restart */
"dictionary changed size during lookup"); goto top;
return NULL;
} }
} }
freeslot = NULL; freeslot = NULL;
...@@ -510,9 +512,8 @@ lookdict(PyDictObject *mp, PyObject *key, ...@@ -510,9 +512,8 @@ lookdict(PyDictObject *mp, PyObject *key,
} }
} }
else { else {
PyErr_SetString(PyExc_RuntimeError, /* The dict was mutated, restart */
"dictionary changed size during lookup"); goto top;
return NULL;
} }
} }
else if (ep->me_key == dummy && freeslot == NULL) else if (ep->me_key == dummy && freeslot == NULL)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment