diff --git a/Doc/deprecations/c-api-pending-removal-in-3.20.rst b/Doc/deprecations/c-api-pending-removal-in-3.20.rst index 18623b19a2ab8d..a813cb21dd4dbf 100644 --- a/Doc/deprecations/c-api-pending-removal-in-3.20.rst +++ b/Doc/deprecations/c-api-pending-removal-in-3.20.rst @@ -1,6 +1,13 @@ Pending removal in Python 3.20 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +* :c:func:`!_PyObject_CallMethodId`, :c:func:`!_PyObject_GetAttrId` and + :c:func:`!_PyUnicode_FromId` are deprecated since 3.15 and will be removed in + 3.20. Instead, use :c:func:`PyUnicode_FromString()` and cache the result in + the module state, then call :c:func:`PyObject_CallMethod` or + :c:func:`PyObject_GetAttr`. + (Contributed by Victor Stinner in :gh:`141049`.) + * The ``cval`` field in :c:type:`PyComplexObject` (:gh:`128813`). Use :c:func:`PyComplex_AsCComplex` and :c:func:`PyComplex_FromCComplex` to convert a Python complex number to/from the C :c:type:`Py_complex` diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 27e3f23e47c875..36e44729cfcb33 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1211,6 +1211,13 @@ Deprecated C APIs use the :c:type:`PyBytesWriter` API instead. (Contributed by Victor Stinner in :gh:`129813`.) +* :c:func:`!_PyObject_CallMethodId`, :c:func:`!_PyObject_GetAttrId` and + :c:func:`!_PyUnicode_FromId` are deprecated since 3.15 and will be removed in + 3.20. Instead, use :c:func:`PyUnicode_FromString()` and cache the result in + the module state, then call :c:func:`PyObject_CallMethod` or + :c:func:`PyObject_GetAttr`. + (Contributed by Victor Stinner in :gh:`141049`.) + * Deprecate :c:member:`~PyComplexObject.cval` field of the :c:type:`PyComplexObject` type. Use :c:func:`PyComplex_AsCComplex` and :c:func:`PyComplex_FromCComplex` diff --git a/Include/cpython/abstract.h b/Include/cpython/abstract.h index ffd19ccd3500fa..7490ece52e5220 100644 --- a/Include/cpython/abstract.h +++ b/Include/cpython/abstract.h @@ -6,7 +6,7 @@ /* Like PyObject_CallMethod(), but expect a _Py_Identifier* as the method name. */ -PyAPI_FUNC(PyObject*) _PyObject_CallMethodId( +Py_DEPRECATED(3.15) PyAPI_FUNC(PyObject*) _PyObject_CallMethodId( PyObject *obj, _Py_Identifier *name, const char *format, ...); diff --git a/Include/cpython/object.h b/Include/cpython/object.h index 8693390aeda624..85d5edd62e3a72 100644 --- a/Include/cpython/object.h +++ b/Include/cpython/object.h @@ -300,7 +300,7 @@ PyAPI_FUNC(void) PyUnstable_Object_Dump(PyObject *); // Alias for backward compatibility #define _PyObject_Dump PyUnstable_Object_Dump -PyAPI_FUNC(PyObject*) _PyObject_GetAttrId(PyObject *, _Py_Identifier *); +Py_DEPRECATED(3.15) PyAPI_FUNC(PyObject*) _PyObject_GetAttrId(PyObject *, _Py_Identifier *); PyAPI_FUNC(PyObject **) _PyObject_GetDictPtr(PyObject *); PyAPI_FUNC(void) PyObject_CallFinalizer(PyObject *); diff --git a/Include/cpython/unicodeobject.h b/Include/cpython/unicodeobject.h index 2853d24c34b66e..631a6570658410 100644 --- a/Include/cpython/unicodeobject.h +++ b/Include/cpython/unicodeobject.h @@ -778,4 +778,4 @@ static inline int Py_UNICODE_ISALNUM(Py_UCS4 ch) { // Return an interned Unicode object for an Identifier; may fail if there is no // memory. -PyAPI_FUNC(PyObject*) _PyUnicode_FromId(_Py_Identifier*); +Py_DEPRECATED(3.15) PyAPI_FUNC(PyObject*) _PyUnicode_FromId(_Py_Identifier*); diff --git a/Misc/NEWS.d/next/C_API/2025-12-03-14-41-07.gh-issue-141049.VuAUe2.rst b/Misc/NEWS.d/next/C_API/2025-12-03-14-41-07.gh-issue-141049.VuAUe2.rst new file mode 100644 index 00000000000000..b0fcd24d414270 --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2025-12-03-14-41-07.gh-issue-141049.VuAUe2.rst @@ -0,0 +1,5 @@ +:c:func:`!_PyObject_CallMethodId`, :c:func:`!_PyObject_GetAttrId` and +:c:func:`!_PyUnicode_FromId` are deprecated since 3.15 and will be removed in +3.20. Instead, use :c:func:`PyUnicode_FromString()` and cache the result in +the module state, then call :c:func:`PyObject_CallMethod` or +:c:func:`PyObject_GetAttr`. Patch by Victor Stinner. diff --git a/Objects/call.c b/Objects/call.c index c69015abfb3ed5..41d075caf11ce6 100644 --- a/Objects/call.c +++ b/Objects/call.c @@ -708,7 +708,10 @@ _PyObject_CallMethodId(PyObject *obj, _Py_Identifier *name, return null_error(tstate); } +_Py_COMP_DIAG_PUSH +_Py_COMP_DIAG_IGNORE_DEPR_DECLS PyObject *callable = _PyObject_GetAttrId(obj, name); +_Py_COMP_DIAG_POP if (callable == NULL) { return NULL; } diff --git a/Objects/object.c b/Objects/object.c index fcea3503de8213..9c079704427a2f 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1263,7 +1263,10 @@ PyObject * _PyObject_GetAttrId(PyObject *v, _Py_Identifier *name) { PyObject *result; +_Py_COMP_DIAG_PUSH +_Py_COMP_DIAG_IGNORE_DEPR_DECLS PyObject *oname = _PyUnicode_FromId(name); /* borrowed */ +_Py_COMP_DIAG_POP if (!oname) return NULL; result = PyObject_GetAttr(v, oname);