]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-145056: Fix merging of collections.OrderedDict and frozendict (GH-146466)
authorSerhiy Storchaka <storchaka@gmail.com>
Mon, 30 Mar 2026 19:06:44 +0000 (22:06 +0300)
committerGitHub <noreply@github.com>
Mon, 30 Mar 2026 19:06:44 +0000 (22:06 +0300)
Lib/collections/__init__.py
Lib/test/test_ordered_dict.py
Misc/NEWS.d/next/Library/2026-03-26-14-51-55.gh-issue-145056.QS-6l1.rst [new file with mode: 0644]
Objects/odictobject.c

index 2eee4c709555139eea22b376cdda6a50b696f6d0..ba60df037f28cbe6169a5fea029ff25ba1d6eecc 100644 (file)
@@ -328,14 +328,14 @@ class OrderedDict(dict):
         return self
 
     def __or__(self, other):
-        if not isinstance(other, dict):
+        if not isinstance(other, (dict, frozendict)):
             return NotImplemented
         new = self.__class__(self)
         new.update(other)
         return new
 
     def __ror__(self, other):
-        if not isinstance(other, dict):
+        if not isinstance(other, (dict, frozendict)):
             return NotImplemented
         new = self.__class__(other)
         new.update(self)
index 4204a6a47d2a8163e046799f7e8f857f9805e367..642c2722711c7ca705faab18e8f8ca30cf4a7597 100644 (file)
@@ -698,6 +698,7 @@ class OrderedDictTests:
         d |= list(b.items())
         expected = OrderedDict({0: 0, 1: 1, 2: 2, 3: 3})
         self.assertEqual(a | dict(b), expected)
+        self.assertEqual(a | frozendict(b), expected)
         self.assertEqual(a | b, expected)
         self.assertEqual(c, expected)
         self.assertEqual(d, expected)
@@ -706,12 +707,17 @@ class OrderedDictTests:
         c |= a
         expected = OrderedDict({1: 1, 2: 1, 3: 3, 0: 0})
         self.assertEqual(dict(b) | a, expected)
+        self.assertEqual(frozendict(b) | a, expected)
+        self.assertEqual(a.__ror__(frozendict(b)), expected)
         self.assertEqual(b | a, expected)
         self.assertEqual(c, expected)
 
         self.assertIs(type(a | b), OrderedDict)
         self.assertIs(type(dict(a) | b), OrderedDict)
+        self.assertIs(type(frozendict(a) | b), frozendict)
+        self.assertIs(type(b.__ror__(frozendict(a))), OrderedDict)
         self.assertIs(type(a | dict(b)), OrderedDict)
+        self.assertIs(type(a | frozendict(b)), OrderedDict)
 
         expected = a.copy()
         a |= ()
diff --git a/Misc/NEWS.d/next/Library/2026-03-26-14-51-55.gh-issue-145056.QS-6l1.rst b/Misc/NEWS.d/next/Library/2026-03-26-14-51-55.gh-issue-145056.QS-6l1.rst
new file mode 100644 (file)
index 0000000..4eaabfb
--- /dev/null
@@ -0,0 +1 @@
+Fix merging of :class:`collections.OrderedDict` and :class:`frozendict`.
index e3ec0ae470c5d8498c10613eed9d22f33718a3a5..b391283e83795d06765b5c65462629df9a49d412 100644 (file)
@@ -906,7 +906,7 @@ odict_or(PyObject *left, PyObject *right)
         type = Py_TYPE(right);
         other = left;
     }
-    if (!PyDict_Check(other)) {
+    if (!PyAnyDict_Check(other)) {
         Py_RETURN_NOTIMPLEMENTED;
     }
     PyObject *new = PyObject_CallOneArg((PyObject*)type, left);
@@ -2268,7 +2268,7 @@ static int
 mutablemapping_update_arg(PyObject *self, PyObject *arg)
 {
     int res = 0;
-    if (PyDict_CheckExact(arg)) {
+    if (PyAnyDict_CheckExact(arg)) {
         PyObject *items = PyDict_Items(arg);
         if (items == NULL) {
             return -1;