@@ -2973,6 +2973,130 @@ eval_get_func_desc(PyObject *self, PyObject *func)
2973
2973
return PyUnicode_FromString (PyEval_GetFuncDesc (func ));
2974
2974
}
2975
2975
2976
+ static PyObject *
2977
+ eval_eval_code_ex (PyObject * mod , PyObject * pos_args )
2978
+ {
2979
+ PyObject * result = NULL ;
2980
+ PyObject * code ;
2981
+ PyObject * globals ;
2982
+ PyObject * locals = NULL ;
2983
+ PyObject * args = NULL ;
2984
+ PyObject * kwargs = NULL ;
2985
+ PyObject * defaults = NULL ;
2986
+ PyObject * kw_defaults = NULL ;
2987
+ PyObject * closure = NULL ;
2988
+
2989
+ PyObject * * c_kwargs = NULL ;
2990
+
2991
+ if ( !PyArg_UnpackTuple ( pos_args , "eval_code_ex" , 2 , 8 , & code , & globals , & locals , & args , & kwargs , & defaults , & kw_defaults , & closure ) )
2992
+ {
2993
+ goto exit ;
2994
+ }
2995
+
2996
+ if ( !PyCode_Check ( code ) )
2997
+ {
2998
+ PyErr_SetString ( PyExc_TypeError , "code must be a Python code object" );
2999
+ goto exit ;
3000
+ }
3001
+
3002
+ if ( !PyDict_Check ( globals ) )
3003
+ {
3004
+ PyErr_SetString ( PyExc_TypeError , "globals must be a dict" );
3005
+ goto exit ;
3006
+ }
3007
+
3008
+ if ( locals && !PyMapping_Check ( locals ) )
3009
+ {
3010
+ PyErr_SetString ( PyExc_TypeError , "locals must be a mapping" );
3011
+ goto exit ;
3012
+ }
3013
+ if ( locals == Py_None )
3014
+ locals = NULL ;
3015
+
3016
+ PyObject * * c_args = NULL ;
3017
+ Py_ssize_t c_args_len = 0 ;
3018
+ if ( args )
3019
+ {
3020
+ if ( !PyTuple_Check ( args ) )
3021
+ {
3022
+ PyErr_SetString ( PyExc_TypeError , "args must be a tuple" );
3023
+ goto exit ;
3024
+ } else {
3025
+ c_args = & PyTuple_GET_ITEM ( args , 0 );
3026
+ c_args_len = PyTuple_Size ( args );
3027
+ }
3028
+ }
3029
+
3030
+ Py_ssize_t c_kwargs_len = 0 ;
3031
+ if ( kwargs )
3032
+ {
3033
+ if ( !PyDict_Check ( kwargs ) )
3034
+ {
3035
+ PyErr_SetString ( PyExc_TypeError , "keywords must be a dict" );
3036
+ goto exit ;
3037
+ } else {
3038
+ c_kwargs_len = PyDict_Size ( kwargs );
3039
+ if ( c_kwargs_len > 0 )
3040
+ {
3041
+ c_kwargs = PyMem_NEW ( PyObject * , 2 * c_kwargs_len );
3042
+ if ( !c_kwargs )
3043
+ {
3044
+ PyErr_NoMemory ();
3045
+ goto exit ;
3046
+ }
3047
+ Py_ssize_t i = 0 ;
3048
+ Py_ssize_t pos = 0 ;
3049
+ while ( PyDict_Next ( kwargs , & pos , & c_kwargs [ i ], & c_kwargs [ i + 1 ] ) )
3050
+ i += 2 ;
3051
+ c_kwargs_len = i / 2 ;
3052
+ /* XXX This is broken if the caller deletes dict items! */
3053
+ }
3054
+ }
3055
+ }
3056
+
3057
+
3058
+ PyObject * * c_defaults = NULL ;
3059
+ Py_ssize_t c_defaults_len = 0 ;
3060
+ if ( ( defaults ) && PyTuple_Check ( defaults ) )
3061
+ {
3062
+ c_defaults = & PyTuple_GET_ITEM ( defaults , 0 );
3063
+ c_defaults_len = PyTuple_Size ( defaults );
3064
+ }
3065
+
3066
+ if ( ( kw_defaults ) && !PyDict_Check ( kw_defaults ) )
3067
+ {
3068
+ PyErr_SetString ( PyExc_TypeError , "kw_defaults must be a dict" );
3069
+ goto exit ;
3070
+ }
3071
+
3072
+ if ( ( closure ) && !PyTuple_Check ( closure ) )
3073
+ {
3074
+ PyErr_SetString ( PyExc_TypeError , "closure must be a tuple of cells" );
3075
+ goto exit ;
3076
+ }
3077
+
3078
+
3079
+ result = PyEval_EvalCodeEx (
3080
+ code ,
3081
+ globals ,
3082
+ locals ,
3083
+ c_args ,
3084
+ c_args_len ,
3085
+ c_kwargs ,
3086
+ c_kwargs_len ,
3087
+ c_defaults ,
3088
+ c_defaults_len ,
3089
+ kw_defaults ,
3090
+ closure
3091
+ );
3092
+
3093
+ exit :
3094
+ if ( c_kwargs )
3095
+ PyMem_DEL ( c_kwargs );
3096
+
3097
+ return result ;
3098
+ }
3099
+
2976
3100
static PyObject *
2977
3101
get_feature_macros (PyObject * self , PyObject * Py_UNUSED (args ))
2978
3102
{
@@ -3294,6 +3418,7 @@ static PyMethodDef TestMethods[] = {
3294
3418
{"set_exc_info" , test_set_exc_info , METH_VARARGS },
3295
3419
{"argparsing" , argparsing , METH_VARARGS },
3296
3420
{"code_newempty" , code_newempty , METH_VARARGS },
3421
+ {"eval_code_ex" , eval_eval_code_ex , METH_VARARGS },
3297
3422
{"make_exception_with_doc" , _PyCFunction_CAST (make_exception_with_doc ),
3298
3423
METH_VARARGS | METH_KEYWORDS },
3299
3424
{"make_memoryview_from_NULL_pointer" , make_memoryview_from_NULL_pointer ,
0 commit comments