https://github.com/python/cpython/commit/21403afa9ba5baa63dc7dd7cf6e109c335d26bb4
commit: 21403afa9ba5baa63dc7dd7cf6e109c335d26bb4
branch: main
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2026-09-17T13:45:31+02:00
summary:

gh-142217: Add tests on the deprecated _Py_Identifier C API (#157638)

Replace also PyDict_GetItemWithError() with PyDict_GetItemRef()
and remove outdated comment in Modules/_pickle.c.

files:
A Misc/NEWS.d/next/C_API/2026-09-16-21-24-36.gh-issue-142217.44sqt4.rst
M Modules/_pickle.c
M Modules/_testcapi/unicode.c
M Tools/c-analyzer/cpython/ignored.tsv

diff --git 
a/Misc/NEWS.d/next/C_API/2026-09-16-21-24-36.gh-issue-142217.44sqt4.rst 
b/Misc/NEWS.d/next/C_API/2026-09-16-21-24-36.gh-issue-142217.44sqt4.rst
new file mode 100644
index 000000000000000..7d48e27d8a83409
--- /dev/null
+++ b/Misc/NEWS.d/next/C_API/2026-09-16-21-24-36.gh-issue-142217.44sqt4.rst
@@ -0,0 +1,2 @@
+Add tests on the undocumented and deprecated ``_Py_Identifier`` C API. Patch
+by Victor Stinner.
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
index 90200a4379319d9..5339337741d2f27 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -4745,17 +4745,9 @@ save(PickleState *st, PicklerObject *self, PyObject 
*obj, int pers_save)
      * __reduce_ex__ method, or the object's __reduce__ method.
      */
     if (self->dispatch_table == NULL) {
-        reduce_func = PyDict_GetItemWithError(st->dispatch_table,
-                                              (PyObject *)type);
-        if (reduce_func == NULL) {
-            if (PyErr_Occurred()) {
-                goto error;
-            }
-        } else {
-            /* PyDict_GetItemWithError() returns a borrowed reference.
-               Increase the reference count to be consistent with
-               PyObject_GetItem and _PyObject_GetAttrId used below. */
-            Py_INCREF(reduce_func);
+        if (PyDict_GetItemRef(st->dispatch_table, (PyObject *)type,
+                              &reduce_func) < 0) {
+            goto error;
         }
     }
     else if (PyMapping_GetOptionalItem(self->dispatch_table, (PyObject *)type,
diff --git a/Modules/_testcapi/unicode.c b/Modules/_testcapi/unicode.c
index 915c9230f66b52e..e4017efd19237fd 100644
--- a/Modules/_testcapi/unicode.c
+++ b/Modules/_testcapi/unicode.c
@@ -227,6 +227,55 @@ unicode_GET_CACHED_HASH(PyObject *self, PyObject *arg)
 }
 
 
+// Test the deprecated _Py_Identifier C API:
+// - _Py_IDENTIFIER()
+// - _Py_static_string()
+// - _Py_static_string_init()
+// - _PyObject_CallMethodId()
+// - _PyObject_GetAttrId()
+// - _PyUnicode_FromId()
+//
+// _testembed also has tests on _PyUnicode_FromId().
+static PyObject*
+test_py_identifier(PyObject *self, PyObject *Py_UNUSED(args))
+{
+// Ignore deprecation warnings
+_Py_COMP_DIAG_PUSH
+_Py_COMP_DIAG_IGNORE_DEPR_DECLS
+
+    _Py_IDENTIFIER(hello);
+    PyObject *str = _PyUnicode_FromId(&PyId_hello);  // borrowed ref
+    if (str == NULL) {
+        return NULL;
+    }
+    assert(PyUnicode_EqualToUTF8(str, "hello") == 1);
+
+    // Calling twice return the same object
+    PyObject *str2 = _PyUnicode_FromId(&PyId_hello);  // borrowed ref
+    assert(str2 == str);
+
+    PyObject *number = Py_GetConstant(Py_CONSTANT_ONE);  // immortal
+    _Py_static_string(to_bytes_id, "to_bytes");
+    PyObject *res = _PyObject_CallMethodId(number, &to_bytes_id, NULL);
+    if (res == NULL) {
+        return NULL;
+    }
+    Py_DECREF(res);
+
+    static _Py_Identifier real_id = _Py_static_string_init("real");
+    res = _PyObject_GetAttrId(number, &real_id);
+    if (res == NULL) {
+        return NULL;
+    }
+    assert(res == number);
+    Py_DECREF(res);
+
+    Py_RETURN_NONE;
+
+_Py_COMP_DIAG_POP
+}
+
+
 // --- PyUnicodeWriter type -------------------------------------------------
 
 typedef struct {
@@ -572,6 +621,7 @@ static PyMethodDef TestMethods[] = {
     {"unicode_asutf8",           unicode_asutf8,                 METH_VARARGS},
     {"unicode_copycharacters",   unicode_copycharacters,         METH_VARARGS},
     {"unicode_GET_CACHED_HASH",  unicode_GET_CACHED_HASH,        METH_O},
+    {"test_py_identifier",       test_py_identifier,             METH_NOARGS},
     {NULL},
 };
 
diff --git a/Tools/c-analyzer/cpython/ignored.tsv 
b/Tools/c-analyzer/cpython/ignored.tsv
index 4c143164650a2ba..cddfeb02c4b8597 100644
--- a/Tools/c-analyzer/cpython/ignored.tsv
+++ b/Tools/c-analyzer/cpython/ignored.tsv
@@ -787,7 +787,9 @@ Modules/clinic/grpmodule.c.h        grp_getgrgid    
_keywords       -
 Modules/clinic/grpmodule.c.h   grp_getgrnam    _keywords       -
 Objects/object.c       -       constants       static PyObject*[]
 Objects/dictobject.c   -       PyFrozenDict_Type       -
-
+Modules/_testcapi/unicode.c    test_py_identifier      PyId_hello      -
+Modules/_testcapi/unicode.c    test_py_identifier      to_bytes_id     -
+Modules/_testcapi/unicode.c    test_py_identifier      real_id -
 
 ## False positives
 Python/specialize.c    -       _Py_InitCleanup -

_______________________________________________
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