From ddce13018ef23ef64c6c71c946e5a7a1595cc425 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Thu, 24 Feb 2022 15:58:55 +0900 Subject: [PATCH 1/4] Add test for regression --- Lib/test/test_dict.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index 66f5d56deeaaf8..e60ae4309cbc18 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -1077,6 +1077,23 @@ def test_splittable_popitem(self): self.assertEqual(list(a), ['x', 'y']) self.assertEqual(list(b), ['x', 'y', 'z']) + @support.cpython_only + def test_splittable_update(self): + """dict.update(other) must preserve order in other.""" + class C: + def __init__(self, order): + if order: + self.a, self.b, self.c = 1, 2, 3 + else: + self.c, self.b, self.a = 1, 2, 3 + o = C(True) + o = C(False) # o.__dict__ has reversed order. + self.assertEqual(list(o.__dict__), ["c", "b", "a"]) + + d = {} + d.update(o.__dict__) + self.assertEqual(list(d), ["c", "b", "a"]) + def test_iterator_pickling(self): for proto in range(pickle.HIGHEST_PROTOCOL + 1): data = {1:"a", 2:"b", 3:"c"} From 7b95b69941b962f6975748971c1085acb4dd98e2 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Thu, 24 Feb 2022 16:31:29 +0900 Subject: [PATCH 2/4] bpo-40116: dict: Fix regression caused by GH-28520. --- Objects/dictobject.c | 72 +++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 41 deletions(-) diff --git a/Objects/dictobject.c b/Objects/dictobject.c index fca879f4e3cdd1..5e929cb5f85301 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2528,8 +2528,6 @@ static int dict_merge(PyObject *a, PyObject *b, int override) { PyDictObject *mp, *other; - Py_ssize_t i, n; - PyDictKeyEntry *entry, *ep0; assert(0 <= override && override <= 2); @@ -2596,54 +2594,46 @@ dict_merge(PyObject *a, PyObject *b, int override) return -1; } } - ep0 = DK_ENTRIES(other->ma_keys); - for (i = 0, n = other->ma_keys->dk_nentries; i < n; i++) { - PyObject *key, *value; - Py_hash_t hash; - entry = &ep0[i]; - key = entry->me_key; - hash = entry->me_hash; - if (other->ma_values) - value = other->ma_values->values[i]; - else - value = entry->me_value; - - if (value != NULL) { - int err = 0; + + Py_ssize_t pos = 0; + PyObject *key, *value; + Py_hash_t hash; + Py_ssize_t orig_nentries = other->ma_keys->dk_nentries; + while (_PyDict_Next(b, &pos, &key, &value, &hash)) { + int err = 0; + Py_INCREF(key); + Py_INCREF(value); + if (override == 1) { Py_INCREF(key); Py_INCREF(value); - if (override == 1) { + err = insertdict(mp, key, hash, value); + } + else { + err = _PyDict_Contains_KnownHash(a, key, hash); + if (err == 0) { Py_INCREF(key); Py_INCREF(value); err = insertdict(mp, key, hash, value); } - else { - err = _PyDict_Contains_KnownHash(a, key, hash); - if (err == 0) { - Py_INCREF(key); - Py_INCREF(value); - err = insertdict(mp, key, hash, value); - } - else if (err > 0) { - if (override != 0) { - _PyErr_SetKeyError(key); - Py_DECREF(value); - Py_DECREF(key); - return -1; - } - err = 0; + else if (err > 0) { + if (override != 0) { + _PyErr_SetKeyError(key); + Py_DECREF(value); + Py_DECREF(key); + return -1; } + err = 0; } - Py_DECREF(value); - Py_DECREF(key); - if (err != 0) - return -1; + } + Py_DECREF(value); + Py_DECREF(key); + if (err != 0) + return -1; - if (n != other->ma_keys->dk_nentries) { - PyErr_SetString(PyExc_RuntimeError, - "dict mutated during update"); - return -1; - } + if (orig_nentries != other->ma_keys->dk_nentries) { + PyErr_SetString(PyExc_RuntimeError, + "dict mutated during update"); + return -1; } } } From e0a3dfcea8fa24bf74c30e1533fb853c53d8f44e Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Thu, 24 Feb 2022 16:34:20 +0900 Subject: [PATCH 3/4] Add news entry --- .../Core and Builtins/2022-02-24-16-34-17.bpo-40116.AeVGG2.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-02-24-16-34-17.bpo-40116.AeVGG2.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-02-24-16-34-17.bpo-40116.AeVGG2.rst b/Misc/NEWS.d/next/Core and Builtins/2022-02-24-16-34-17.bpo-40116.AeVGG2.rst new file mode 100644 index 00000000000000..fb3f82e880d0a7 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-02-24-16-34-17.bpo-40116.AeVGG2.rst @@ -0,0 +1,2 @@ +Fix regression that dict.update(other) may don't respect iterate order of +other when other is key sharing dict. From cdd86d43978c5c068fc974db5cf0ddd39a520735 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Thu, 3 Mar 2022 12:46:33 +0900 Subject: [PATCH 4/4] fix doc issue --- .../next/Library/2022-02-09-22-40-11.bpo-46643.aBlIx1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2022-02-09-22-40-11.bpo-46643.aBlIx1.rst b/Misc/NEWS.d/next/Library/2022-02-09-22-40-11.bpo-46643.aBlIx1.rst index e8b4d66e943f68..82ff831e3887df 100644 --- a/Misc/NEWS.d/next/Library/2022-02-09-22-40-11.bpo-46643.aBlIx1.rst +++ b/Misc/NEWS.d/next/Library/2022-02-09-22-40-11.bpo-46643.aBlIx1.rst @@ -1 +1 @@ -In :func:`typing.get_type_hints`, support evaluating stringified ``ParamSpecArgs`` and ``ParamSpecKwargs`` annotations. Patch by Gregory Beauregard. \ No newline at end of file +In :func:`typing.get_type_hints`, support evaluating stringified ``ParamSpecArgs`` and ``ParamSpecKwargs`` annotations. Patch by Gregory Beauregard.