@@ -57,8 +57,15 @@ static const char *convertsimple(PyObject *, const char **, va_list *, int,
5757static Py_ssize_t convertbuffer (PyObject * , const void * * p , const char * * );
5858static int getbuffer (PyObject * , Py_buffer * , const char * * );
5959
60- static int vgetargskeywords (PyObject * , PyObject * ,
61- const char * , const char * const * , va_list * , int );
60+ static int
61+ vgetargskeywords (PyObject * args , PyObject * kwargs ,
62+ const char * format , const char * const * kwlist ,
63+ va_list * p_va , int flags );
64+ static int
65+ vgetargskeywords_impl (PyObject * const * args , Py_ssize_t nargs ,
66+ PyObject * kwargs , PyObject * kwnames ,
67+ const char * format , const char * const * kwlist ,
68+ va_list * p_va , int flags );
6269static int vgetargskeywordsfast (PyObject * , PyObject * ,
6370 struct _PyArg_Parser * , va_list * , int );
6471static int vgetargskeywordsfast_impl (PyObject * const * args , Py_ssize_t nargs ,
@@ -139,6 +146,30 @@ PyArg_ParseVector(PyObject *const *args, Py_ssize_t nargs, const char *format, .
139146 return retval ;
140147}
141148
149+ int
150+ PyArg_ParseVectorAndKeywords (PyObject * const * args , Py_ssize_t nargs ,
151+ PyObject * kwnames ,
152+ const char * format ,
153+ const char * const * kwlist , ...)
154+ {
155+ if ((args == NULL && nargs != 0 ) ||
156+ (kwnames != NULL && !PyTuple_Check (kwnames )) ||
157+ format == NULL ||
158+ kwlist == NULL )
159+ {
160+ PyErr_BadInternalCall ();
161+ return 0 ;
162+ }
163+
164+ va_list va ;
165+ va_start (va , kwlist );
166+ int retval = vgetargskeywords_impl (args , nargs , NULL , kwnames , format ,
167+ kwlist , & va , 0 );
168+ va_end (va );
169+ return retval ;
170+ }
171+
172+
142173int
143174PyArg_VaParse (PyObject * args , const char * format , va_list va )
144175{
@@ -1622,11 +1653,27 @@ PyArg_ValidateKeywordArguments(PyObject *kwargs)
16221653static PyObject *
16231654new_kwtuple (const char * const * keywords , int total , int pos );
16241655
1656+ static PyObject *
1657+ find_keyword_str (PyObject * kwnames , PyObject * const * kwstack , const char * key )
1658+ {
1659+ Py_ssize_t nkwargs = PyTuple_GET_SIZE (kwnames );
1660+ for (Py_ssize_t i = 0 ; i < nkwargs ; i ++ ) {
1661+ PyObject * kwname = PyTuple_GET_ITEM (kwnames , i );
1662+ assert (PyUnicode_Check (kwname ));
1663+ if (PyUnicode_EqualToUTF8 (kwname , key )) {
1664+ return Py_NewRef (kwstack [i ]);
1665+ }
1666+ }
1667+ return NULL ;
1668+ }
1669+
16251670#define IS_END_OF_FORMAT (c ) (c == '\0' || c == ';' || c == ':')
16261671
16271672static int
1628- vgetargskeywords (PyObject * args , PyObject * kwargs , const char * format ,
1629- const char * const * kwlist , va_list * p_va , int flags )
1673+ vgetargskeywords_impl (PyObject * const * args , Py_ssize_t nargs ,
1674+ PyObject * kwargs , PyObject * kwnames ,
1675+ const char * format , const char * const * kwlist ,
1676+ va_list * p_va , int flags )
16301677{
16311678 char msgbuf [512 ];
16321679 int levels [32 ];
@@ -1635,16 +1682,18 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
16351682 int max = INT_MAX ;
16361683 int i , pos , len ;
16371684 int skip = 0 ;
1638- Py_ssize_t nargs , nkwargs ;
1685+ Py_ssize_t nkwargs ;
16391686 freelistentry_t static_entries [STATIC_FREELIST_ENTRIES ];
16401687 freelist_t freelist ;
1688+ PyObject * const * kwstack = NULL ;
16411689
16421690 freelist .entries = static_entries ;
16431691 freelist .first_available = 0 ;
16441692 freelist .entries_malloced = 0 ;
16451693
1646- assert (args != NULL && PyTuple_Check ( args ) );
1694+ assert (args != NULL || nargs == 0 );
16471695 assert (kwargs == NULL || PyDict_Check (kwargs ));
1696+ assert (kwnames == NULL || PyTuple_Check (kwnames ));
16481697 assert (format != NULL );
16491698 assert (kwlist != NULL );
16501699 assert (p_va != NULL );
@@ -1682,8 +1731,16 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
16821731 freelist .entries_malloced = 1 ;
16831732 }
16841733
1685- nargs = PyTuple_GET_SIZE (args );
1686- nkwargs = (kwargs == NULL ) ? 0 : PyDict_GET_SIZE (kwargs );
1734+ if (kwargs != NULL ) {
1735+ nkwargs = PyDict_GET_SIZE (kwargs );
1736+ }
1737+ else if (kwnames != NULL ) {
1738+ nkwargs = PyTuple_GET_SIZE (kwnames );
1739+ kwstack = args + nargs ;
1740+ }
1741+ else {
1742+ nkwargs = 0 ;
1743+ }
16871744 if (nargs + nkwargs > len ) {
16881745 /* Adding "keyword" (when nargs == 0) prevents producing wrong error
16891746 messages in some special cases (see bpo-31229). */
@@ -1767,11 +1824,16 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
17671824 if (!skip ) {
17681825 PyObject * current_arg ;
17691826 if (i < nargs ) {
1770- current_arg = Py_NewRef (PyTuple_GET_ITEM ( args , i ) );
1827+ current_arg = Py_NewRef (args [ i ] );
17711828 }
17721829 else if (nkwargs && i >= pos ) {
1773- if (PyDict_GetItemStringRef (kwargs , kwlist [i ], & current_arg ) < 0 ) {
1774- return cleanreturn (0 , & freelist );
1830+ if (kwargs != NULL ) {
1831+ if (PyDict_GetItemStringRef (kwargs , kwlist [i ], & current_arg ) < 0 ) {
1832+ return cleanreturn (0 , & freelist );
1833+ }
1834+ }
1835+ else {
1836+ current_arg = find_keyword_str (kwnames , kwstack , kwlist [i ]);
17751837 }
17761838 if (current_arg ) {
17771839 -- nkwargs ;
@@ -1856,8 +1918,13 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
18561918 /* make sure there are no arguments given by name and position */
18571919 for (i = pos ; i < nargs ; i ++ ) {
18581920 PyObject * current_arg ;
1859- if (PyDict_GetItemStringRef (kwargs , kwlist [i ], & current_arg ) < 0 ) {
1860- return cleanreturn (0 , & freelist );
1921+ if (kwargs != NULL ) {
1922+ if (PyDict_GetItemStringRef (kwargs , kwlist [i ], & current_arg ) < 0 ) {
1923+ return cleanreturn (0 , & freelist );
1924+ }
1925+ }
1926+ else {
1927+ current_arg = find_keyword_str (kwnames , kwstack , kwlist [i ]);
18611928 }
18621929 if (current_arg ) {
18631930 Py_DECREF (current_arg );
@@ -1873,7 +1940,20 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
18731940 }
18741941 /* make sure there are no extraneous keyword arguments */
18751942 j = 0 ;
1876- while (PyDict_Next (kwargs , & j , & key , NULL )) {
1943+ while (1 ) {
1944+ if (kwargs != NULL ) {
1945+ if (!PyDict_Next (kwargs , & j , & key , NULL )) {
1946+ break ;
1947+ }
1948+ }
1949+ else {
1950+ if (j >= nkwargs ) {
1951+ break ;
1952+ }
1953+ key = PyTuple_GET_ITEM (kwnames , j );
1954+ j ++ ;
1955+ }
1956+
18771957 int match = 0 ;
18781958 if (!PyUnicode_Check (key )) {
18791959 PyErr_SetString (PyExc_TypeError ,
@@ -1931,6 +2011,16 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
19312011 return cleanreturn (1 , & freelist );
19322012}
19332013
2014+ static int
2015+ vgetargskeywords (PyObject * argstuple , PyObject * kwargs ,
2016+ const char * format , const char * const * kwlist ,
2017+ va_list * p_va , int flags )
2018+ {
2019+ PyObject * const * args = _PyTuple_ITEMS (argstuple );
2020+ Py_ssize_t nargs = PyTuple_GET_SIZE (argstuple );
2021+ return vgetargskeywords_impl (args , nargs , kwargs , NULL ,
2022+ format , kwlist , p_va , flags );
2023+ }
19342024
19352025static int
19362026scan_keywords (const char * const * keywords , int * ptotal , int * pposonly )
0 commit comments