https://github.com/python/cpython/commit/9012fa741d55419dc77c5c191794eb93e71ae9a4
commit: 9012fa741d55419dc77c5c191794eb93e71ae9a4
branch: main
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2025-01-22T11:04:19Z
summary:

gh-128863: Deprecate private C API functions (#128864)

Deprecate private C API functions:

* _PyBytes_Join()
* _PyDict_GetItemStringWithError()
* _PyDict_Pop()
* _PyThreadState_UncheckedGet()
* _PyUnicode_AsString()
* _Py_HashPointer()
* _Py_fopen_obj()

Replace _Py_HashPointer() with Py_HashPointer().

Remove references to deprecated functions.

files:
A Doc/deprecations/c-api-pending-removal-in-3.18.rst
A Misc/NEWS.d/next/C_API/2025-01-15-11-42-07.gh-issue-128863.C9MkB_.rst
M Doc/whatsnew/3.14.rst
M Include/cpython/bytesobject.h
M Include/cpython/dictobject.h
M Include/cpython/fileutils.h
M Include/cpython/pyhash.h
M Include/cpython/pystate.h
M Include/cpython/unicodeobject.h
M Lib/test/audit-tests.py
M Objects/descrobject.c
M Objects/dictobject.c
M Objects/methodobject.c
M Objects/odictobject.c
M Python/context.c
M Python/fileutils.c

diff --git a/Doc/deprecations/c-api-pending-removal-in-3.18.rst 
b/Doc/deprecations/c-api-pending-removal-in-3.18.rst
new file mode 100644
index 00000000000000..d04c746cd9f33e
--- /dev/null
+++ b/Doc/deprecations/c-api-pending-removal-in-3.18.rst
@@ -0,0 +1,16 @@
+Pending removal in Python 3.18
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Deprecated private functions (:gh:`128863`):
+
+  * :c:func:`!_PyBytes_Join`: use :c:func:`PyBytes_Join`.
+  * :c:func:`!_PyDict_GetItemStringWithError`: use 
:c:func:`PyDict_GetItemStringRef`.
+  * :c:func:`!_PyDict_Pop()`: :c:func:`PyDict_Pop`.
+  * :c:func:`!_PyThreadState_UncheckedGet`: use 
:c:func:`PyThreadState_GetUnchecked`.
+  * :c:func:`!_PyUnicode_AsString`: use :c:func:`PyUnicode_AsUTF8`.
+  * :c:func:`!_Py_HashPointer`: use :c:func:`Py_HashPointer`.
+  * :c:func:`!_Py_fopen_obj`: use :c:func:`Py_fopen`.
+
+  The `pythoncapi-compat project
+  <https://github.com/python/pythoncapi-compat/>`__ can be used to get these
+  new public functions on Python 3.13 and older.
diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index 5652a63ce8d701..685a09dc70eec2 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -1376,12 +1376,31 @@ Deprecated
 
 .. include:: ../deprecations/c-api-pending-removal-in-3.15.rst
 
+.. include:: ../deprecations/c-api-pending-removal-in-3.18.rst
+
 .. include:: ../deprecations/c-api-pending-removal-in-future.rst
 
 * The ``PyMonitoring_FireBranchEvent`` function is deprecated and should
   be replaced with calls to :c:func:`PyMonitoring_FireBranchLeftEvent`
   and :c:func:`PyMonitoring_FireBranchRightEvent`.
 
+* The following private functions are deprecated and planned for removal in
+  Python 3.18:
+
+  * :c:func:`!_PyBytes_Join`: use :c:func:`PyBytes_Join`.
+  * :c:func:`!_PyDict_GetItemStringWithError`: use 
:c:func:`PyDict_GetItemStringRef`.
+  * :c:func:`!_PyDict_Pop()`: use :c:func:`PyDict_Pop`.
+  * :c:func:`!_PyThreadState_UncheckedGet`: use 
:c:func:`PyThreadState_GetUnchecked`.
+  * :c:func:`!_PyUnicode_AsString`: use :c:func:`PyUnicode_AsUTF8`.
+  * :c:func:`!_Py_HashPointer`: use :c:func:`Py_HashPointer`.
+  * :c:func:`!_Py_fopen_obj`: use :c:func:`Py_fopen`.
+
+  The `pythoncapi-compat project`_ can be used to get these new public
+  functions on Python 3.13 and older.
+
+  (Contributed by Victor Stinner in :gh:`128863`.)
+
+
 Removed
 -------
 
diff --git a/Include/cpython/bytesobject.h b/Include/cpython/bytesobject.h
index cf3f0387ecf323..71c133f173f157 100644
--- a/Include/cpython/bytesobject.h
+++ b/Include/cpython/bytesobject.h
@@ -34,5 +34,9 @@ static inline Py_ssize_t PyBytes_GET_SIZE(PyObject *op) {
 
 PyAPI_FUNC(PyObject*) PyBytes_Join(PyObject *sep, PyObject *iterable);
 
-// Alias kept for backward compatibility
-#define _PyBytes_Join PyBytes_Join
+// Deprecated alias kept for backward compatibility
+Py_DEPRECATED(3.14) static inline PyObject*
+_PyBytes_Join(PyObject *sep, PyObject *iterable)
+{
+    return PyBytes_Join(sep, iterable);
+}
diff --git a/Include/cpython/dictobject.h b/Include/cpython/dictobject.h
index 78473e54898fa5..df9ec7050fca1a 100644
--- a/Include/cpython/dictobject.h
+++ b/Include/cpython/dictobject.h
@@ -68,7 +68,12 @@ PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t 
minused);
 
 PyAPI_FUNC(int) PyDict_Pop(PyObject *dict, PyObject *key, PyObject **result);
 PyAPI_FUNC(int) PyDict_PopString(PyObject *dict, const char *key, PyObject 
**result);
-PyAPI_FUNC(PyObject *) _PyDict_Pop(PyObject *dict, PyObject *key, PyObject 
*default_value);
+
+// Use PyDict_Pop() instead
+Py_DEPRECATED(3.14) PyAPI_FUNC(PyObject *) _PyDict_Pop(
+    PyObject *dict,
+    PyObject *key,
+    PyObject *default_value);
 
 /* Dictionary watchers */
 
diff --git a/Include/cpython/fileutils.h b/Include/cpython/fileutils.h
index 702f89aca324c5..626b1ad57b3846 100644
--- a/Include/cpython/fileutils.h
+++ b/Include/cpython/fileutils.h
@@ -6,9 +6,11 @@ PyAPI_FUNC(FILE*) Py_fopen(
     PyObject *path,
     const char *mode);
 
-// Deprecated alias to Py_fopen() kept for backward compatibility
-Py_DEPRECATED(3.14) PyAPI_FUNC(FILE*) _Py_fopen_obj(
-    PyObject *path,
-    const char *mode);
+// Deprecated alias kept for backward compatibility
+Py_DEPRECATED(3.14) static inline FILE*
+_Py_fopen_obj(PyObject *path, const char *mode)
+{
+    return Py_fopen(path, mode);
+}
 
 PyAPI_FUNC(int) Py_fclose(FILE *file);
diff --git a/Include/cpython/pyhash.h b/Include/cpython/pyhash.h
index 876a7f0ea44f4d..a33ba10b8d3a37 100644
--- a/Include/cpython/pyhash.h
+++ b/Include/cpython/pyhash.h
@@ -29,9 +29,6 @@
 /* Helpers for hash functions */
 PyAPI_FUNC(Py_hash_t) _Py_HashDouble(PyObject *, double);
 
-// Kept for backward compatibility
-#define _Py_HashPointer Py_HashPointer
-
 
 /* hash function definition */
 typedef struct {
@@ -44,6 +41,14 @@ typedef struct {
 PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void);
 
 PyAPI_FUNC(Py_hash_t) Py_HashPointer(const void *ptr);
+
+// Deprecated alias kept for backward compatibility
+Py_DEPRECATED(3.14) static inline Py_hash_t
+_Py_HashPointer(const void *ptr)
+{
+    return Py_HashPointer(ptr);
+}
+
 PyAPI_FUNC(Py_hash_t) PyObject_GenericHash(PyObject *);
 
 PyAPI_FUNC(Py_hash_t) Py_HashBuffer(const void *ptr, Py_ssize_t len);
diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h
index 32f68378ea5d72..cd6d9582496850 100644
--- a/Include/cpython/pystate.h
+++ b/Include/cpython/pystate.h
@@ -239,8 +239,12 @@ struct _ts {
  * if it is NULL. */
 PyAPI_FUNC(PyThreadState *) PyThreadState_GetUnchecked(void);
 
-// Alias kept for backward compatibility
-#define _PyThreadState_UncheckedGet PyThreadState_GetUnchecked
+// Deprecated alias kept for backward compatibility
+Py_DEPRECATED(3.14) static inline PyThreadState*
+_PyThreadState_UncheckedGet(void)
+{
+    return PyThreadState_GetUnchecked();
+}
 
 
 // Disable tracing and profiling.
diff --git a/Include/cpython/unicodeobject.h b/Include/cpython/unicodeobject.h
index 46a01c8e591709..287de52b96202c 100644
--- a/Include/cpython/unicodeobject.h
+++ b/Include/cpython/unicodeobject.h
@@ -630,8 +630,12 @@ _PyUnicodeWriter_Dealloc(_PyUnicodeWriter *writer);
 
 PyAPI_FUNC(const char *) PyUnicode_AsUTF8(PyObject *unicode);
 
-// Alias kept for backward compatibility
-#define _PyUnicode_AsString PyUnicode_AsUTF8
+// Deprecated alias kept for backward compatibility
+Py_DEPRECATED(3.14) static inline const char*
+_PyUnicode_AsString(PyObject *unicode)
+{
+    return PyUnicode_AsUTF8(unicode);
+}
 
 
 /* === Characters Type APIs =============================================== */
diff --git a/Lib/test/audit-tests.py b/Lib/test/audit-tests.py
index 6df09d891433ea..6b9b21cf7f6a3c 100644
--- a/Lib/test/audit-tests.py
+++ b/Lib/test/audit-tests.py
@@ -187,7 +187,7 @@ class C(A):
 
 
 def test_open(testfn):
-    # SSLContext.load_dh_params uses _Py_fopen_obj rather than normal open()
+    # SSLContext.load_dh_params uses Py_fopen() rather than normal open()
     try:
         import ssl
 
diff --git 
a/Misc/NEWS.d/next/C_API/2025-01-15-11-42-07.gh-issue-128863.C9MkB_.rst 
b/Misc/NEWS.d/next/C_API/2025-01-15-11-42-07.gh-issue-128863.C9MkB_.rst
new file mode 100644
index 00000000000000..a94d7933ad32ef
--- /dev/null
+++ b/Misc/NEWS.d/next/C_API/2025-01-15-11-42-07.gh-issue-128863.C9MkB_.rst
@@ -0,0 +1,16 @@
+The following private functions are deprecated and planned for removal in
+Python 3.18:
+
+* :c:func:`!_PyBytes_Join`: use :c:func:`PyBytes_Join`.
+* :c:func:`!_PyDict_GetItemStringWithError`: use 
:c:func:`PyDict_GetItemStringRef`.
+* :c:func:`!_PyDict_Pop()`: use :c:func:`PyDict_Pop`.
+* :c:func:`!_PyThreadState_UncheckedGet`: use 
:c:func:`PyThreadState_GetUnchecked`.
+* :c:func:`!_PyUnicode_AsString`: use :c:func:`PyUnicode_AsUTF8`.
+* :c:func:`!_Py_HashPointer`: use :c:func:`Py_HashPointer`.
+* :c:func:`!_Py_fopen_obj`: use :c:func:`Py_fopen`.
+
+The `pythoncapi-compat project
+<https://github.com/python/pythoncapi-compat/>`__ can be used to get these new
+public functions on Python 3.13 and older.
+
+Patch by Victor Stinner.
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index 1852118359f014..238becee241d1d 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -1349,7 +1349,7 @@ wrapper_hash(PyObject *self)
     wrapperobject *wp = (wrapperobject *)self;
     Py_hash_t x, y;
     x = PyObject_GenericHash(wp->self);
-    y = _Py_HashPointer(wp->descr);
+    y = Py_HashPointer(wp->descr);
     x = x ^ y;
     if (x == -1)
         x = -2;
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 504e65b01ca959..8fe71123252a75 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -3090,8 +3090,8 @@ PyDict_PopString(PyObject *op, const char *key, PyObject 
**result)
 }
 
 
-PyObject *
-_PyDict_Pop(PyObject *dict, PyObject *key, PyObject *default_value)
+static PyObject *
+dict_pop_default(PyObject *dict, PyObject *key, PyObject *default_value)
 {
     PyObject *result;
     if (PyDict_Pop(dict, key, &result) == 0) {
@@ -3104,6 +3104,12 @@ _PyDict_Pop(PyObject *dict, PyObject *key, PyObject 
*default_value)
     return result;
 }
 
+PyObject *
+_PyDict_Pop(PyObject *dict, PyObject *key, PyObject *default_value)
+{
+    return dict_pop_default(dict, key, default_value);
+}
+
 static PyDictObject *
 dict_dict_fromkeys(PyInterpreterState *interp, PyDictObject *mp,
                    PyObject *iterable, PyObject *value)
@@ -4465,7 +4471,7 @@ static PyObject *
 dict_pop_impl(PyDictObject *self, PyObject *key, PyObject *default_value)
 /*[clinic end generated code: output=3abb47b89f24c21c input=e221baa01044c44c]*/
 {
-    return _PyDict_Pop((PyObject*)self, key, default_value);
+    return dict_pop_default((PyObject*)self, key, default_value);
 }
 
 /*[clinic input]
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index 345da4607423cf..ecec0f7205a11d 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -331,7 +331,7 @@ meth_hash(PyObject *self)
 {
     PyCFunctionObject *a = _PyCFunctionObject_CAST(self);
     Py_hash_t x = PyObject_GenericHash(a->m_self);
-    Py_hash_t y = _Py_HashPointer((void*)(a->m_ml->ml_meth));
+    Py_hash_t y = Py_HashPointer((void*)(a->m_ml->ml_meth));
     x ^= y;
     if (x == -1) {
         x = -2;
diff --git a/Objects/odictobject.c b/Objects/odictobject.c
index e151023dd764bf..f2d8da0c567878 100644
--- a/Objects/odictobject.c
+++ b/Objects/odictobject.c
@@ -260,7 +260,7 @@ mp_length         __len__          -                   
dict_length
 mp_subscript      __getitem__      -                   dict_subscript
 mp_ass_subscript  __setitem__      -                   dict_ass_sub
                   __delitem__
-tp_hash           __hash__         _Py_HashPointer     ..._HashNotImpl
+tp_hash           __hash__         Py_HashPointer      ..._HashNotImpl
 tp_str            __str__          object_str          -
 tp_getattro       __getattribute__ ..._GenericGetAttr  (repeated)
                   __getattr__
diff --git a/Python/context.c b/Python/context.c
index f30b59b9443bbf..bb1aa42b9c5e4f 100644
--- a/Python/context.c
+++ b/Python/context.c
@@ -860,7 +860,7 @@ contextvar_generate_hash(void *addr, PyObject *name)
         return -1;
     }
 
-    Py_hash_t res = _Py_HashPointer(addr) ^ name_hash;
+    Py_hash_t res = Py_HashPointer(addr) ^ name_hash;
     return res == -1 ? -2 : res;
 }
 
diff --git a/Python/fileutils.c b/Python/fileutils.c
index 72804c39220591..68d24bc6b93465 100644
--- a/Python/fileutils.c
+++ b/Python/fileutils.c
@@ -1842,14 +1842,6 @@ Py_fopen(PyObject *path, const char *mode)
 }
 
 
-// Deprecated alias to Py_fopen() kept for backward compatibility
-FILE*
-_Py_fopen_obj(PyObject *path, const char *mode)
-{
-    return Py_fopen(path, mode);
-}
-
-
 // Call fclose().
 //
 // On Windows, files opened by Py_fopen() in the Python DLL must be closed by

_______________________________________________
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