]> granicus.if.org Git - python/commitdiff
Issue #14417: Mutating a dict during lookup now restarts the lookup instead of raisin...
authorAntoine Pitrou <solipsis@pitrou.net>
Sun, 13 May 2012 18:48:01 +0000 (20:48 +0200)
committerAntoine Pitrou <solipsis@pitrou.net>
Sun, 13 May 2012 18:48:01 +0000 (20:48 +0200)
Doc/library/stdtypes.rst
Doc/whatsnew/3.3.rst
Lib/test/test_dict.py
Misc/NEWS
Objects/dictobject.c

index 212fd5e7611eaaeda2d438c9e0deb17110a7856b..a34b1cfd271c8c00d6c25fa91230c4f73d0f1ff5 100644 (file)
@@ -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*.
index 35920b9b13a85d4cd9bbdf223b5d751520c9bbd6..148324e6aaca67c0dfa26927a146835522b62862 100644 (file)
@@ -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()``.
 
index 426f76e9e8c4a9b4ba35cb27f7c287898a6a0d11..dd4d552875b610beaca8d10850c3afb2d9a5cf6d 100644 (file)
@@ -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 = {}
index 031738d95aa103d77652d44efa7be6b2bbeab9aa..f27dab53def84a93ca3946c90f845a11810e1b81 100644 (file)
--- 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.
 
index 077f3cd9bd3ad20594dc73599ac21b859a36a993..fd1d46c6c32e785e8e286188be41258b537d8b6b 100644 (file)
@@ -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)