From 0dabacee160cbb9d848b4e2b292e9e70aefd96f8 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Fri, 22 May 1998 00:55:34 +0000 Subject: [PATCH] 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. --- Objects/funcobject.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/Objects/funcobject.c b/Objects/funcobject.c index d62dd08c190..c9dd1398a2b 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -127,11 +127,11 @@ PyFunction_SetDefaults(op, defaults) #define OFF(x) offsetof(PyFunctionObject, x) 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_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)}, {"__doc__", T_OBJECT, OFF(func_doc)}, {NULL} /* Sentinel */ @@ -150,6 +150,38 @@ func_getattr(op, 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 func_dealloc(op) PyFunctionObject *op; @@ -216,7 +248,7 @@ PyTypeObject PyFunction_Type = { (destructor)func_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ (getattrfunc)func_getattr, /*tp_getattr*/ - 0, /*tp_setattr*/ + (setattrfunc)func_setattr, /*tp_setattr*/ (cmpfunc)func_compare, /*tp_compare*/ (reprfunc)func_repr, /*tp_repr*/ 0, /*tp_as_number*/