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.
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 @@
 #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 @@
 	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 @@
 	(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*/