https://github.com/python/cpython/commit/a5568d0eb70f8ffbfc7815b58e24170787615931
commit: a5568d0eb70f8ffbfc7815b58e24170787615931
branch: main
author: da-woods <[email protected]>
committer: vstinner <[email protected]>
date: 2026-06-19T08:41:00Z
summary:

gh-141510 Add frozendict fast paths to abstract.c (#150692)

Add frozendict to the fast paths of PyMapping_GetOptionalItem(),
PyMapping_Keys(), PyMapping_Values(), and PyMapping_Items().

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>

files:
A Misc/NEWS.d/next/C_API/2026-06-18-18-24-11.gh-issue-141510.-EOHJ1.rst
M Lib/test/test_capi/test_abstract.py
M Objects/abstract.c

diff --git a/Lib/test/test_capi/test_abstract.py 
b/Lib/test/test_capi/test_abstract.py
index 3a2ed9f5db82f0f..e455a8636209247 100644
--- a/Lib/test/test_capi/test_abstract.py
+++ b/Lib/test/test_capi/test_abstract.py
@@ -411,6 +411,11 @@ def test_mapping_getoptionalitem(self):
         self.assertEqual(getitem(dct2, 'a'), 1)
         self.assertEqual(getitem(dct2, 'b'), KeyError)
 
+        frozendct = frozendict(dct)
+        self.assertEqual(getitem(frozendct, 'a'), 1)
+        self.assertEqual(getitem(frozendct, 'b'), KeyError)
+        self.assertEqual(getitem(frozendct, '\U0001f40d'), 2)
+
         self.assertEqual(getitem(['a', 'b', 'c'], 1), 'b')
 
         self.assertRaises(TypeError, getitem, 42, 'a')
@@ -431,6 +436,11 @@ def test_mapping_getoptionalitemstring(self):
         self.assertEqual(getitemstring(dct2, b'a'), 1)
         self.assertEqual(getitemstring(dct2, b'b'), KeyError)
 
+        frozendct = frozendict(dct)
+        self.assertEqual(getitemstring(frozendct, 'a'), 1)
+        self.assertEqual(getitemstring(frozendct, 'b'), KeyError)
+        self.assertEqual(getitemstring(frozendct, '\U0001f40d'.encode()), 2)
+
         self.assertRaises(TypeError, getitemstring, 42, b'a')
         self.assertRaises(UnicodeDecodeError, getitemstring, {}, b'\xff')
         self.assertRaises(SystemError, getitemstring, {}, NULL)
@@ -677,8 +687,10 @@ def items(self):
         dict_obj = {'foo': 1, 'bar': 2, 'spam': 3}
 
         for mapping in [{}, OrderedDict(), Mapping1(), Mapping2(),
+                        frozendict(),
                         dict_obj, OrderedDict(dict_obj),
-                        Mapping1(dict_obj), Mapping2(dict_obj)]:
+                        Mapping1(dict_obj), Mapping2(dict_obj),
+                        frozendict(dict_obj)]:
             self.assertListEqual(_testlimitedcapi.mapping_keys(mapping),
                                  list(mapping.keys()))
             self.assertListEqual(_testlimitedcapi.mapping_values(mapping),
diff --git 
a/Misc/NEWS.d/next/C_API/2026-06-18-18-24-11.gh-issue-141510.-EOHJ1.rst 
b/Misc/NEWS.d/next/C_API/2026-06-18-18-24-11.gh-issue-141510.-EOHJ1.rst
new file mode 100644
index 000000000000000..c77b462e97bdd1d
--- /dev/null
+++ b/Misc/NEWS.d/next/C_API/2026-06-18-18-24-11.gh-issue-141510.-EOHJ1.rst
@@ -0,0 +1 @@
+Add :class:`frozendict` to the fast paths of 
:c:func:`PyMapping_GetOptionalItem`, :c:func:`PyMapping_Keys`, 
:c:func:`PyMapping_Values`, and :c:func:`PyMapping_Items`.
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 48b3137152e7bf3..28f751965f36b94 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -208,7 +208,7 @@ PyObject_GetItem(PyObject *o, PyObject *key)
 int
 PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result)
 {
-    if (PyDict_CheckExact(obj)) {
+    if (PyAnyDict_CheckExact(obj)) {
         return PyDict_GetItemRef(obj, key, result);
     }
 
@@ -2462,7 +2462,7 @@ PyMapping_Keys(PyObject *o)
     if (o == NULL) {
         return null_error();
     }
-    if (PyDict_CheckExact(o)) {
+    if (PyAnyDict_CheckExact(o)) {
         return PyDict_Keys(o);
     }
     return method_output_as_list(o, &_Py_ID(keys));
@@ -2474,7 +2474,7 @@ PyMapping_Items(PyObject *o)
     if (o == NULL) {
         return null_error();
     }
-    if (PyDict_CheckExact(o)) {
+    if (PyAnyDict_CheckExact(o)) {
         return PyDict_Items(o);
     }
     return method_output_as_list(o, &_Py_ID(items));
@@ -2486,7 +2486,7 @@ PyMapping_Values(PyObject *o)
     if (o == NULL) {
         return null_error();
     }
-    if (PyDict_CheckExact(o)) {
+    if (PyAnyDict_CheckExact(o)) {
         return PyDict_Values(o);
     }
     return method_output_as_list(o, &_Py_ID(values));

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to