Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-65210: Add const qualifiers in PyArg_VaParseTupleAndKeywords() #105958

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions Doc/c-api/arg.rst
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ API Functions
than a variable number of arguments.


.. c:function:: int PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char *keywords[], ...)
.. c:function:: int PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char * const *keywords, ...)

Parse the parameters of a function that takes both positional and keyword
parameters into local variables.
Expand All @@ -424,15 +424,24 @@ API Functions
Returns true on success; on failure, it returns false and raises the
appropriate exception.

.. note::

The *keywords* parameter declaration is :c:expr:`char * const *` in C and
:c:expr:`const char * const *` in C++.
This can be overridden with the :c:macro:`PY_CXX_CONST` macro.

.. versionchanged:: 3.6
Added support for :ref:`positional-only parameters
<positional-only_parameter>`.

.. versionchanged:: 3.13
The *keywords* parameter has now type :c:expr:`char * const *` in C and
:c:expr:`const char * const *` in C++, instead of :c:expr:`char **`.
Added support for non-ASCII keyword parameter names.


.. c:function:: int PyArg_VaParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char *keywords[], va_list vargs)

.. c:function:: int PyArg_VaParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char * const *keywords, va_list vargs)

Identical to :c:func:`PyArg_ParseTupleAndKeywords`, except that it accepts a
va_list rather than a variable number of arguments.
Expand Down Expand Up @@ -505,6 +514,19 @@ API Functions

PyArg_ParseTuple(args, "O|O:ref", &object, &callback)

.. c:macro:: PY_CXX_CONST

The value to be inserted, if any, before :c:expr:`char * const *`
in the *keywords* parameter declaration of
:c:func:`PyArg_ParseTupleAndKeywords` and
:c:func:`PyArg_VaParseTupleAndKeywords`.
Default empty for C and ``const`` for C++
(:c:expr:`const char * const *`).
To override, define it to the desired value before including
:file:`Python.h`.

.. versionadded:: 3.13


---------------
Building values
Expand Down
2 changes: 1 addition & 1 deletion Doc/extending/extending.rst
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,7 @@ Keyword Parameters for Extension Functions
The :c:func:`PyArg_ParseTupleAndKeywords` function is declared as follows::

int PyArg_ParseTupleAndKeywords(PyObject *arg, PyObject *kwdict,
const char *format, char *kwlist[], ...);
const char *format, char * const *kwlist, ...);

The *arg* and *format* parameters are identical to those of the
:c:func:`PyArg_ParseTuple` function. The *kwdict* parameter is the dictionary of
Expand Down
10 changes: 10 additions & 0 deletions Doc/whatsnew/3.13.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1104,6 +1104,16 @@ New Features
APIs accepting the format codes always use ``Py_ssize_t`` for ``#`` formats.
(Contributed by Inada Naoki in :gh:`104922`.)

* The *keywords* parameter of :c:func:`PyArg_ParseTupleAndKeywords` and
:c:func:`PyArg_VaParseTupleAndKeywords` has now type :c:expr:`char * const *`
in C and :c:expr:`const char * const *` in C++, instead of :c:expr:`char **`.
It makes these functions compatible with arguments of type
:c:expr:`const char * const *`, :c:expr:`const char **` or
:c:expr:`char * const *` in C++ and :c:expr:`char * const *` in C
without an explicit type cast.
This can be overridden with the :c:macro:`PY_CXX_CONST` macro.
(Contributed by Serhiy Storchaka in :gh:`65210`.)

* Add :c:func:`PyImport_AddModuleRef`: similar to
:c:func:`PyImport_AddModule`, but return a :term:`strong reference` instead
of a :term:`borrowed reference`.
Expand Down
4 changes: 2 additions & 2 deletions Include/modsupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ extern "C" {
PyAPI_FUNC(int) PyArg_Parse(PyObject *, const char *, ...);
PyAPI_FUNC(int) PyArg_ParseTuple(PyObject *, const char *, ...);
PyAPI_FUNC(int) PyArg_ParseTupleAndKeywords(PyObject *, PyObject *,
const char *, char **, ...);
const char *, PY_CXX_CONST char * const *, ...);
PyAPI_FUNC(int) PyArg_VaParse(PyObject *, const char *, va_list);
PyAPI_FUNC(int) PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *,
const char *, char **, va_list);
const char *, PY_CXX_CONST char * const *, va_list);

PyAPI_FUNC(int) PyArg_ValidateKeywordArguments(PyObject *);
PyAPI_FUNC(int) PyArg_UnpackTuple(PyObject *, const char *, Py_ssize_t, Py_ssize_t, ...);
Expand Down
8 changes: 8 additions & 0 deletions Include/pyport.h
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,14 @@ extern "C" {
# define ALIGNOF_MAX_ALIGN_T _Alignof(long double)
#endif

#ifndef PY_CXX_CONST
# ifdef __cplusplus
# define PY_CXX_CONST const
# else
# define PY_CXX_CONST
# endif
#endif

#if defined(__sgi) && !defined(_SGI_MP_SOURCE)
# define _SGI_MP_SOURCE
#endif
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Change the declaration of the *keywords* parameter of
:c:func:`PyArg_ParseTupleAndKeywords` and
:c:func:`PyArg_VaParseTupleAndKeywords` for better compatibility with C++.
17 changes: 9 additions & 8 deletions Python/getargs.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

/* New getargs implementation */

#define PY_CXX_CONST const
#include "Python.h"
#include "pycore_abstract.h" // _PyNumber_Index()
#include "pycore_dict.h" // _PyDict_HasOnlyStringKeys()
Expand All @@ -12,10 +13,10 @@
PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, const char *, ...);
PyAPI_FUNC(int) _PyArg_ParseTuple_SizeT(PyObject *, const char *, ...);
PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywords_SizeT(PyObject *, PyObject *,
const char *, char **, ...);
const char *, const char * const *, ...);
PyAPI_FUNC(int) _PyArg_VaParse_SizeT(PyObject *, const char *, va_list);
PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *, PyObject *,
const char *, char **, va_list);
const char *, const char * const *, va_list);

#define FLAG_COMPAT 1

Expand Down Expand Up @@ -54,7 +55,7 @@ static Py_ssize_t convertbuffer(PyObject *, const void **p, const char **);
static int getbuffer(PyObject *, Py_buffer *, const char**);

static int vgetargskeywords(PyObject *, PyObject *,
const char *, char **, va_list *, int);
const char *, const char * const *, va_list *, int);
static int vgetargskeywordsfast(PyObject *, PyObject *,
struct _PyArg_Parser *, va_list *, int);
static int vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs,
Expand Down Expand Up @@ -1247,7 +1248,7 @@ int
PyArg_ParseTupleAndKeywords(PyObject *args,
PyObject *keywords,
const char *format,
char **kwlist, ...)
const char * const *kwlist, ...)
{
int retval;
va_list va;
Expand All @@ -1271,7 +1272,7 @@ int
_PyArg_ParseTupleAndKeywords_SizeT(PyObject *args,
PyObject *keywords,
const char *format,
char **kwlist, ...)
const char * const *kwlist, ...)
{
int retval;
va_list va;
Expand All @@ -1297,7 +1298,7 @@ int
PyArg_VaParseTupleAndKeywords(PyObject *args,
PyObject *keywords,
const char *format,
char **kwlist, va_list va)
const char * const *kwlist, va_list va)
{
int retval;
va_list lva;
Expand All @@ -1322,7 +1323,7 @@ int
_PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args,
PyObject *keywords,
const char *format,
char **kwlist, va_list va)
const char * const *kwlist, va_list va)
{
int retval;
va_list lva;
Expand Down Expand Up @@ -1460,7 +1461,7 @@ PyArg_ValidateKeywordArguments(PyObject *kwargs)

static int
vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
char **kwlist, va_list *p_va, int flags)
const char * const *kwlist, va_list *p_va, int flags)
{
char msgbuf[512];
int levels[32];
Expand Down
Loading