summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_testcapimodule.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 7f7a13e..8c44ad2 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -4051,6 +4051,104 @@ raise_SIGINT_then_send_None(PyObject *self, PyObject *args)
}
+static int
+fastcall_args(PyObject *args, PyObject ***stack, Py_ssize_t *nargs)
+{
+ if (args == Py_None) {
+ *stack = NULL;
+ *nargs = 0;
+ }
+ else if (PyTuple_Check(args)) {
+ *stack = &PyTuple_GET_ITEM(args, 0);
+ *nargs = PyTuple_GET_SIZE(args);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "args must be None or a tuple");
+ return -1;
+ }
+ return 0;
+}
+
+
+static PyObject *
+test_pyobject_fastcall(PyObject *self, PyObject *args)
+{
+ PyObject *func, *func_args;
+ PyObject **stack;
+ Py_ssize_t nargs;
+
+ if (!PyArg_ParseTuple(args, "OO", &func, &func_args)) {
+ return NULL;
+ }
+
+ if (fastcall_args(func_args, &stack, &nargs) < 0) {
+ return NULL;
+ }
+ return _PyObject_FastCall(func, stack, nargs);
+}
+
+
+static PyObject *
+test_pyobject_fastcalldict(PyObject *self, PyObject *args)
+{
+ PyObject *func, *func_args, *kwargs;
+ PyObject **stack;
+ Py_ssize_t nargs;
+
+ if (!PyArg_ParseTuple(args, "OOO", &func, &func_args, &kwargs)) {
+ return NULL;
+ }
+
+ if (fastcall_args(func_args, &stack, &nargs) < 0) {
+ return NULL;
+ }
+
+ if (kwargs == Py_None) {
+ kwargs = NULL;
+ }
+ else if (!PyDict_Check(kwargs)) {
+ PyErr_SetString(PyExc_TypeError, "kwnames must be None or a dict");
+ return NULL;
+ }
+
+ return _PyObject_FastCallDict(func, stack, nargs, kwargs);
+}
+
+
+static PyObject *
+test_pyobject_fastcallkeywords(PyObject *self, PyObject *args)
+{
+ PyObject *func, *func_args, *kwnames = NULL;
+ PyObject **stack;
+ Py_ssize_t nargs, nkw;
+
+ if (!PyArg_ParseTuple(args, "OOO", &func, &func_args, &kwnames)) {
+ return NULL;
+ }
+
+ if (fastcall_args(func_args, &stack, &nargs) < 0) {
+ return NULL;
+ }
+
+ if (kwnames == Py_None) {
+ kwnames = NULL;
+ }
+ else if (PyTuple_Check(kwnames)) {
+ nkw = PyTuple_GET_SIZE(kwnames);
+ if (nargs < nkw) {
+ PyErr_SetString(PyExc_ValueError, "kwnames longer than args");
+ return NULL;
+ }
+ nargs -= nkw;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "kwnames must be None or a tuple");
+ return NULL;
+ }
+ return _PyObject_FastCallKeywords(func, stack, nargs, kwnames);
+}
+
+
static PyMethodDef TestMethods[] = {
{"raise_exception", raise_exception, METH_VARARGS},
{"raise_memoryerror", (PyCFunction)raise_memoryerror, METH_NOARGS},
@@ -4256,6 +4354,9 @@ static PyMethodDef TestMethods[] = {
{"tracemalloc_get_traceback", tracemalloc_get_traceback, METH_VARARGS},
{"dict_get_version", dict_get_version, METH_VARARGS},
{"raise_SIGINT_then_send_None", raise_SIGINT_then_send_None, METH_VARARGS},
+ {"pyobject_fastcall", test_pyobject_fastcall, METH_VARARGS},
+ {"pyobject_fastcalldict", test_pyobject_fastcalldict, METH_VARARGS},
+ {"pyobject_fastcallkeywords", test_pyobject_fastcallkeywords, METH_VARARGS},
{NULL, NULL} /* sentinel */
};