@@ -1598,7 +1598,7 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
15981598{
15991599 char msgbuf [512 ];
16001600 int levels [32 ];
1601- const char * fname , * msg , * custom_msg , * keyword ;
1601+ const char * fname , * msg , * custom_msg ;
16021602 int min = INT_MAX ;
16031603 int max = INT_MAX ;
16041604 int i , pos , len ;
@@ -1666,7 +1666,6 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
16661666
16671667 /* convert tuple args and keyword args in same loop, using kwlist to drive process */
16681668 for (i = 0 ; i < len ; i ++ ) {
1669- keyword = kwlist [i ];
16701669 if (* format == '|' ) {
16711670 if (min != INT_MAX ) {
16721671 PyErr_SetString (PyExc_SystemError ,
@@ -1720,26 +1719,17 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
17201719 return cleanreturn (0 , & freelist );
17211720 }
17221721 if (!skip ) {
1723- current_arg = NULL ;
1724- if (nkwargs && i >= pos ) {
1725- current_arg = PyDict_GetItemString (kwargs , keyword );
1726- if (!current_arg && PyErr_Occurred ()) {
1727- return cleanreturn (0 , & freelist );
1728- }
1722+ if (i < nargs ) {
1723+ current_arg = PyTuple_GET_ITEM (args , i );
17291724 }
1730- if (current_arg ) {
1731- -- nkwargs ;
1732- if (i < nargs ) {
1733- /* arg present in tuple and in dict */
1734- PyErr_Format (PyExc_TypeError ,
1735- "Argument given by name ('%s') "
1736- "and position (%d)" ,
1737- keyword , i + 1 );
1738- return cleanreturn (0 , & freelist );
1739- }
1725+ else if (nkwargs && i >= pos ) {
1726+ current_arg = PyDict_GetItemString (kwargs , kwlist [i ]);
1727+ if (current_arg )
1728+ -- nkwargs ;
1729+ }
1730+ else {
1731+ current_arg = NULL ;
17401732 }
1741- else if (i < nargs )
1742- current_arg = PyTuple_GET_ITEM (args , i );
17431733
17441734 if (current_arg ) {
17451735 msg = convertitem (current_arg , & format , p_va , flags ,
@@ -1763,8 +1753,8 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
17631753 }
17641754 else {
17651755 PyErr_Format (PyExc_TypeError , "Required argument "
1766- "'%s' (pos %d) not found" ,
1767- keyword , i + 1 );
1756+ "'%s' (pos %d) not found" ,
1757+ kwlist [ i ] , i + 1 );
17681758 return cleanreturn (0 , & freelist );
17691759 }
17701760 }
@@ -1803,19 +1793,32 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
18031793 return cleanreturn (0 , & freelist );
18041794 }
18051795
1806- /* make sure there are no extraneous keyword arguments */
18071796 if (nkwargs > 0 ) {
1808- PyObject * key , * value ;
1809- Py_ssize_t pos = 0 ;
1810- while (PyDict_Next (kwargs , & pos , & key , & value )) {
1797+ PyObject * key ;
1798+ Py_ssize_t j ;
1799+ /* make sure there are no arguments given by name and position */
1800+ for (i = pos ; i < nargs ; i ++ ) {
1801+ current_arg = PyDict_GetItemString (kwargs , kwlist [i ]);
1802+ if (current_arg ) {
1803+ /* arg present in tuple and in dict */
1804+ PyErr_Format (PyExc_TypeError ,
1805+ "Argument given by name ('%s') "
1806+ "and position (%d)" ,
1807+ kwlist [i ], i + 1 );
1808+ return cleanreturn (0 , & freelist );
1809+ }
1810+ }
1811+ /* make sure there are no extraneous keyword arguments */
1812+ j = 0 ;
1813+ while (PyDict_Next (kwargs , & j , & key , NULL )) {
18111814 int match = 0 ;
18121815 if (!PyUnicode_Check (key )) {
18131816 PyErr_SetString (PyExc_TypeError ,
18141817 "keywords must be strings" );
18151818 return cleanreturn (0 , & freelist );
18161819 }
1817- for (i = 0 ; i < len ; i ++ ) {
1818- if (* kwlist [ i ] && _PyUnicode_EqualToASCIIString (key , kwlist [i ])) {
1820+ for (i = pos ; i < len ; i ++ ) {
1821+ if (_PyUnicode_EqualToASCIIString (key , kwlist [i ])) {
18191822 match = 1 ;
18201823 break ;
18211824 }
@@ -1963,10 +1966,13 @@ parser_clear(struct _PyArg_Parser *parser)
19631966}
19641967
19651968static PyObject *
1966- find_keyword (PyObject * kwnames , PyObject * * kwstack , PyObject * key )
1969+ find_keyword (PyObject * kwargs , PyObject * kwnames , PyObject * * kwstack , PyObject * key )
19671970{
19681971 Py_ssize_t i , nkwargs ;
19691972
1973+ if (kwargs != NULL ) {
1974+ return PyDict_GetItem (kwargs , key );
1975+ }
19701976 nkwargs = PyTuple_GET_SIZE (kwnames );
19711977 for (i = 0 ; i < nkwargs ; i ++ ) {
19721978 PyObject * kwname = PyTuple_GET_ITEM (kwnames , i );
@@ -1978,7 +1984,7 @@ find_keyword(PyObject *kwnames, PyObject **kwstack, PyObject *key)
19781984 }
19791985 if (!PyUnicode_Check (kwname )) {
19801986 /* ignore non-string keyword keys:
1981- an error will be raised above */
1987+ an error will be raised below */
19821988 continue ;
19831989 }
19841990 if (_PyUnicode_EQ (kwname , key )) {
@@ -2012,8 +2018,7 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,
20122018 freelist .entries_malloced = 0 ;
20132019
20142020 assert (kwargs == NULL || PyDict_Check (kwargs ));
2015- assert ((kwargs != NULL || kwnames != NULL )
2016- || (kwargs == NULL && kwnames == NULL ));
2021+ assert (kwargs == NULL || kwnames == NULL );
20172022 assert (p_va != NULL );
20182023
20192024 if (parser == NULL ) {
@@ -2074,7 +2079,6 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,
20742079 format = parser -> format ;
20752080 /* convert tuple args and keyword args in same loop, using kwtuple to drive process */
20762081 for (i = 0 ; i < len ; i ++ ) {
2077- keyword = (i >= pos ) ? PyTuple_GET_ITEM (kwtuple , i - pos ) : NULL ;
20782082 if (* format == '|' ) {
20792083 format ++ ;
20802084 }
@@ -2083,31 +2087,17 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,
20832087 }
20842088 assert (!IS_END_OF_FORMAT (* format ));
20852089
2086- current_arg = NULL ;
2087- if (nkwargs && i >= pos ) {
2088- if (kwargs != NULL ) {
2089- current_arg = PyDict_GetItem (kwargs , keyword );
2090- if (!current_arg && PyErr_Occurred ()) {
2091- return cleanreturn (0 , & freelist );
2092- }
2093- }
2094- else {
2095- current_arg = find_keyword (kwnames , kwstack , keyword );
2096- }
2090+ if (i < nargs ) {
2091+ current_arg = args [i ];
20972092 }
2098- if (current_arg ) {
2099- -- nkwargs ;
2100- if (i < nargs ) {
2101- /* arg present in tuple and in dict */
2102- PyErr_Format (PyExc_TypeError ,
2103- "Argument given by name ('%U') "
2104- "and position (%d)" ,
2105- keyword , i + 1 );
2106- return cleanreturn (0 , & freelist );
2107- }
2093+ else if (nkwargs && i >= pos ) {
2094+ keyword = PyTuple_GET_ITEM (kwtuple , i - pos );
2095+ current_arg = find_keyword (kwargs , kwnames , kwstack , keyword );
2096+ if (current_arg )
2097+ -- nkwargs ;
21082098 }
2109- else if ( i < nargs ) {
2110- current_arg = args [ i ] ;
2099+ else {
2100+ current_arg = NULL ;
21112101 }
21122102
21132103 if (current_arg ) {
@@ -2123,13 +2113,15 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,
21232113 if (i < parser -> min ) {
21242114 /* Less arguments than required */
21252115 if (i < pos ) {
2116+ Py_ssize_t min = Py_MIN (pos , parser -> min );
21262117 PyErr_Format (PyExc_TypeError ,
21272118 "Function takes %s %d positional arguments"
21282119 " (%d given)" ,
2129- ( Py_MIN ( pos , parser -> min ) < parser -> max ) ? "at least" : "exactly" ,
2130- Py_MIN ( pos , parser -> min ) , nargs );
2120+ min < parser -> max ? "at least" : "exactly" ,
2121+ min , nargs );
21312122 }
21322123 else {
2124+ keyword = PyTuple_GET_ITEM (kwtuple , i - pos );
21332125 PyErr_Format (PyExc_TypeError , "Required argument "
21342126 "'%U' (pos %d) not found" ,
21352127 keyword , i + 1 );
@@ -2152,54 +2144,50 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,
21522144
21532145 assert (IS_END_OF_FORMAT (* format ) || (* format == '|' ) || (* format == '$' ));
21542146
2155- /* make sure there are no extraneous keyword arguments */
21562147 if (nkwargs > 0 ) {
2157- if (kwargs != NULL ) {
2158- PyObject * key , * value ;
2159- Py_ssize_t pos = 0 ;
2160- while (PyDict_Next (kwargs , & pos , & key , & value )) {
2161- int match ;
2162- if (!PyUnicode_Check (key )) {
2163- PyErr_SetString (PyExc_TypeError ,
2164- "keywords must be strings" );
2165- return cleanreturn (0 , & freelist );
2166- }
2167- match = PySequence_Contains (kwtuple , key );
2168- if (match <= 0 ) {
2169- if (!match ) {
2170- PyErr_Format (PyExc_TypeError ,
2171- "'%U' is an invalid keyword "
2172- "argument for this function" ,
2173- key );
2174- }
2175- return cleanreturn (0 , & freelist );
2176- }
2148+ Py_ssize_t j ;
2149+ /* make sure there are no arguments given by name and position */
2150+ for (i = pos ; i < nargs ; i ++ ) {
2151+ keyword = PyTuple_GET_ITEM (kwtuple , i - pos );
2152+ current_arg = find_keyword (kwargs , kwnames , kwstack , keyword );
2153+ if (current_arg ) {
2154+ /* arg present in tuple and in dict */
2155+ PyErr_Format (PyExc_TypeError ,
2156+ "Argument given by name ('%U') "
2157+ "and position (%d)" ,
2158+ keyword , i + 1 );
2159+ return cleanreturn (0 , & freelist );
21772160 }
21782161 }
2179- else {
2180- Py_ssize_t j , nkwargs ;
2181-
2182- nkwargs = PyTuple_GET_SIZE (kwnames );
2183- for (j = 0 ; j < nkwargs ; j ++ ) {
2184- PyObject * key = PyTuple_GET_ITEM (kwnames , j );
2185- int match ;
2186-
2187- if (!PyUnicode_Check (key )) {
2188- PyErr_SetString (PyExc_TypeError ,
2189- "keywords must be strings" );
2190- return cleanreturn (0 , & freelist );
2191- }
2162+ /* make sure there are no extraneous keyword arguments */
2163+ j = 0 ;
2164+ while (1 ) {
2165+ int match ;
2166+ if (kwargs != NULL ) {
2167+ if (!PyDict_Next (kwargs , & j , & keyword , NULL ))
2168+ break ;
2169+ }
2170+ else {
2171+ if (j >= PyTuple_GET_SIZE (kwnames ))
2172+ break ;
2173+ keyword = PyTuple_GET_ITEM (kwnames , j );
2174+ j ++ ;
2175+ }
21922176
2193- match = PySequence_Contains (kwtuple , key );
2194- if (match <= 0 ) {
2195- if (!match ) {
2196- PyErr_Format (PyExc_TypeError ,
2197- "'%U' is an invalid keyword "
2198- "argument for this function" ,
2199- key );
2200- }
2201- return cleanreturn (0 , & freelist );
2177+ if (!PyUnicode_Check (keyword )) {
2178+ PyErr_SetString (PyExc_TypeError ,
2179+ "keywords must be strings" );
2180+ return cleanreturn (0 , & freelist );
2181+ }
2182+ match = PySequence_Contains (kwtuple , keyword );
2183+ if (match <= 0 ) {
2184+ if (!match ) {
2185+ PyErr_Format (PyExc_TypeError ,
2186+ "'%U' is an invalid keyword "
2187+ "argument for this function" ,
2188+ keyword );
22022189 }
2190+ return cleanreturn (0 , & freelist );
22032191 }
22042192 }
22052193 }
0 commit comments