@@ -3793,67 +3793,86 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
37933793 PyFrameObject * f ;
37943794 PyObject * retval = NULL ;
37953795 PyObject * * fastlocals , * * freevars ;
3796- PyThreadState * tstate = PyThreadState_GET () ;
3796+ PyThreadState * tstate ;
37973797 PyObject * x , * u ;
37983798 int total_args = co -> co_argcount + co -> co_kwonlyargcount ;
3799- int i ;
3800- int n = argcount ;
3801- PyObject * kwdict = NULL ;
3799+ int i , n ;
3800+ PyObject * kwdict ;
3801+
3802+ assert ((kwcount == 0 ) || (kws != NULL ));
38023803
38033804 if (globals == NULL ) {
38043805 PyErr_SetString (PyExc_SystemError ,
38053806 "PyEval_EvalCodeEx: NULL globals" );
38063807 return NULL ;
38073808 }
38083809
3810+ /* Create the frame */
3811+ tstate = PyThreadState_GET ();
38093812 assert (tstate != NULL );
3810- assert (globals != NULL );
38113813 f = PyFrame_New (tstate , co , globals , locals );
3812- if (f == NULL )
3814+ if (f == NULL ) {
38133815 return NULL ;
3814-
3816+ }
38153817 fastlocals = f -> f_localsplus ;
38163818 freevars = f -> f_localsplus + co -> co_nlocals ;
38173819
3818- /* Parse arguments. */
3820+ /* Create a dictionary for keyword parameters (**kwags) */
38193821 if (co -> co_flags & CO_VARKEYWORDS ) {
38203822 kwdict = PyDict_New ();
38213823 if (kwdict == NULL )
38223824 goto fail ;
38233825 i = total_args ;
3824- if (co -> co_flags & CO_VARARGS )
3826+ if (co -> co_flags & CO_VARARGS ) {
38253827 i ++ ;
3828+ }
38263829 SETLOCAL (i , kwdict );
38273830 }
3828- if (argcount > co -> co_argcount )
3831+ else {
3832+ kwdict = NULL ;
3833+ }
3834+
3835+ /* Copy positional arguments into local variables */
3836+ if (argcount > co -> co_argcount ) {
38293837 n = co -> co_argcount ;
3838+ }
3839+ else {
3840+ n = argcount ;
3841+ }
38303842 for (i = 0 ; i < n ; i ++ ) {
38313843 x = args [i ];
38323844 Py_INCREF (x );
38333845 SETLOCAL (i , x );
38343846 }
3847+
3848+ /* Pack other positional arguments into the *args argument */
38353849 if (co -> co_flags & CO_VARARGS ) {
38363850 u = PyTuple_New (argcount - n );
3837- if (u == NULL )
3851+ if (u == NULL ) {
38383852 goto fail ;
3853+ }
38393854 SETLOCAL (total_args , u );
38403855 for (i = n ; i < argcount ; i ++ ) {
38413856 x = args [i ];
38423857 Py_INCREF (x );
38433858 PyTuple_SET_ITEM (u , i - n , x );
38443859 }
38453860 }
3861+
3862+ /* Handle keyword arguments (passed as an array of (key, value)) */
38463863 for (i = 0 ; i < kwcount ; i ++ ) {
38473864 PyObject * * co_varnames ;
38483865 PyObject * keyword = kws [2 * i ];
38493866 PyObject * value = kws [2 * i + 1 ];
38503867 int j ;
3868+
38513869 if (keyword == NULL || !PyUnicode_Check (keyword )) {
38523870 PyErr_Format (PyExc_TypeError ,
38533871 "%U() keywords must be strings" ,
38543872 co -> co_name );
38553873 goto fail ;
38563874 }
3875+
38573876 /* Speed hack: do raw pointer compares. As names are
38583877 normally interned this should almost always hit. */
38593878 co_varnames = ((PyTupleObject * )(co -> co_varnames ))-> ob_item ;
@@ -3862,6 +3881,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
38623881 if (nm == keyword )
38633882 goto kw_found ;
38643883 }
3884+
38653885 /* Slow fallback, just in case */
38663886 for (j = 0 ; j < total_args ; j ++ ) {
38673887 PyObject * nm = co_varnames [j ];
@@ -3872,6 +3892,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
38723892 else if (cmp < 0 )
38733893 goto fail ;
38743894 }
3895+
38753896 if (j >= total_args && kwdict == NULL ) {
38763897 PyErr_Format (PyExc_TypeError ,
38773898 "%U() got an unexpected "
@@ -3880,10 +3901,12 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
38803901 keyword );
38813902 goto fail ;
38823903 }
3904+
38833905 if (PyDict_SetItem (kwdict , keyword , value ) == -1 ) {
38843906 goto fail ;
38853907 }
38863908 continue ;
3909+
38873910 kw_found :
38883911 if (GETLOCAL (j ) != NULL ) {
38893912 PyErr_Format (PyExc_TypeError ,
@@ -3896,10 +3919,14 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
38963919 Py_INCREF (value );
38973920 SETLOCAL (j , value );
38983921 }
3922+
3923+ /* Check the number of positional arguments */
38993924 if (argcount > co -> co_argcount && !(co -> co_flags & CO_VARARGS )) {
39003925 too_many_positional (co , argcount , defcount , fastlocals );
39013926 goto fail ;
39023927 }
3928+
3929+ /* Add missing positional arguments (copy default values from defs) */
39033930 if (argcount < co -> co_argcount ) {
39043931 int m = co -> co_argcount - defcount ;
39053932 int missing = 0 ;
@@ -3922,6 +3949,8 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
39223949 }
39233950 }
39243951 }
3952+
3953+ /* Add missing keyword arguments (copy default values from kwdefs) */
39253954 if (co -> co_kwonlyargcount > 0 ) {
39263955 int missing = 0 ;
39273956 for (i = co -> co_argcount ; i < total_args ; i ++ ) {
@@ -3964,12 +3993,15 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
39643993 goto fail ;
39653994 SETLOCAL (co -> co_nlocals + i , c );
39663995 }
3996+
3997+ /* Copy closure variables to free variables */
39673998 for (i = 0 ; i < PyTuple_GET_SIZE (co -> co_freevars ); ++ i ) {
39683999 PyObject * o = PyTuple_GET_ITEM (closure , i );
39694000 Py_INCREF (o );
39704001 freevars [PyTuple_GET_SIZE (co -> co_cellvars ) + i ] = o ;
39714002 }
39724003
4004+ /* Handle generator/coroutine */
39734005 if (co -> co_flags & (CO_GENERATOR | CO_COROUTINE )) {
39744006 PyObject * gen ;
39754007 PyObject * coro_wrapper = tstate -> coroutine_wrapper ;
0 commit comments