]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-105736: Sync pure python version of OrderedDict with the C version (#108098)
authorRaymond Hettinger <rhettinger@users.noreply.github.com>
Mon, 21 Aug 2023 09:49:08 +0000 (04:49 -0500)
committerGitHub <noreply@github.com>
Mon, 21 Aug 2023 09:49:08 +0000 (11:49 +0200)
Lib/collections/__init__.py
Lib/test/test_ordered_dict.py
Misc/NEWS.d/next/Library/2023-08-17-14-45-25.gh-issue-105736.NJsH7r.rst [new file with mode: 0644]

index 03ca2d7e18f6f02cae8947c3125c7888407a9d65..8652dc8a4ec4501ef6f2f5eb111c3aa4d541cf8d 100644 (file)
@@ -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,
index decbcc2419c9fc8749e1a101c155c185b6d9f2fd..4571b23dfe7c1ac74e0d09c3c04e51654578b848 100644 (file)
@@ -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 (file)
index 0000000..f051317
--- /dev/null
@@ -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__`.