diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2023-08-21 12:31:11 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-21 12:31:11 (GMT) |
commit | 1ce8b92ce92e9a44ac804ea4e4c61d08d7e89a2e (patch) | |
tree | 8c2fa1f4d4a1eeeaba8cf5c1c5de1a38c04f7ebc | |
parent | f798a6360b038a3fc47509101eb77bcc1c9b6662 (diff) | |
download | cpython-1ce8b92ce92e9a44ac804ea4e4c61d08d7e89a2e.zip cpython-1ce8b92ce92e9a44ac804ea4e4c61d08d7e89a2e.tar.gz cpython-1ce8b92ce92e9a44ac804ea4e4c61d08d7e89a2e.tar.bz2 |
[3.12] gh-105736: Sync pure python version of OrderedDict with the C version (GH-108098) (#108200)
gh-105736: Sync pure python version of OrderedDict with the C version (GH-108098)
(cherry picked from commit 20cc90c0df3e368fe7cb63d958f0b17a78fa9d0a)
Co-authored-by: Raymond Hettinger <rhettinger@users.noreply.github.com>
-rw-r--r-- | Lib/collections/__init__.py | 16 | ||||
-rw-r--r-- | Lib/test/test_ordered_dict.py | 11 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2023-08-17-14-45-25.gh-issue-105736.NJsH7r.rst | 3 |
3 files changed, 23 insertions, 7 deletions
diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index 03ca2d7..8652dc8 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -95,17 +95,19 @@ class OrderedDict(dict): # Individual links are kept alive by the hard reference in self.__map. # Those hard references disappear when a key is deleted from an OrderedDict. + def __new__(cls, /, *args, **kwds): + "Create the ordered dict object and set up the underlying structures." + self = dict.__new__(cls) + self.__hardroot = _Link() + self.__root = root = _proxy(self.__hardroot) + root.prev = root.next = root + self.__map = {} + return self + def __init__(self, other=(), /, **kwds): '''Initialize an ordered dictionary. The signature is the same as regular dictionaries. Keyword argument order is preserved. ''' - try: - self.__root - except AttributeError: - self.__hardroot = _Link() - self.__root = root = _proxy(self.__hardroot) - root.prev = root.next = root - self.__map = {} self.__update(other, **kwds) def __setitem__(self, key, value, diff --git a/Lib/test/test_ordered_dict.py b/Lib/test/test_ordered_dict.py index decbcc2..4571b23 100644 --- a/Lib/test/test_ordered_dict.py +++ b/Lib/test/test_ordered_dict.py @@ -122,6 +122,17 @@ class OrderedDictTests: self.OrderedDict(Spam()) self.assertEqual(calls, ['keys']) + def test_overridden_init(self): + # Sync-up pure Python OD class with C class where + # a consistent internal state is created in __new__ + # rather than __init__. + OrderedDict = self.OrderedDict + class ODNI(OrderedDict): + def __init__(*args, **kwargs): + pass + od = ODNI() + od['a'] = 1 # This used to fail because __init__ was bypassed + def test_fromkeys(self): OrderedDict = self.OrderedDict od = OrderedDict.fromkeys('abc') diff --git a/Misc/NEWS.d/next/Library/2023-08-17-14-45-25.gh-issue-105736.NJsH7r.rst b/Misc/NEWS.d/next/Library/2023-08-17-14-45-25.gh-issue-105736.NJsH7r.rst new file mode 100644 index 0000000..f051317 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-08-17-14-45-25.gh-issue-105736.NJsH7r.rst @@ -0,0 +1,3 @@ +Harmonized the pure Python version of OrderedDict with the C version. Now, +both versions set up their internal state in `__new__`. Formerly, the pure +Python version did the set up in `__init__`. |