Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0dabace

Browse files
committed
Make function objects somewhat mutable -- the members func_code,
func_defaults and func_doc (alias __doc__) may be assigned to. For the first two, there's a type restriction to code object and tuple, respectively.
1 parent b1ed9c5 commit 0dabace

1 file changed

Lines changed: 35 additions & 3 deletions

File tree

Objects/funcobject.c

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,11 @@ PyFunction_SetDefaults(op, defaults)
127127
#define OFF(x) offsetof(PyFunctionObject, x)
128128

129129
static 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+
153185
static void
154186
func_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

Comments
 (0)