@@ -127,11 +127,11 @@ PyFunction_SetDefaults(op, defaults)
127127#define OFF (x ) offsetof(PyFunctionObject, x)
128128
129129static struct memberlist func_memberlist [] = {
130- {"func_code" , T_OBJECT , OFF (func_code ), READONLY },
130+ {"func_code" , T_OBJECT , OFF (func_code )},
131131 {"func_globals" ,T_OBJECT , OFF (func_globals ), READONLY },
132132 {"func_name" , T_OBJECT , OFF (func_name ), READONLY },
133133 {"__name__" , T_OBJECT , OFF (func_name ), READONLY },
134- {"func_defaults" ,T_OBJECT , OFF (func_defaults ), READONLY },
134+ {"func_defaults" ,T_OBJECT , OFF (func_defaults )},
135135 {"func_doc" , T_OBJECT , OFF (func_doc )},
136136 {"__doc__" , T_OBJECT , OFF (func_doc )},
137137 {NULL } /* Sentinel */
@@ -150,6 +150,38 @@ func_getattr(op, name)
150150 return PyMember_Get ((char * )op , func_memberlist , name );
151151}
152152
153+ static int
154+ func_setattr (op , name , value )
155+ PyFunctionObject * op ;
156+ char * name ;
157+ PyObject * value ;
158+ {
159+ if (PyEval_GetRestricted ()) {
160+ PyErr_SetString (PyExc_RuntimeError ,
161+ "function attributes not settable in restricted mode" );
162+ return -1 ;
163+ }
164+ if (strcmp (name , "func_code" ) == 0 ) {
165+ if (value == NULL || !PyCode_Check (value )) {
166+ PyErr_SetString (
167+ PyExc_TypeError ,
168+ "func_code must be set to a code object" );
169+ return -1 ;
170+ }
171+ }
172+ else if (strcmp (name , "func_defaults" ) == 0 ) {
173+ if (value != Py_None && !PyTuple_Check (value )) {
174+ PyErr_SetString (
175+ PyExc_TypeError ,
176+ "func_defaults must be set to a tuple object" );
177+ return -1 ;
178+ }
179+ if (value == Py_None )
180+ value = NULL ;
181+ }
182+ return PyMember_Set ((char * )op , func_memberlist , name , value );
183+ }
184+
153185static void
154186func_dealloc (op )
155187 PyFunctionObject * op ;
@@ -216,7 +248,7 @@ PyTypeObject PyFunction_Type = {
216248 (destructor )func_dealloc , /*tp_dealloc*/
217249 0 , /*tp_print*/
218250 (getattrfunc )func_getattr , /*tp_getattr*/
219- 0 , /*tp_setattr*/
251+ ( setattrfunc ) func_setattr , /*tp_setattr*/
220252 (cmpfunc )func_compare , /*tp_compare*/
221253 (reprfunc )func_repr , /*tp_repr*/
222254 0 , /*tp_as_number*/
0 commit comments