mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
Add _PyObject_FastCallKeywords()
Issue #27830: Similar to _PyObject_FastCallDict(), but keyword arguments are also passed in the same C array than positional arguments, rather than being passed as a Python dict.
This commit is contained in:
parent
53868aaabb
commit
577e1f8cb4
4 changed files with 116 additions and 9 deletions
|
@ -2309,6 +2309,85 @@ exit:
|
|||
return result;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
_PyStack_AsDict(PyObject **stack, Py_ssize_t nkwargs, PyObject *func)
|
||||
{
|
||||
PyObject *kwdict;
|
||||
|
||||
kwdict = PyDict_New();
|
||||
if (kwdict == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (--nkwargs >= 0) {
|
||||
int err;
|
||||
PyObject *key = *stack++;
|
||||
PyObject *value = *stack++;
|
||||
if (PyDict_GetItem(kwdict, key) != NULL) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%.200s%s got multiple values "
|
||||
"for keyword argument '%U'",
|
||||
PyEval_GetFuncName(func),
|
||||
PyEval_GetFuncDesc(func),
|
||||
key);
|
||||
Py_DECREF(kwdict);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = PyDict_SetItem(kwdict, key, value);
|
||||
if (err) {
|
||||
Py_DECREF(kwdict);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return kwdict;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
_PyObject_FastCallKeywords(PyObject *func, PyObject **stack, Py_ssize_t nargs,
|
||||
Py_ssize_t nkwargs)
|
||||
{
|
||||
PyObject *args, *kwdict, *result;
|
||||
|
||||
/* _PyObject_FastCallKeywords() must not be called with an exception set,
|
||||
because it may clear it (directly or indirectly) and so the
|
||||
caller loses its exception */
|
||||
assert(!PyErr_Occurred());
|
||||
|
||||
assert(func != NULL);
|
||||
assert(nargs >= 0);
|
||||
assert(nkwargs >= 0);
|
||||
assert((nargs == 0 && nkwargs == 0) || stack != NULL);
|
||||
|
||||
if (PyFunction_Check(func)) {
|
||||
/* Fast-path: avoid temporary tuple or dict */
|
||||
return _PyFunction_FastCallKeywords(func, stack, nargs, nkwargs);
|
||||
}
|
||||
|
||||
if (PyCFunction_Check(func) && nkwargs == 0) {
|
||||
return _PyCFunction_FastCallDict(func, args, nargs, NULL);
|
||||
}
|
||||
|
||||
/* Slow-path: build temporary tuple and/or dict */
|
||||
args = _PyStack_AsTuple(stack, nargs);
|
||||
|
||||
if (nkwargs > 0) {
|
||||
kwdict = _PyStack_AsDict(stack + nargs, nkwargs, func);
|
||||
if (kwdict == NULL) {
|
||||
Py_DECREF(args);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
kwdict = NULL;
|
||||
}
|
||||
|
||||
result = PyObject_Call(func, args, kwdict);
|
||||
Py_DECREF(args);
|
||||
Py_XDECREF(kwdict);
|
||||
return result;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
call_function_tail(PyObject *callable, PyObject *args)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue