From 6d506fd916fb13d48aaf48341a2e2cb400f86c42 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Fri, 12 Apr 2024 11:19:27 +0100 Subject: [PATCH] When clearing object's dict, clear inline values but leave dict attached --- Lib/test/test_class.py | 10 ++++++ ...-04-12-11-19-18.gh-issue-117750.YttK6h.rst | 3 ++ Objects/dictobject.c | 33 ++++++++++--------- 3 files changed, 31 insertions(+), 15 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-04-12-11-19-18.gh-issue-117750.YttK6h.rst diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py index 4c1814142736e3..a9cfd8df691845 100644 --- a/Lib/test/test_class.py +++ b/Lib/test/test_class.py @@ -862,6 +862,16 @@ class C: pass self.assertFalse(has_inline_values(c)) self.check_100(c) + def test_bug_117750(self): + "Aborted on 3.13a6" + class C: + def __init__(self): + self.__dict__.clear() + + obj = C() + self.assertEqual(obj.__dict__, {}) + obj.foo = None # Aborted here + self.assertEqual(obj.__dict__, {"foo":None}) if __name__ == '__main__': diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-12-11-19-18.gh-issue-117750.YttK6h.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-12-11-19-18.gh-issue-117750.YttK6h.rst new file mode 100644 index 00000000000000..d7cf5d6e57d0cb --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-12-11-19-18.gh-issue-117750.YttK6h.rst @@ -0,0 +1,3 @@ +Fix issue where an object's dict would get out of sync with the object's +internal values when being cleared. ``obj.__dict__.clear()`` now clears the +internal values, but leaves the dict attached to the object. diff --git a/Objects/dictobject.c b/Objects/dictobject.c index e7993e4b051433..d1db46dd008f4c 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2684,25 +2684,28 @@ clear_lock_held(PyObject *op) interp, PyDict_EVENT_CLEARED, mp, NULL, NULL); // We don't inc ref empty keys because they're immortal ensure_shared_on_resize(mp); - - set_keys(mp, Py_EMPTY_KEYS); - set_values(mp, NULL); - mp->ma_used = 0; mp->ma_version_tag = new_version; - /* ...then clear the keys and values */ - if (oldvalues != NULL) { - if (!oldvalues->embedded) { - n = oldkeys->dk_nentries; - for (i = 0; i < n; i++) - Py_CLEAR(oldvalues->values[i]); - free_values(oldvalues, IS_DICT_SHARED(mp)); - } - dictkeys_decref(interp, oldkeys, false); - } - else { + mp->ma_used = 0; + if (oldvalues == NULL) { + set_keys(mp, Py_EMPTY_KEYS); assert(oldkeys->dk_refcnt == 1); dictkeys_decref(interp, oldkeys, IS_DICT_SHARED(mp)); } + else { + n = oldkeys->dk_nentries; + for (i = 0; i < n; i++) { + Py_CLEAR(oldvalues->values[i]); + } + if (oldvalues->embedded) { + oldvalues->size = 0; + } + else { + set_values(mp, NULL); + set_keys(mp, Py_EMPTY_KEYS); + free_values(oldvalues, IS_DICT_SHARED(mp)); + dictkeys_decref(interp, oldkeys, false); + } + } ASSERT_CONSISTENT(mp); } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy