@@ -89,7 +89,7 @@ PyCFunction_Call(PyObject *func, PyObject *args, PyObject *kwds)
8989
9090 assert (kwds == NULL || PyDict_Check (kwds ));
9191 /* PyCFunction_Call() must not be called with an exception set,
92- because it may clear it (directly or indirectly) and so the
92+ because it can clear it (directly or indirectly) and so the
9393 caller loses its exception */
9494 assert (!PyErr_Occurred ());
9595
@@ -155,14 +155,14 @@ PyObject *
155155_PyCFunction_FastCallDict (PyObject * func_obj , PyObject * * args , Py_ssize_t nargs ,
156156 PyObject * kwargs )
157157{
158- PyCFunctionObject * func = ( PyCFunctionObject * ) func_obj ;
159- PyCFunction meth = PyCFunction_GET_FUNCTION ( func ) ;
160- PyObject * self = PyCFunction_GET_SELF ( func ) ;
158+ PyCFunctionObject * func ;
159+ PyCFunction meth ;
160+ PyObject * self ;
161161 PyObject * result ;
162162 int flags ;
163163
164- assert (PyCFunction_Check ( func ) );
165- assert (func != NULL );
164+ assert (func_obj != NULL );
165+ assert (PyCFunction_Check ( func_obj ) );
166166 assert (nargs >= 0 );
167167 assert (nargs == 0 || args != NULL );
168168 assert (kwargs == NULL || PyDict_Check (kwargs ));
@@ -172,55 +172,51 @@ _PyCFunction_FastCallDict(PyObject *func_obj, PyObject **args, Py_ssize_t nargs,
172172 caller loses its exception */
173173 assert (!PyErr_Occurred ());
174174
175+ func = (PyCFunctionObject * )func_obj ;
176+ meth = PyCFunction_GET_FUNCTION (func );
177+ self = PyCFunction_GET_SELF (func );
175178 flags = PyCFunction_GET_FLAGS (func ) & ~(METH_CLASS | METH_STATIC | METH_COEXIST );
176179
177180 switch (flags )
178181 {
179182 case METH_NOARGS :
183+ if (nargs != 0 ) {
184+ goto no_keyword_error ;
185+ }
186+
180187 if (kwargs != NULL && PyDict_GET_SIZE (kwargs ) != 0 ) {
181188 PyErr_Format (PyExc_TypeError , "%.200s() takes no keyword arguments" ,
182189 func -> m_ml -> ml_name );
183190 return NULL ;
184191 }
185192
186- if (nargs != 0 ) {
187- PyErr_Format (PyExc_TypeError ,
188- "%.200s() takes no arguments (%zd given)" ,
189- func -> m_ml -> ml_name , nargs );
190- return NULL ;
191- }
192-
193193 result = (* meth ) (self , NULL );
194194 break ;
195195
196196 case METH_O :
197- if (kwargs != NULL && PyDict_GET_SIZE (kwargs ) != 0 ) {
198- PyErr_Format (PyExc_TypeError , "%.200s() takes no keyword arguments" ,
199- func -> m_ml -> ml_name );
200- return NULL ;
201- }
202-
203197 if (nargs != 1 ) {
204198 PyErr_Format (PyExc_TypeError ,
205199 "%.200s() takes exactly one argument (%zd given)" ,
206200 func -> m_ml -> ml_name , nargs );
207201 return NULL ;
208202 }
209203
204+ if (kwargs != NULL && PyDict_GET_SIZE (kwargs ) != 0 ) {
205+ goto no_keyword_error ;
206+ }
207+
210208 result = (* meth ) (self , args [0 ]);
211209 break ;
212210
213211 case METH_VARARGS :
214212 case METH_VARARGS | METH_KEYWORDS :
215213 {
216- /* Slow-path: create a temporary tuple */
214+ /* Slow-path: create a temporary tuple for positional arguments */
217215 PyObject * tuple ;
218216
219- if (!(flags & METH_KEYWORDS ) && kwargs != NULL && PyDict_GET_SIZE (kwargs ) != 0 ) {
220- PyErr_Format (PyExc_TypeError ,
221- "%.200s() takes no keyword arguments" ,
222- func -> m_ml -> ml_name );
223- return NULL ;
217+ if (!(flags & METH_KEYWORDS )
218+ && kwargs != NULL && PyDict_GET_SIZE (kwargs ) != 0 ) {
219+ goto no_keyword_error ;
224220 }
225221
226222 tuple = _PyStack_AsTuple (args , nargs );
@@ -267,35 +263,134 @@ _PyCFunction_FastCallDict(PyObject *func_obj, PyObject **args, Py_ssize_t nargs,
267263 result = _Py_CheckFunctionResult (func_obj , result , NULL );
268264
269265 return result ;
266+
267+ no_keyword_error :
268+ PyErr_Format (PyExc_TypeError ,
269+ "%.200s() takes no arguments (%zd given)" ,
270+ func -> m_ml -> ml_name , nargs );
271+ return NULL ;
270272}
271273
272274PyObject *
273- _PyCFunction_FastCallKeywords (PyObject * func , PyObject * * stack ,
275+ _PyCFunction_FastCallKeywords (PyObject * func_obj , PyObject * * args ,
274276 Py_ssize_t nargs , PyObject * kwnames )
275277{
276- PyObject * kwdict , * result ;
278+ PyCFunctionObject * func ;
279+ PyCFunction meth ;
280+ PyObject * self , * result ;
277281 Py_ssize_t nkwargs = (kwnames == NULL ) ? 0 : PyTuple_GET_SIZE (kwnames );
282+ int flags ;
278283
279- assert (PyCFunction_Check (func ));
284+ assert (func_obj != NULL );
285+ assert (PyCFunction_Check (func_obj ));
280286 assert (nargs >= 0 );
281287 assert (kwnames == NULL || PyTuple_CheckExact (kwnames ));
282- assert ((nargs == 0 && nkwargs == 0 ) || stack != NULL );
288+ assert ((nargs == 0 && nkwargs == 0 ) || args != NULL );
283289 /* kwnames must only contains str strings, no subclass, and all keys must
284290 be unique */
285291
286- if (nkwargs > 0 ) {
287- kwdict = _PyStack_AsDict (stack + nargs , kwnames );
288- if (kwdict == NULL ) {
292+ /* _PyCFunction_FastCallKeywords() must not be called with an exception
293+ set, because it can clear it (directly or indirectly) and so the caller
294+ loses its exception */
295+ assert (!PyErr_Occurred ());
296+
297+ func = (PyCFunctionObject * )func_obj ;
298+ meth = PyCFunction_GET_FUNCTION (func );
299+ self = PyCFunction_GET_SELF (func );
300+ flags = PyCFunction_GET_FLAGS (func ) & ~(METH_CLASS | METH_STATIC | METH_COEXIST );
301+
302+ switch (flags )
303+ {
304+ case METH_NOARGS :
305+ if (nargs != 0 ) {
306+ PyErr_Format (PyExc_TypeError ,
307+ "%.200s() takes no arguments (%zd given)" ,
308+ func -> m_ml -> ml_name , nargs );
309+ return NULL ;
310+ }
311+
312+ if (nkwargs ) {
313+ goto no_keyword_error ;
314+ }
315+
316+ result = (* meth ) (self , NULL );
317+ break ;
318+
319+ case METH_O :
320+ if (nargs != 1 ) {
321+ PyErr_Format (PyExc_TypeError ,
322+ "%.200s() takes exactly one argument (%zd given)" ,
323+ func -> m_ml -> ml_name , nargs );
289324 return NULL ;
290325 }
326+
327+ if (nkwargs ) {
328+ goto no_keyword_error ;
329+ }
330+
331+ result = (* meth ) (self , args [0 ]);
332+ break ;
333+
334+ case METH_FASTCALL :
335+ /* Fast-path: avoid temporary dict to pass keyword arguments */
336+ result = ((_PyCFunctionFast )meth ) (self , args , nargs , kwnames );
337+ break ;
338+
339+ case METH_VARARGS :
340+ case METH_VARARGS | METH_KEYWORDS :
341+ {
342+ /* Slow-path: create a temporary tuple for positional arguments
343+ and a temporary dict for keyword arguments */
344+ PyObject * argtuple ;
345+
346+ if (!(flags & METH_KEYWORDS ) && nkwargs ) {
347+ goto no_keyword_error ;
348+ }
349+
350+ argtuple = _PyStack_AsTuple (args , nargs );
351+ if (argtuple == NULL ) {
352+ return NULL ;
353+ }
354+
355+ if (flags & METH_KEYWORDS ) {
356+ PyObject * kwdict ;
357+
358+ if (nkwargs > 0 ) {
359+ kwdict = _PyStack_AsDict (args + nargs , kwnames );
360+ if (kwdict == NULL ) {
361+ Py_DECREF (argtuple );
362+ return NULL ;
363+ }
364+ }
365+ else {
366+ kwdict = NULL ;
367+ }
368+
369+ result = (* (PyCFunctionWithKeywords )meth ) (self , argtuple , kwdict );
370+ Py_XDECREF (kwdict );
371+ }
372+ else {
373+ result = (* meth ) (self , argtuple );
374+ }
375+ Py_DECREF (argtuple );
376+ break ;
291377 }
292- else {
293- kwdict = NULL ;
378+
379+ default :
380+ PyErr_SetString (PyExc_SystemError ,
381+ "Bad call flags in _PyCFunction_FastCallKeywords. "
382+ "METH_OLDARGS is no longer supported!" );
383+ return NULL ;
294384 }
295385
296- result = _PyCFunction_FastCallDict (func , stack , nargs , kwdict );
297- Py_XDECREF (kwdict );
386+ result = _Py_CheckFunctionResult (func_obj , result , NULL );
298387 return result ;
388+
389+ no_keyword_error :
390+ PyErr_Format (PyExc_TypeError ,
391+ "%.200s() takes no keyword arguments" ,
392+ func -> m_ml -> ml_name );
393+ return NULL ;
299394}
300395
301396/* Methods (the standard built-in methods, that is) */
0 commit comments