summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2023-06-27 23:34:37 (GMT)
committerGitHub <noreply@github.com>2023-06-27 23:34:37 (GMT)
commit84caa3324aaefb900895de2f946607cfdbe1be70 (patch)
treedb29f52d43d243cce40c9a9584d79ccd2484e1b6
parent6b5166fb12c4744544da4ee26ef437d025eb762a (diff)
downloadcpython-84caa3324aaefb900895de2f946607cfdbe1be70.zip
cpython-84caa3324aaefb900895de2f946607cfdbe1be70.tar.gz
cpython-84caa3324aaefb900895de2f946607cfdbe1be70.tar.bz2
gh-106084: Remove _PyObject_CallMethod() function (#106159)
Remove the following private functions from the public C API: * _Py_CheckFunctionResult() * _PyObject_CallMethod() * _PyObject_CallMethodId() * _PyObject_CallMethodIdNoArgs() * _PyObject_CallMethodIdObjArgs() * _PyObject_CallMethodIdOneArg() * _PyObject_MakeTpCall() * _PyObject_VectorcallMethodId() * _PyStack_AsDict() Move these functions to the internal C API (pycore_call.h). No longer export the following functions: * _PyObject_Call() * _PyObject_CallMethod() * _PyObject_CallMethodId() * _PyObject_CallMethodIdObjArgs() * _PyObject_Call_Prepend() * _PyObject_FastCallDictTstate() * _PyStack_AsDict() The following functions are still exported for stdlib shared extensions: * _Py_CheckFunctionResult() * _PyObject_MakeTpCall() Mark the following internal functions as extern: * _PyStack_UnpackDict() * _PyStack_UnpackDict_Free() * _PyStack_UnpackDict_FreeNoDecRef()
-rw-r--r--Include/cpython/abstract.h74
-rw-r--r--Include/internal/pycore_call.h105
-rw-r--r--Modules/_bisectmodule.c5
-rw-r--r--Modules/_io/iobase.c3
-rw-r--r--Modules/_io/textio.c3
-rw-r--r--Modules/arraymodule.c1
-rw-r--r--Objects/descrobject.c1
-rw-r--r--Objects/methodobject.c1
-rw-r--r--Python/pylifecycle.c3
9 files changed, 111 insertions, 85 deletions
diff --git a/Include/cpython/abstract.h b/Include/cpython/abstract.h
index 5eb22ff..2e76ff4 100644
--- a/Include/cpython/abstract.h
+++ b/Include/cpython/abstract.h
@@ -4,20 +4,6 @@
/* === Object Protocol ================================================== */
-/* Convert keyword arguments from the FASTCALL (stack: C array, kwnames: tuple)
- format to a Python dictionary ("kwargs" dict).
-
- The type of kwnames keys is not checked. The final function getting
- arguments is responsible to check if all keys are strings, for example using
- PyArg_ParseTupleAndKeywords() or PyArg_ValidateKeywordArguments().
-
- Duplicate keys are merged using the last value. If duplicate keys must raise
- an exception, the caller is responsible to implement an explicit keys on
- kwnames. */
-PyAPI_FUNC(PyObject *) _PyStack_AsDict(
- PyObject *const *values,
- PyObject *kwnames);
-
/* Suggested size (number of positional arguments) for arrays of PyObject*
allocated on a C stack to avoid allocating memory on the heap memory. Such
array is used to pass positional arguments to call functions of the
@@ -29,32 +15,17 @@ PyAPI_FUNC(PyObject *) _PyStack_AsDict(
40 bytes on the stack. */
#define _PY_FASTCALL_SMALL_STACK 5
-PyAPI_FUNC(PyObject *) _Py_CheckFunctionResult(
- PyThreadState *tstate,
- PyObject *callable,
- PyObject *result,
- const char *where);
-
/* === Vectorcall protocol (PEP 590) ============================= */
-/* Call callable using tp_call. Arguments are like PyObject_Vectorcall()
- or PyObject_FastCallDict() (both forms are supported),
- except that nargs is plainly the number of arguments without flags. */
-PyAPI_FUNC(PyObject *) _PyObject_MakeTpCall(
- PyThreadState *tstate,
- PyObject *callable,
- PyObject *const *args, Py_ssize_t nargs,
- PyObject *keywords);
-
// PyVectorcall_NARGS() is exported as a function for the stable ABI.
// Here (when we are not using the stable ABI), the name is overridden to
// call a static inline function for best performance.
-#define PyVectorcall_NARGS(n) _PyVectorcall_NARGS(n)
static inline Py_ssize_t
_PyVectorcall_NARGS(size_t n)
{
return n & ~PY_VECTORCALL_ARGUMENTS_OFFSET;
}
+#define PyVectorcall_NARGS(n) _PyVectorcall_NARGS(n)
PyAPI_FUNC(vectorcallfunc) PyVectorcall_Function(PyObject *callable);
@@ -90,49 +61,6 @@ PyObject_CallMethodOneArg(PyObject *self, PyObject *name, PyObject *arg)
return PyObject_VectorcallMethod(name, args, nargsf, _Py_NULL);
}
-PyAPI_FUNC(PyObject *) _PyObject_CallMethod(PyObject *obj,
- PyObject *name,
- const char *format, ...);
-
-/* Like PyObject_CallMethod(), but expect a _Py_Identifier*
- as the method name. */
-PyAPI_FUNC(PyObject *) _PyObject_CallMethodId(PyObject *obj,
- _Py_Identifier *name,
- const char *format, ...);
-
-PyAPI_FUNC(PyObject *) _PyObject_CallMethodIdObjArgs(
- PyObject *obj,
- _Py_Identifier *name,
- ...);
-
-static inline PyObject *
-_PyObject_VectorcallMethodId(
- _Py_Identifier *name, PyObject *const *args,
- size_t nargsf, PyObject *kwnames)
-{
- PyObject *oname = _PyUnicode_FromId(name); /* borrowed */
- if (!oname) {
- return _Py_NULL;
- }
- return PyObject_VectorcallMethod(oname, args, nargsf, kwnames);
-}
-
-static inline PyObject *
-_PyObject_CallMethodIdNoArgs(PyObject *self, _Py_Identifier *name)
-{
- size_t nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET;
- return _PyObject_VectorcallMethodId(name, &self, nargsf, _Py_NULL);
-}
-
-static inline PyObject *
-_PyObject_CallMethodIdOneArg(PyObject *self, _Py_Identifier *name, PyObject *arg)
-{
- PyObject *args[2] = {self, arg};
- size_t nargsf = 2 | PY_VECTORCALL_ARGUMENTS_OFFSET;
- assert(arg != NULL);
- return _PyObject_VectorcallMethodId(name, args, nargsf, _Py_NULL);
-}
-
/* Guess the size of object 'o' using len(o) or o.__length_hint__().
If neither of those return a non-negative value, then return the default
value. If one of the calls fails, this function returns -1. */
diff --git a/Include/internal/pycore_call.h b/Include/internal/pycore_call.h
index 5d9342b..3caf504 100644
--- a/Include/internal/pycore_call.h
+++ b/Include/internal/pycore_call.h
@@ -10,29 +10,112 @@ extern "C" {
#include "pycore_pystate.h" // _PyThreadState_GET()
-PyAPI_FUNC(PyObject *) _PyObject_Call_Prepend(
+// Export for shared stdlib extensions like the math extension,
+// function used via inlined _PyObject_VectorcallTstate() function.
+PyAPI_FUNC(PyObject*) _Py_CheckFunctionResult(
+ PyThreadState *tstate,
+ PyObject *callable,
+ PyObject *result,
+ const char *where);
+
+/* Convert keyword arguments from the FASTCALL (stack: C array, kwnames: tuple)
+ format to a Python dictionary ("kwargs" dict).
+
+ The type of kwnames keys is not checked. The final function getting
+ arguments is responsible to check if all keys are strings, for example using
+ PyArg_ParseTupleAndKeywords() or PyArg_ValidateKeywordArguments().
+
+ Duplicate keys are merged using the last value. If duplicate keys must raise
+ an exception, the caller is responsible to implement an explicit keys on
+ kwnames. */
+extern PyObject* _PyStack_AsDict(PyObject *const *values, PyObject *kwnames);
+
+extern PyObject* _PyObject_Call_Prepend(
PyThreadState *tstate,
PyObject *callable,
PyObject *obj,
PyObject *args,
PyObject *kwargs);
-PyAPI_FUNC(PyObject *) _PyObject_FastCallDictTstate(
+extern PyObject* _PyObject_FastCallDictTstate(
PyThreadState *tstate,
PyObject *callable,
PyObject *const *args,
size_t nargsf,
PyObject *kwargs);
-PyAPI_FUNC(PyObject *) _PyObject_Call(
+extern PyObject* _PyObject_Call(
PyThreadState *tstate,
PyObject *callable,
PyObject *args,
PyObject *kwargs);
extern PyObject * _PyObject_CallMethodFormat(
- PyThreadState *tstate, PyObject *callable, const char *format, ...);
+ PyThreadState *tstate,
+ PyObject *callable,
+ const char *format,
+ ...);
+// Export for shared stdlib extensions like the array extension
+PyAPI_FUNC(PyObject*) _PyObject_CallMethod(
+ PyObject *obj,
+ PyObject *name,
+ const char *format, ...);
+
+/* Like PyObject_CallMethod(), but expect a _Py_Identifier*
+ as the method name. */
+extern PyObject* _PyObject_CallMethodId(
+ PyObject *obj,
+ _Py_Identifier *name,
+ const char *format, ...);
+
+extern PyObject* _PyObject_CallMethodIdObjArgs(
+ PyObject *obj,
+ _Py_Identifier *name,
+ ...);
+
+static inline PyObject *
+_PyObject_VectorcallMethodId(
+ _Py_Identifier *name, PyObject *const *args,
+ size_t nargsf, PyObject *kwnames)
+{
+ PyObject *oname = _PyUnicode_FromId(name); /* borrowed */
+ if (!oname) {
+ return _Py_NULL;
+ }
+ return PyObject_VectorcallMethod(oname, args, nargsf, kwnames);
+}
+
+static inline PyObject *
+_PyObject_CallMethodIdNoArgs(PyObject *self, _Py_Identifier *name)
+{
+ size_t nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET;
+ return _PyObject_VectorcallMethodId(name, &self, nargsf, _Py_NULL);
+}
+
+static inline PyObject *
+_PyObject_CallMethodIdOneArg(PyObject *self, _Py_Identifier *name, PyObject *arg)
+{
+ PyObject *args[2] = {self, arg};
+ size_t nargsf = 2 | PY_VECTORCALL_ARGUMENTS_OFFSET;
+ assert(arg != NULL);
+ return _PyObject_VectorcallMethodId(name, args, nargsf, _Py_NULL);
+}
+
+
+/* === Vectorcall protocol (PEP 590) ============================= */
+
+// Call callable using tp_call. Arguments are like PyObject_Vectorcall()
+// or PyObject_FastCallDict() (both forms are supported),
+// except that nargs is plainly the number of arguments without flags.
+//
+// Export for shared stdlib extensions like the math extension,
+// function used via inlined _PyObject_VectorcallTstate() function.
+PyAPI_FUNC(PyObject*) _PyObject_MakeTpCall(
+ PyThreadState *tstate,
+ PyObject *callable,
+ PyObject *const *args, Py_ssize_t nargs,
+ PyObject *keywords);
// Static inline variant of public PyVectorcall_Function().
static inline vectorcallfunc
@@ -110,22 +193,26 @@ _PyObject_CallNoArgs(PyObject *func) {
static inline PyObject *
-_PyObject_FastCallTstate(PyThreadState *tstate, PyObject *func, PyObject *const *args, Py_ssize_t nargs)
+_PyObject_FastCallTstate(PyThreadState *tstate, PyObject *func,
+ PyObject *const *args, Py_ssize_t nargs)
{
EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_API, func);
return _PyObject_VectorcallTstate(tstate, func, args, (size_t)nargs, NULL);
}
-PyObject *const *
+extern PyObject *const *
_PyStack_UnpackDict(PyThreadState *tstate,
PyObject *const *args, Py_ssize_t nargs,
PyObject *kwargs, PyObject **p_kwnames);
-void
-_PyStack_UnpackDict_Free(PyObject *const *stack, Py_ssize_t nargs,
+extern void _PyStack_UnpackDict_Free(
+ PyObject *const *stack,
+ Py_ssize_t nargs,
PyObject *kwnames);
-void _PyStack_UnpackDict_FreeNoDecRef(PyObject *const *stack, PyObject *kwnames);
+extern void _PyStack_UnpackDict_FreeNoDecRef(
+ PyObject *const *stack,
+ PyObject *kwnames);
#ifdef __cplusplus
}
diff --git a/Modules/_bisectmodule.c b/Modules/_bisectmodule.c
index 0773bbd..60f4dc6 100644
--- a/Modules/_bisectmodule.c
+++ b/Modules/_bisectmodule.c
@@ -3,8 +3,13 @@
Converted to C by Dmitry Vasiliev (dima at hlabs.spb.ru).
*/
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
+
#define PY_SSIZE_T_CLEAN
#include "Python.h"
+#include "pycore_call.h" // _PyObject_CallMethod()
/*[clinic input]
module _bisect
diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c
index f98e75c..5cd679c 100644
--- a/Modules/_io/iobase.c
+++ b/Modules/_io/iobase.c
@@ -10,8 +10,9 @@
#define PY_SSIZE_T_CLEAN
#include "Python.h"
+#include "pycore_call.h" // _PyObject_CallMethod()
#include "pycore_long.h" // _PyLong_GetOne()
-#include "pycore_object.h"
+#include "pycore_object.h" // _PyType_HasFeature()
#include <stddef.h> // offsetof()
#include "_iomodule.h"
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
index 0ea7458..e6b1306 100644
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -8,10 +8,11 @@
#define PY_SSIZE_T_CLEAN
#include "Python.h"
+#include "pycore_call.h" // _PyObject_CallMethod()
#include "pycore_interp.h" // PyInterpreterState.fs_codec
#include "pycore_long.h" // _PyLong_GetZero()
#include "pycore_fileutils.h" // _Py_GetLocaleEncoding()
-#include "pycore_object.h"
+#include "pycore_object.h" // _PyObject_GC_UNTRACK()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "structmember.h" // PyMemberDef
#include "_iomodule.h"
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index 8132689..15f7766 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -9,6 +9,7 @@
#define PY_SSIZE_T_CLEAN
#include "Python.h"
+#include "pycore_call.h" // _PyObject_CallMethod()
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_bytesobject.h" // _PyBytes_Repeat
#include "structmember.h" // PyMemberDef
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index 89bac99..a814902 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -2,6 +2,7 @@
#include "Python.h"
#include "pycore_abstract.h" // _PyObject_RealIsSubclass()
+#include "pycore_call.h" // _PyStack_AsDict()
#include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate()
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
#include "pycore_pystate.h" // _PyThreadState_GET()
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index 51752de..fe08199 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -2,6 +2,7 @@
/* Method object implementation */
#include "Python.h"
+#include "pycore_call.h" // _Py_CheckFunctionResult()
#include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate()
#include "pycore_object.h"
#include "pycore_pyerrors.h"
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 6117f3a..1df35ef 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -2,10 +2,11 @@
#include "Python.h"
+#include "pycore_call.h" // _PyObject_CallMethod()
#include "pycore_ceval.h" // _PyEval_FiniGIL()
#include "pycore_context.h" // _PyContext_Init()
-#include "pycore_exceptions.h" // _PyExc_InitTypes()
#include "pycore_dict.h" // _PyDict_Fini()
+#include "pycore_exceptions.h" // _PyExc_InitTypes()
#include "pycore_fileutils.h" // _Py_ResetForceASCII()
#include "pycore_floatobject.h" // _PyFloat_InitTypes()
#include "pycore_genobject.h" // _PyAsyncGen_Fini()