mirror of https://github.com/python/cpython.git
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.
This commit is contained in:
parent
b1ed9c5295
commit
0dabacee16
|
@ -127,11 +127,11 @@ PyFunction_SetDefaults(op, defaults)
|
||||||
#define OFF(x) offsetof(PyFunctionObject, x)
|
#define OFF(x) offsetof(PyFunctionObject, x)
|
||||||
|
|
||||||
static struct memberlist func_memberlist[] = {
|
static struct memberlist func_memberlist[] = {
|
||||||
{"func_code", T_OBJECT, OFF(func_code), READONLY},
|
{"func_code", T_OBJECT, OFF(func_code)},
|
||||||
{"func_globals",T_OBJECT, OFF(func_globals), READONLY},
|
{"func_globals",T_OBJECT, OFF(func_globals), READONLY},
|
||||||
{"func_name", T_OBJECT, OFF(func_name), READONLY},
|
{"func_name", T_OBJECT, OFF(func_name), READONLY},
|
||||||
{"__name__", T_OBJECT, OFF(func_name), READONLY},
|
{"__name__", T_OBJECT, OFF(func_name), READONLY},
|
||||||
{"func_defaults",T_OBJECT, OFF(func_defaults), READONLY},
|
{"func_defaults",T_OBJECT, OFF(func_defaults)},
|
||||||
{"func_doc", T_OBJECT, OFF(func_doc)},
|
{"func_doc", T_OBJECT, OFF(func_doc)},
|
||||||
{"__doc__", T_OBJECT, OFF(func_doc)},
|
{"__doc__", T_OBJECT, OFF(func_doc)},
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
|
@ -150,6 +150,38 @@ func_getattr(op, name)
|
||||||
return PyMember_Get((char *)op, func_memberlist, name);
|
return PyMember_Get((char *)op, func_memberlist, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
func_setattr(op, name, value)
|
||||||
|
PyFunctionObject *op;
|
||||||
|
char *name;
|
||||||
|
PyObject *value;
|
||||||
|
{
|
||||||
|
if (PyEval_GetRestricted()) {
|
||||||
|
PyErr_SetString(PyExc_RuntimeError,
|
||||||
|
"function attributes not settable in restricted mode");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (strcmp(name, "func_code") == 0) {
|
||||||
|
if (value == NULL || !PyCode_Check(value)) {
|
||||||
|
PyErr_SetString(
|
||||||
|
PyExc_TypeError,
|
||||||
|
"func_code must be set to a code object");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "func_defaults") == 0) {
|
||||||
|
if (value != Py_None && !PyTuple_Check(value)) {
|
||||||
|
PyErr_SetString(
|
||||||
|
PyExc_TypeError,
|
||||||
|
"func_defaults must be set to a tuple object");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (value == Py_None)
|
||||||
|
value = NULL;
|
||||||
|
}
|
||||||
|
return PyMember_Set((char *)op, func_memberlist, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
func_dealloc(op)
|
func_dealloc(op)
|
||||||
PyFunctionObject *op;
|
PyFunctionObject *op;
|
||||||
|
@ -216,7 +248,7 @@ PyTypeObject PyFunction_Type = {
|
||||||
(destructor)func_dealloc, /*tp_dealloc*/
|
(destructor)func_dealloc, /*tp_dealloc*/
|
||||||
0, /*tp_print*/
|
0, /*tp_print*/
|
||||||
(getattrfunc)func_getattr, /*tp_getattr*/
|
(getattrfunc)func_getattr, /*tp_getattr*/
|
||||||
0, /*tp_setattr*/
|
(setattrfunc)func_setattr, /*tp_setattr*/
|
||||||
(cmpfunc)func_compare, /*tp_compare*/
|
(cmpfunc)func_compare, /*tp_compare*/
|
||||||
(reprfunc)func_repr, /*tp_repr*/
|
(reprfunc)func_repr, /*tp_repr*/
|
||||||
0, /*tp_as_number*/
|
0, /*tp_as_number*/
|
||||||
|
|
Loading…
Reference in New Issue