summaryrefslogtreecommitdiff
path: root/Objects/funcobject.c
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2001-09-17 23:46:56 +0000
committerGuido van Rossum <guido@python.org>2001-09-17 23:46:56 +0000
commit7917b9eea89a8eff0afa362482ed5502f25b77f7 (patch)
tree2ea3296ee5d392222eaa5543a841f2eed19d57ef /Objects/funcobject.c
parent63d6743c2f212ca68ba0b18d238991d437ebe574 (diff)
downloadcpython-7917b9eea89a8eff0afa362482ed5502f25b77f7.tar.gz
Rewrite function attributes to use the generic routines properly.
This uses the new "restricted" feature of structmember, and getset descriptors for some of the type checks.
Diffstat (limited to 'Objects/funcobject.c')
-rw-r--r--Objects/funcobject.c190
1 files changed, 118 insertions, 72 deletions
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index 57d02fefd9..91a312759f 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -127,99 +127,145 @@ PyFunction_SetClosure(PyObject *op, PyObject *closure)
#define OFF(x) offsetof(PyFunctionObject, x)
+#define RR ()
+
static struct memberlist func_memberlist[] = {
- {"func_code", T_OBJECT, OFF(func_code)},
- {"func_globals", T_OBJECT, OFF(func_globals), READONLY},
+ {"func_closure", T_OBJECT, OFF(func_closure),
+ RESTRICTED|READONLY},
+ {"func_doc", T_OBJECT, OFF(func_doc), WRITE_RESTRICTED},
+ {"__doc__", T_OBJECT, OFF(func_doc), WRITE_RESTRICTED},
+ {"func_globals", T_OBJECT, OFF(func_globals),
+ RESTRICTED|READONLY},
{"func_name", T_OBJECT, OFF(func_name), READONLY},
{"__name__", T_OBJECT, OFF(func_name), READONLY},
- {"func_closure", T_OBJECT, OFF(func_closure), READONLY},
- {"func_defaults", T_OBJECT, OFF(func_defaults)},
- {"func_doc", T_OBJECT, OFF(func_doc)},
- {"__doc__", T_OBJECT, OFF(func_doc)},
- {"func_dict", T_OBJECT, OFF(func_dict)},
- {"__dict__", T_OBJECT, OFF(func_dict)},
{NULL} /* Sentinel */
};
+static int
+restricted(void)
+{
+ if (!PyEval_GetRestricted())
+ return 0;
+ PyErr_SetString(PyExc_RuntimeError,
+ "function attributes not accessible in restricted mode");
+ return 1;
+}
+
static PyObject *
-func_getattro(PyObject *op, PyObject *name)
+func_get_dict(PyFunctionObject *op)
{
- char *sname = PyString_AsString(name);
-
- if (sname[0] != '_' && PyEval_GetRestricted()) {
- PyErr_SetString(PyExc_RuntimeError,
- "function attributes not accessible in restricted mode");
+ if (restricted())
return NULL;
- }
- /* If func_dict is being accessed but no attribute has been set
- * yet, then initialize it to the empty dictionary.
- */
- if ((!strcmp(sname, "func_dict") || !strcmp(sname, "__dict__"))
- && ((PyFunctionObject*)op)->func_dict == NULL)
- {
- PyFunctionObject* funcop = (PyFunctionObject*)op;
-
- funcop->func_dict = PyDict_New();
- if (funcop->func_dict == NULL)
+ if (op->func_dict == NULL) {
+ op->func_dict = PyDict_New();
+ if (op->func_dict == NULL)
return NULL;
}
- return PyObject_GenericGetAttr(op, name);
+ Py_INCREF(op->func_dict);
+ return op->func_dict;
}
static int
-func_setattro(PyObject *op, PyObject *name, PyObject *value)
+func_set_dict(PyFunctionObject *op, PyObject *value)
{
- char *sname = PyString_AsString(name);
+ PyObject *tmp;
- if (PyEval_GetRestricted()) {
- PyErr_SetString(PyExc_RuntimeError,
- "function attributes not settable in restricted mode");
+ if (restricted())
+ return -1;
+ /* It is illegal to del f.func_dict */
+ if (value == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "function's dictionary may not be deleted");
+ return -1;
+ }
+ /* Can only set func_dict to a dictionary */
+ if (!PyDict_Check(value)) {
+ PyErr_SetString(PyExc_TypeError,
+ "setting function's dictionary to a non-dict");
return -1;
}
- if (strcmp(sname, "func_code") == 0) {
- /* not legal to del f.func_code or to set it to anything
- * other than a code object.
- */
- if (value == NULL || !PyCode_Check(value)) {
- PyErr_SetString(
- PyExc_TypeError,
+ tmp = op->func_dict;
+ Py_INCREF(value);
+ op->func_dict = value;
+ Py_XDECREF(tmp);
+ return 0;
+}
+
+static PyObject *
+func_get_code(PyFunctionObject *op)
+{
+ if (restricted())
+ return NULL;
+ Py_INCREF(op->func_code);
+ return op->func_code;
+}
+
+static int
+func_set_code(PyFunctionObject *op, PyObject *value)
+{
+ PyObject *tmp;
+
+ if (restricted())
+ return -1;
+ /* Not legal to del f.func_code or to set it to anything
+ * other than a code object. */
+ if (value == NULL || !PyCode_Check(value)) {
+ PyErr_SetString(PyExc_TypeError,
"func_code must be set to a code object");
- return -1;
- }
+ return -1;
}
- else if (strcmp(sname, "func_defaults") == 0) {
- /* legal to del f.func_defaults. Can only set
- * func_defaults to NULL or a tuple.
- */
- if (value == Py_None)
- value = NULL;
- if (value != NULL && !PyTuple_Check(value)) {
- PyErr_SetString(
- PyExc_TypeError,
- "func_defaults must be set to a tuple object");
- return -1;
- }
+ tmp = op->func_code;
+ Py_INCREF(value);
+ op->func_code = value;
+ Py_DECREF(tmp);
+ return 0;
+}
+
+static PyObject *
+func_get_defaults(PyFunctionObject *op)
+{
+ if (restricted())
+ return NULL;
+ if (op->func_defaults == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
}
- else if (!strcmp(sname, "func_dict") || !strcmp(sname, "__dict__")) {
- /* It is illegal to del f.func_dict. Can only set
- * func_dict to a dictionary.
- */
- if (value == NULL) {
- PyErr_SetString(
- PyExc_TypeError,
- "function's dictionary may not be deleted");
- return -1;
- }
- if (!PyDict_Check(value)) {
- PyErr_SetString(
- PyExc_TypeError,
- "setting function's dictionary to a non-dict");
- return -1;
- }
+ Py_INCREF(op->func_defaults);
+ return op->func_defaults;
+}
+
+static int
+func_set_defaults(PyFunctionObject *op, PyObject *value)
+{
+ PyObject *tmp;
+
+ if (restricted())
+ return -1;
+ /* Legal to del f.func_defaults.
+ * Can only set func_defaults to NULL or a tuple. */
+ if (value == Py_None)
+ value = NULL;
+ if (value != NULL && !PyTuple_Check(value)) {
+ PyErr_SetString(PyExc_TypeError,
+ "func_defaults must be set to a tuple object");
+ return -1;
}
- return PyObject_GenericSetAttr(op, name, value);
+ tmp = op->func_defaults;
+ Py_XINCREF(value);
+ op->func_defaults = value;
+ Py_XDECREF(tmp);
+ return 0;
}
+static struct getsetlist func_getsetlist[] = {
+ {"func_code", (getter)func_get_code, (setter)func_set_code},
+ {"func_defaults", (getter)func_get_defaults,
+ (setter)func_set_defaults},
+ {"func_dict", (getter)func_get_dict, (setter)func_set_dict},
+ {"__dict__", (getter)func_get_dict, (setter)func_set_dict},
+ {NULL} /* Sentinel */
+};
+
static void
func_dealloc(PyFunctionObject *op)
{
@@ -365,8 +411,8 @@ PyTypeObject PyFunction_Type = {
0, /* tp_hash */
function_call, /* tp_call */
0, /* tp_str */
- func_getattro, /* tp_getattro */
- func_setattro, /* tp_setattro */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ PyObject_GenericSetAttr, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
@@ -378,7 +424,7 @@ PyTypeObject PyFunction_Type = {
0, /* tp_iternext */
0, /* tp_methods */
func_memberlist, /* tp_members */
- 0, /* tp_getset */
+ func_getsetlist, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
func_descr_get, /* tp_descr_get */