From a394bbcbda55bad40f6a1c0c518679e5b28e6e8b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 30 May 2023 18:59:29 +0200 Subject: [PATCH 1/3] gh-105107: Remove PyEval_CallFunction() function Remove 4 functions from the C API, deprecated in Python 3.9: * PyEval_CallObjectWithKeywords() * PyEval_CallObject() * PyEval_CallFunction() * PyEval_CallMethod() Keep 3 functions in the stable ABI: * PyEval_CallObjectWithKeywords() * PyEval_CallFunction() * PyEval_CallMethod() --- Doc/data/stable_abi.dat | 3 --- Doc/whatsnew/3.13.rst | 14 +++++++++++++ Include/ceval.h | 21 ------------------- ...-05-30-19-11-09.gh-issue-105107.YQwMnm.rst | 9 ++++++++ Misc/stable_abi.toml | 3 +++ Objects/call.c | 15 +++++++------ 6 files changed, 33 insertions(+), 32 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2023-05-30-19-11-09.gh-issue-105107.YQwMnm.rst diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index f112d268129fd1..f255d9586b9ba3 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -180,9 +180,6 @@ function,PyErr_WarnFormat,3.2,, function,PyErr_WriteUnraisable,3.2,, function,PyEval_AcquireLock,3.2,, function,PyEval_AcquireThread,3.2,, -function,PyEval_CallFunction,3.2,, -function,PyEval_CallMethod,3.2,, -function,PyEval_CallObjectWithKeywords,3.2,, function,PyEval_EvalCode,3.2,, function,PyEval_EvalCodeEx,3.2,, function,PyEval_EvalFrame,3.2,, diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 13b9be1c8ee23f..6d1fdb4fad219c 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -308,3 +308,17 @@ Deprecated Removed ------- +* Remove functions deprecated in Python 3.9. + + * ``PyEval_CallObject()``, ``PyEval_CallObjectWithKeywords()``: use + :c:func:`PyObject_CallNoArgs` or :c:func:`PyObject_Call` instead. + Warning: :c:func:`PyObject_Call` positional arguments must be a + :class:`tuple` and must not be *NULL*, keyword arguments must by a + :class:`dict` or *NULL*, whereas removed functions checked arguments type. + To replace ``PyEval_CallObjectWithKeywords(func, NULL, kwargs)`` with + :c:func:`PyObject_Call`, pass an empty tuple as positional arguments using + :c:func:`PyTuple_New(0) `. + * ``PyEval_CallFunction()``: use :c:func:`PyObject_CallFunction` instead. + * ``PyEval_CallMethod()``: use :c:func:`PyObject_CallMethod` instead. + + (Contributed by Victor Stinner in :gh:`105107`.) diff --git a/Include/ceval.h b/Include/ceval.h index ad4d909d6f2b14..cf231b74f2bffa 100644 --- a/Include/ceval.h +++ b/Include/ceval.h @@ -17,27 +17,6 @@ PyAPI_FUNC(PyObject *) PyEval_EvalCodeEx(PyObject *co, PyObject *const *defs, int defc, PyObject *kwdefs, PyObject *closure); -/* PyEval_CallObjectWithKeywords(), PyEval_CallObject(), PyEval_CallFunction - * and PyEval_CallMethod are deprecated. Since they are officially part of the - * stable ABI (PEP 384), they must be kept for backward compatibility. - * PyObject_Call(), PyObject_CallFunction() and PyObject_CallMethod() are - * recommended to call a callable object. - */ - -Py_DEPRECATED(3.9) PyAPI_FUNC(PyObject *) PyEval_CallObjectWithKeywords( - PyObject *callable, - PyObject *args, - PyObject *kwargs); - -/* Deprecated since PyEval_CallObjectWithKeywords is deprecated */ -#define PyEval_CallObject(callable, arg) \ - PyEval_CallObjectWithKeywords((callable), (arg), _PyObject_CAST(_Py_NULL)) - -Py_DEPRECATED(3.9) PyAPI_FUNC(PyObject *) PyEval_CallFunction( - PyObject *callable, const char *format, ...); -Py_DEPRECATED(3.9) PyAPI_FUNC(PyObject *) PyEval_CallMethod( - PyObject *obj, const char *name, const char *format, ...); - PyAPI_FUNC(PyObject *) PyEval_GetBuiltins(void); PyAPI_FUNC(PyObject *) PyEval_GetGlobals(void); PyAPI_FUNC(PyObject *) PyEval_GetLocals(void); diff --git a/Misc/NEWS.d/next/C API/2023-05-30-19-11-09.gh-issue-105107.YQwMnm.rst b/Misc/NEWS.d/next/C API/2023-05-30-19-11-09.gh-issue-105107.YQwMnm.rst new file mode 100644 index 00000000000000..8423f4742ce2e9 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2023-05-30-19-11-09.gh-issue-105107.YQwMnm.rst @@ -0,0 +1,9 @@ +Remove functions deprecated in Python 3.9. + +* ``PyEval_CallObject()``, ``PyEval_CallObjectWithKeywords()``: use + :c:func:`PyObject_CallNoArgs` and :c:func:`PyObject_Call` (positional + arguments must not be *NULL*) instead. +* ``PyEval_CallFunction()``: use :c:func:`PyObject_CallFunction` instead. +* ``PyEval_CallMethod()``: use :c:func:`PyObject_CallMethod` instead. + +Patch by Victor Stinner. diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index 1db98483f09f77..ff3b09ca74c39e 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -667,10 +667,13 @@ added = '3.2' [function.PyEval_CallFunction] added = '3.2' + abi_only = true [function.PyEval_CallMethod] added = '3.2' + abi_only = true [function.PyEval_CallObjectWithKeywords] added = '3.2' + abi_only = true [function.PyEval_EvalCode] added = '3.2' [function.PyEval_EvalCodeEx] diff --git a/Objects/call.c b/Objects/call.c index e9002d350c9288..4658cf1f56bb7d 100644 --- a/Objects/call.c +++ b/Objects/call.c @@ -426,8 +426,9 @@ _PyFunction_Vectorcall(PyObject *func, PyObject* const* stack, /* --- More complex call functions -------------------------------- */ /* External interface to call any callable object. - The args must be a tuple or NULL. The kwargs must be a dict or NULL. */ -PyObject * + The args must be a tuple or NULL. The kwargs must be a dict or NULL. + Function removed in Python 3.13 API but kept in the stable ABI. */ +PyAPI_FUNC(PyObject*) PyEval_CallObjectWithKeywords(PyObject *callable, PyObject *args, PyObject *kwargs) { @@ -583,9 +584,8 @@ PyObject_CallFunction(PyObject *callable, const char *format, ...) /* PyEval_CallFunction is exact copy of PyObject_CallFunction. - * This function is kept for backward compatibility. - */ -PyObject * + Function removed in Python 3.13 API but kept in the stable ABI. */ +PyAPI_FUNC(PyObject*) PyEval_CallFunction(PyObject *callable, const char *format, ...) { va_list va; @@ -656,9 +656,8 @@ PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...) /* PyEval_CallMethod is exact copy of PyObject_CallMethod. - * This function is kept for backward compatibility. - */ -PyObject * + Function removed in Python 3.13 API but kept in the stable ABI. */ +PyAPI_FUNC(PyObject*) PyEval_CallMethod(PyObject *obj, const char *name, const char *format, ...) { PyThreadState *tstate = _PyThreadState_GET(); From 70301a11b48efbb091bb4b0d0ad450158daccf69 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 31 May 2023 12:50:10 +0200 Subject: [PATCH 2/3] Fix typo --- Doc/whatsnew/3.13.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 6d1fdb4fad219c..306964a18b5164 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -313,7 +313,7 @@ Removed * ``PyEval_CallObject()``, ``PyEval_CallObjectWithKeywords()``: use :c:func:`PyObject_CallNoArgs` or :c:func:`PyObject_Call` instead. Warning: :c:func:`PyObject_Call` positional arguments must be a - :class:`tuple` and must not be *NULL*, keyword arguments must by a + :class:`tuple` and must not be *NULL*, keyword arguments must be a :class:`dict` or *NULL*, whereas removed functions checked arguments type. To replace ``PyEval_CallObjectWithKeywords(func, NULL, kwargs)`` with :c:func:`PyObject_Call`, pass an empty tuple as positional arguments using From 3a3980fc9ab6cd10fd69af080e3a78fc11510dea Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 31 May 2023 12:51:50 +0200 Subject: [PATCH 3/3] Complete the doc --- Doc/whatsnew/3.13.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 306964a18b5164..7e29ed306c2d76 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -314,7 +314,8 @@ Removed :c:func:`PyObject_CallNoArgs` or :c:func:`PyObject_Call` instead. Warning: :c:func:`PyObject_Call` positional arguments must be a :class:`tuple` and must not be *NULL*, keyword arguments must be a - :class:`dict` or *NULL*, whereas removed functions checked arguments type. + :class:`dict` or *NULL*, whereas removed functions checked arguments type + and accepted *NULL* positional and keyword arguments. To replace ``PyEval_CallObjectWithKeywords(func, NULL, kwargs)`` with :c:func:`PyObject_Call`, pass an empty tuple as positional arguments using :c:func:`PyTuple_New(0) `.