summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1998-05-22 00:55:34 (GMT)
committerGuido van Rossum <guido@python.org>1998-05-22 00:55:34 (GMT)
commit0dabacee160cbb9d848b4e2b292e9e70aefd96f8 (patch)
tree6e04feaa1108db1c742fb391f3dd1ab0ab524ee0
parentb1ed9c529579ebeba7bafabeaa9254f8df3c33f9 (diff)
downloadcpython-0dabacee160cbb9d848b4e2b292e9e70aefd96f8.zip
cpython-0dabacee160cbb9d848b4e2b292e9e70aefd96f8.tar.gz
cpython-0dabacee160cbb9d848b4e2b292e9e70aefd96f8.tar.bz2
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.
-rw-r--r--Objects/funcobject.c38
1 files changed, 35 insertions, 3 deletions
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index d62dd08..c9dd139 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*/