]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-128863: Deprecate private C API functions (#128864)
authorVictor Stinner <vstinner@python.org>
Wed, 22 Jan 2025 11:04:19 +0000 (12:04 +0100)
committerGitHub <noreply@github.com>
Wed, 22 Jan 2025 11:04:19 +0000 (11:04 +0000)
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.

16 files changed:
Doc/deprecations/c-api-pending-removal-in-3.18.rst [new file with mode: 0644]
Doc/whatsnew/3.14.rst
Include/cpython/bytesobject.h
Include/cpython/dictobject.h
Include/cpython/fileutils.h
Include/cpython/pyhash.h
Include/cpython/pystate.h
Include/cpython/unicodeobject.h
Lib/test/audit-tests.py
Misc/NEWS.d/next/C_API/2025-01-15-11-42-07.gh-issue-128863.C9MkB_.rst [new file with mode: 0644]
Objects/descrobject.c
Objects/dictobject.c
Objects/methodobject.c
Objects/odictobject.c
Python/context.c
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 (file)
index 0000000..d04c746
--- /dev/null
@@ -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.
index 5652a63ce8d7017d0fe076e1313f01fe78803857..685a09dc70eec2d61bd3601a6180e74ee6975873 100644 (file)
@@ -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
 -------
 
index cf3f0387ecf32381a592b0ee263a71af701e7ef5..71c133f173f157ffe85fa2fe09dfaf526a093216 100644 (file)
@@ -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);
+}
index 78473e54898fa53f316463ec1b8f3310d43b46b4..df9ec7050fca1a99f66a4f5c70e60f15ded89ca7 100644 (file)
@@ -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 */
 
index 702f89aca324c51a79d84d3d314066499dc6fc4c..626b1ad57b384688609f0add0a2b52a3bbf8c97a 100644 (file)
@@ -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);
index 876a7f0ea44f4dcc7fbb734dd781d08d281022ad..a33ba10b8d3a37c2d9d2a0005a6c976084bd185a 100644 (file)
@@ -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);
index 32f68378ea5d72893253d4698ebbf5cad5feb579..cd6d95824968502a1589bb6a2eac5f65dc7db3c0 100644 (file)
@@ -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.
index 46a01c8e591709ba15fde42de9b16a121b847456..287de52b96202c3b800d02ec70654d84033c9c57 100644 (file)
@@ -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 =============================================== */
index 6df09d891433ea99c9bb451b450ec6335f8e45aa..6b9b21cf7f6a3cd1c61045e86d4baac148a440cb 100644 (file)
@@ -187,7 +187,7 @@ def test_monkeypatch():
 
 
 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 (file)
index 0000000..a94d793
--- /dev/null
@@ -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.
index 1852118359f0144f8e20a5ba0e361debc73e0496..238becee241d1de4c4f0c898b19da91ade8c7529 100644 (file)
@@ -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;
index 504e65b01ca9593350ea0bbc77f69496249e741f..8fe71123252a75352f146e49abefb96e9f19be72 100644 (file)
@@ -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]
index 345da4607423cf5ef82462a7ebfd80e86745eab6..ecec0f7205a11d12938223c3ae1c5f01b37682f9 100644 (file)
@@ -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;
index e151023dd764bfd2da477de16fe3fb9feb08e282..f2d8da0c56787802ed7c93141ceba48f24c4b73d 100644 (file)
@@ -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__
index f30b59b9443bbf69264325863ddec3df83857ace..bb1aa42b9c5e4f490b8e3566c6aa3040d966d562 100644 (file)
@@ -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;
 }
 
index 72804c39220591fc55a4374633c8dc588a214b34..68d24bc6b934653621d609e299b9bbd60fd8a37b 100644 (file)
@@ -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