Add _PyObject_CallFunctionVa() helper
Issue #28915: Add _PyObject_CallFunctionVa() helper to factorize code of
functions:
* PyObject_CallFunction()
* _PyObject_CallFunction_SizeT()
* callmethod()
diff --git a/Objects/abstract.c b/Objects/abstract.c
index b2cf07c..4f59f04 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -2519,27 +2519,10 @@
}
}
-static PyObject*
-call_function_tail(PyObject *callable, PyObject *args)
+static PyObject *
+_PyObject_CallFunctionVa(PyObject *callable, const char *format,
+ va_list va, int is_size_t)
{
- PyObject *result;
-
- assert(args != NULL);
-
- if (!PyTuple_Check(args)) {
- result = PyObject_CallFunctionObjArgs(callable, args, NULL);
- }
- else {
- result = PyObject_Call(callable, args, NULL);
- }
-
- return result;
-}
-
-PyObject *
-PyObject_CallFunction(PyObject *callable, const char *format, ...)
-{
- va_list va;
PyObject *args, *result;
if (callable == NULL) {
@@ -2550,76 +2533,68 @@
return _PyObject_CallNoArg(callable);
}
- va_start(va, format);
- args = Py_VaBuildValue(format, va);
- va_end(va);
- if (args == NULL) {
- return NULL;
- }
-
- result = call_function_tail(callable, args);
- Py_DECREF(args);
- return result;
-}
-
-PyObject *
-_PyObject_CallFunction_SizeT(PyObject *callable, const char *format, ...)
-{
- va_list va;
- PyObject *args, *result;
-
- if (callable == NULL) {
- return null_error();
- }
-
- if (!format || !*format) {
- return _PyObject_CallNoArg(callable);
- }
-
- va_start(va, format);
- args = _Py_VaBuildValue_SizeT(format, va);
- va_end(va);
- if (args == NULL) {
- return NULL;
- }
-
- result = call_function_tail(callable, args);
- Py_DECREF(args);
- return result;
-}
-
-static PyObject*
-callmethod(PyObject* callable, const char *format, va_list va, int is_size_t)
-{
- PyObject *args, *result;
-
- assert(callable != NULL);
-
- if (!PyCallable_Check(callable)) {
- type_error("attribute of type '%.200s' is not callable", callable);
- return NULL;
- }
-
- if (!format || !*format) {
- return _PyObject_CallNoArg(callable);
- }
-
if (is_size_t) {
- args = _Py_VaBuildValue_SizeT(format, va);
+ args = Py_VaBuildValue(format, va);
}
else {
- args = Py_VaBuildValue(format, va);
+ args = _Py_VaBuildValue_SizeT(format, va);
}
if (args == NULL) {
return NULL;
}
- result = call_function_tail(callable, args);
+ if (!PyTuple_Check(args)) {
+ PyObject *stack[1] = {args};
+ result = _PyObject_FastCall(callable, stack, 1);
+ }
+ else {
+ result = PyObject_Call(callable, args, NULL);
+ }
+
Py_DECREF(args);
return result;
}
PyObject *
+PyObject_CallFunction(PyObject *callable, const char *format, ...)
+{
+ va_list va;
+ PyObject *result;
+
+ va_start(va, format);
+ result = _PyObject_CallFunctionVa(callable, format, va, 0);
+ va_end(va);
+
+ return result;
+}
+
+PyObject *
+_PyObject_CallFunction_SizeT(PyObject *callable, const char *format, ...)
+{
+ va_list va;
+ PyObject *result;
+
+ va_start(va, format);
+ result = _PyObject_CallFunctionVa(callable, format, va, 1);
+ va_end(va);
+
+ return result;
+}
+
+static PyObject*
+callmethod(PyObject* callable, const char *format, va_list va, int is_size_t)
+{
+ assert(callable != NULL);
+
+ if (!PyCallable_Check(callable)) {
+ type_error("attribute of type '%.200s' is not callable", callable);
+ return NULL;
+ }
+
+ return _PyObject_CallFunctionVa(callable, format, va, is_size_t);
+}
+
+PyObject *
PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...)
{
va_list va;