diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 17b291fd4d0fa4..84523525e2631e 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -43,7 +43,6 @@ function,PyBytes_Size,3.2,, var,PyBytes_Type,3.2,, type,PyCFunction,3.2,, type,PyCFunctionWithKeywords,3.2,, -function,PyCFunction_Call,3.2,, function,PyCFunction_GetFlags,3.2,, function,PyCFunction_GetFunction,3.2,, function,PyCFunction_GetSelf,3.2,, diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index cdc48a547ce267..1f1172493cb232 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -373,6 +373,7 @@ Removed :c:func:`PyTuple_New(0) `. * ``PyEval_CallFunction()``: use :c:func:`PyObject_CallFunction` instead. * ``PyEval_CallMethod()``: use :c:func:`PyObject_CallMethod` instead. + * ``PyCFunction_Call()``: use :c:func:`PyObject_Call` instead. (Contributed by Victor Stinner in :gh:`105107`.) diff --git a/Include/methodobject.h b/Include/methodobject.h index 72af5ad933df7f..2381e8482b82a8 100644 --- a/Include/methodobject.h +++ b/Include/methodobject.h @@ -49,8 +49,6 @@ PyAPI_FUNC(PyCFunction) PyCFunction_GetFunction(PyObject *); PyAPI_FUNC(PyObject *) PyCFunction_GetSelf(PyObject *); PyAPI_FUNC(int) PyCFunction_GetFlags(PyObject *); -Py_DEPRECATED(3.9) PyAPI_FUNC(PyObject *) PyCFunction_Call(PyObject *, PyObject *, PyObject *); - struct PyMethodDef { const char *ml_name; /* The name of the built-in function/method */ PyCFunction ml_meth; /* The C function that implements it */ diff --git a/Lib/test/test_call.py b/Lib/test/test_call.py index 12759c53bb662c..5410131a7dfd89 100644 --- a/Lib/test/test_call.py +++ b/Lib/test/test_call.py @@ -966,6 +966,7 @@ def c_py_recurse(m): finally: sys.setrecursionlimit(depth) + class TestFunctionWithManyArgs(unittest.TestCase): def test_function_with_many_args(self): for N in (10, 500, 1000): @@ -977,5 +978,24 @@ def test_function_with_many_args(self): self.assertEqual(l['f'](*range(N)), N//2) +@unittest.skipIf(_testcapi is None, 'need _testcapi') +class TestCAPI(unittest.TestCase): + def test_cfunction_call(self): + def func(*args, **kwargs): + return (args, kwargs) + + # PyCFunction_Call() was removed in Python 3.13 API, but was kept in + # the stable ABI. + def PyCFunction_Call(func, *args, **kwargs): + if kwargs: + return _testcapi.pycfunction_call(func, args, kwargs) + else: + return _testcapi.pycfunction_call(func, args) + + self.assertEqual(PyCFunction_Call(func), ((), {})) + self.assertEqual(PyCFunction_Call(func, 1, 2, 3), ((1, 2, 3), {})) + self.assertEqual(PyCFunction_Call(func, "arg", num=5), (("arg",), {'num': 5})) + + if __name__ == "__main__": unittest.main() 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 index 8423f4742ce2e9..6cc758cb83962b 100644 --- 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 @@ -5,5 +5,6 @@ Remove functions deprecated in Python 3.9. arguments must not be *NULL*) instead. * ``PyEval_CallFunction()``: use :c:func:`PyObject_CallFunction` instead. * ``PyEval_CallMethod()``: use :c:func:`PyObject_CallMethod` instead. +* ``PyCFunction_Call()``: use :c:func:`PyObject_Call` instead. Patch by Victor Stinner. diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index 7ff4da9a1f7b6a..fac59c97f4bf9f 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -447,6 +447,7 @@ added = '3.2' [function.PyCFunction_Call] added = '3.2' + abi_only = true [function.PyCFunction_GetFlags] added = '3.2' [function.PyCFunction_GetFunction] diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 86b6dc3b36fe7d..d7c89f48f792ed 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2362,6 +2362,19 @@ meth_fastcall_keywords(PyObject* self, PyObject* const* args, return Py_BuildValue("NNN", _null_to_none(self), pyargs, pykwargs); } +static PyObject* +test_pycfunction_call(PyObject *module, PyObject *args) +{ + // Function removed in the Python 3.13 API but was kept in the stable ABI. + extern PyObject* PyCFunction_Call(PyObject *callable, PyObject *args, PyObject *kwargs); + + PyObject *func, *pos_args, *kwargs = NULL; + if (!PyArg_ParseTuple(args, "OO!|O!", &func, &PyTuple_Type, &pos_args, &PyDict_Type, &kwargs)) { + return NULL; + } + return PyCFunction_Call(func, pos_args, kwargs); +} + static PyObject* pynumber_tobase(PyObject *module, PyObject *args) { @@ -3369,6 +3382,7 @@ static PyMethodDef TestMethods[] = { {"meth_noargs", meth_noargs, METH_NOARGS}, {"meth_fastcall", _PyCFunction_CAST(meth_fastcall), METH_FASTCALL}, {"meth_fastcall_keywords", _PyCFunction_CAST(meth_fastcall_keywords), METH_FASTCALL|METH_KEYWORDS}, + {"pycfunction_call", test_pycfunction_call, METH_VARARGS}, {"pynumber_tobase", pynumber_tobase, METH_VARARGS}, {"test_set_type_size", test_set_type_size, METH_NOARGS}, {"test_py_clear", test_py_clear, METH_NOARGS}, diff --git a/Objects/call.c b/Objects/call.c index 4658cf1f56bb7d..40eccefb4a6c8d 100644 --- a/Objects/call.c +++ b/Objects/call.c @@ -380,11 +380,11 @@ PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs) } -PyObject * +/* Function removed in the Python 3.13 API but kept in the stable ABI. */ +PyAPI_FUNC(PyObject *) PyCFunction_Call(PyObject *callable, PyObject *args, PyObject *kwargs) { - PyThreadState *tstate = _PyThreadState_GET(); - return _PyObject_Call(tstate, callable, args, kwargs); + return PyObject_Call(callable, args, kwargs); } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy