summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2012-05-13 18:48:01 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2012-05-13 18:48:01 (GMT)
commit9a2349030a706433b519ae99816fc540ecefc143 (patch)
tree8afad14bc8fa10812c97a35ef4fc1ab09521ee43
parent7feb9f42258ff72ce1d3628c5ccc261c2ca238b9 (diff)
downloadcpython-9a2349030a706433b519ae99816fc540ecefc143.zip
cpython-9a2349030a706433b519ae99816fc540ecefc143.tar.gz
cpython-9a2349030a706433b519ae99816fc540ecefc143.tar.bz2
Issue #14417: Mutating a dict during lookup now restarts the lookup instead of raising a RuntimeError (undoes issue #14205).
-rw-r--r--Doc/library/stdtypes.rst4
-rw-r--r--Doc/whatsnew/3.3.rst7
-rw-r--r--Lib/test/test_dict.py7
-rw-r--r--Misc/NEWS3
-rw-r--r--Objects/dictobject.c17
5 files changed, 15 insertions, 23 deletions
diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst
index 212fd5e..a34b1cf 100644
--- a/Doc/library/stdtypes.rst
+++ b/Doc/library/stdtypes.rst
@@ -2210,10 +2210,6 @@ pairs within braces, for example: ``{'jack': 4098, 'sjoerd': 4127}`` or ``{4098:
See :class:`collections.Counter` for a complete implementation including
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
Set ``d[key]`` to *value*.
diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst
index 35920b9..148324e 100644
--- a/Doc/whatsnew/3.3.rst
+++ b/Doc/whatsnew/3.3.rst
@@ -557,13 +557,6 @@ Some smaller changes made to the core Python language are:
(: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`:
``copy()`` and ``clear()``.
diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py
index 426f76e..dd4d552 100644
--- a/Lib/test/test_dict.py
+++ b/Lib/test/test_dict.py
@@ -411,7 +411,7 @@ class DictTest(unittest.TestCase):
d[i+1] = 1
def test_mutating_lookup(self):
- # changing dict during a lookup
+ # changing dict during a lookup (issue #14417)
class NastyKey:
mutate_dict = None
@@ -433,9 +433,8 @@ class DictTest(unittest.TestCase):
key2 = NastyKey(2)
d = {key1: 1}
NastyKey.mutate_dict = (d, key1)
- with self.assertRaisesRegex(RuntimeError,
- 'dictionary changed size during lookup'):
- d[key2] = 2
+ d[key2] = 2
+ self.assertEqual(d, {key2: 2})
def test_repr(self):
d = {}
diff --git a/Misc/NEWS b/Misc/NEWS
index 031738d..f27dab5 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ What's New in Python 3.3.0 Alpha 4?
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
Storchaka.
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 077f3cd..fd1d46c 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -439,12 +439,15 @@ lookdict(PyDictObject *mp, PyObject *key,
register size_t i;
register size_t perturb;
register PyDictKeyEntry *freeslot;
- register size_t mask = DK_MASK(mp->ma_keys);
- PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0];
+ register size_t mask;
+ PyDictKeyEntry *ep0;
register PyDictKeyEntry *ep;
register int cmp;
PyObject *startkey;
+top:
+ mask = DK_MASK(mp->ma_keys);
+ ep0 = &mp->ma_keys->dk_entries[0];
i = (size_t)hash & mask;
ep = &ep0[i];
if (ep->me_key == NULL || ep->me_key == key) {
@@ -468,9 +471,8 @@ lookdict(PyDictObject *mp, PyObject *key,
}
}
else {
- PyErr_SetString(PyExc_RuntimeError,
- "dictionary changed size during lookup");
- return NULL;
+ /* The dict was mutated, restart */
+ goto top;
}
}
freeslot = NULL;
@@ -510,9 +512,8 @@ lookdict(PyDictObject *mp, PyObject *key,
}
}
else {
- PyErr_SetString(PyExc_RuntimeError,
- "dictionary changed size during lookup");
- return NULL;
+ /* The dict was mutated, restart */
+ goto top;
}
}
else if (ep->me_key == dummy && freeslot == NULL)