From 57f91ac95aec1922ba104019a81a6508485862c4 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 12 Sep 2016 13:37:07 +0200 Subject: Document kwnames in _PyObject_FastCallKeywords() and _PyStack_AsDict() Issue #27213. --- Include/abstract.h | 70 ++++++++++++++++++++++++++++---------------------- Objects/abstract.c | 3 +++ Objects/methodobject.c | 5 ++++ Python/ceval.c | 5 ++++ 4 files changed, 53 insertions(+), 30 deletions(-) diff --git a/Include/abstract.h b/Include/abstract.h index a94ce66..3e8ca1f 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -273,6 +273,13 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ PyObject **stack, Py_ssize_t nargs); + /* Convert keyword arguments from the (stack, kwnames) format to a Python + dictionary. + + kwnames must only contains str strings, no subclass, and all keys must + be unique. kwnames is not checked, usually these checks are done before or later + calling _PyStack_AsDict(). For example, _PyArg_ParseStack() raises an + error if a key is not a string. */ PyAPI_FUNC(PyObject *) _PyStack_AsDict( PyObject **values, PyObject *kwnames); @@ -293,36 +300,39 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ PyObject **kwnames, PyObject *func); - /* Call the callable object func with the "fast call" calling convention: - args is a C array for positional arguments (nargs is the number of - positional arguments), kwargs is a dictionary for keyword arguments. - - If nargs is equal to zero, args can be NULL. kwargs can be NULL. - nargs must be greater or equal to zero. - - Return the result on success. Raise an exception on return NULL on - error. */ - PyAPI_FUNC(PyObject *) _PyObject_FastCallDict(PyObject *func, - PyObject **args, Py_ssize_t nargs, - PyObject *kwargs); - - /* Call the callable object func with the "fast call" calling convention: - args is a C array for positional arguments followed by values of - keyword arguments. Keys of keyword arguments are stored as a tuple - of strings in kwnames. nargs is the number of positional parameters at - the beginning of stack. The size of kwnames gives the number of keyword - values in the stack after positional arguments. - - If nargs is equal to zero and there is no keyword argument (kwnames is - NULL or its size is zero), args can be NULL. - - Return the result on success. Raise an exception and return NULL on - error. */ - PyAPI_FUNC(PyObject *) _PyObject_FastCallKeywords - (PyObject *func, - PyObject **args, - Py_ssize_t nargs, - PyObject *kwnames); + /* Call the callable object func with the "fast call" calling convention: + args is a C array for positional arguments (nargs is the number of + positional arguments), kwargs is a dictionary for keyword arguments. + + If nargs is equal to zero, args can be NULL. kwargs can be NULL. + nargs must be greater or equal to zero. + + Return the result on success. Raise an exception on return NULL on + error. */ + PyAPI_FUNC(PyObject *) _PyObject_FastCallDict(PyObject *func, + PyObject **args, Py_ssize_t nargs, + PyObject *kwargs); + + /* Call the callable object func with the "fast call" calling convention: + args is a C array for positional arguments followed by values of + keyword arguments. Keys of keyword arguments are stored as a tuple + of strings in kwnames. nargs is the number of positional parameters at + the beginning of stack. The size of kwnames gives the number of keyword + values in the stack after positional arguments. + + kwnames must only contains str strings, no subclass, and all keys must + be unique. + + If nargs is equal to zero and there is no keyword argument (kwnames is + NULL or its size is zero), args can be NULL. + + Return the result on success. Raise an exception and return NULL on + error. */ + PyAPI_FUNC(PyObject *) _PyObject_FastCallKeywords + (PyObject *func, + PyObject **args, + Py_ssize_t nargs, + PyObject *kwnames); #define _PyObject_FastCall(func, args, nargs) \ _PyObject_FastCallDict((func), (args), (nargs), NULL) diff --git a/Objects/abstract.c b/Objects/abstract.c index a929be9..17da5c9 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2457,6 +2457,9 @@ _PyObject_FastCallKeywords(PyObject *func, PyObject **stack, Py_ssize_t nargs, assert(nargs >= 0); assert(kwnames == NULL || PyTuple_CheckExact(kwnames)); assert((nargs == 0 && nkwargs == 0) || stack != NULL); + /* kwnames must only contains str strings, no subclass, and all keys must + be unique: these are implemented in Python/ceval.c and + _PyArg_ParseStack(). */ if (PyFunction_Check(func)) { return _PyFunction_FastCallKeywords(func, stack, nargs, kwnames); diff --git a/Objects/methodobject.c b/Objects/methodobject.c index 90c473e..19e8114 100644 --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -276,6 +276,11 @@ _PyCFunction_FastCallKeywords(PyObject *func, PyObject **stack, Py_ssize_t nkwargs; assert(PyCFunction_Check(func)); + assert(nargs >= 0); + assert(kwnames == NULL || PyTuple_CheckExact(kwnames)); + assert((nargs == 0 && nkwargs == 0) || stack != NULL); + /* kwnames must only contains str strings, no subclass, and all keys must + be unique */ nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames); if (nkwargs > 0) { diff --git a/Python/ceval.c b/Python/ceval.c index c9ac03f..ff36d36 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4863,7 +4863,12 @@ fast_function(PyObject *func, PyObject **stack, Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames); Py_ssize_t nd; + assert(PyFunction_Check(func)); + assert(nargs >= 0); + assert(kwnames == NULL || PyTuple_CheckExact(kwnames)); assert((nargs == 0 && nkwargs == 0) || stack != NULL); + /* kwnames must only contains str strings, no subclass, and all keys must + be unique */ PCALL(PCALL_FUNCTION); PCALL(PCALL_FAST_FUNCTION); -- cgit v0.12