diff options
author | Guido van Rossum <guido@python.org> | 2001-09-17 23:46:56 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2001-09-17 23:46:56 (GMT) |
commit | d9d1d4ac6fda7f4c898b55194be37b03b89450e9 (patch) | |
tree | 0524526733e2e0affab748ea0c82a82d35faac07 /Objects/funcobject.c | |
parent | 5d1e34aa4217f1c3526e2dc330c84bf836c696b8 (diff) | |
download | cpython-d9d1d4ac6fda7f4c898b55194be37b03b89450e9.zip cpython-d9d1d4ac6fda7f4c898b55194be37b03b89450e9.tar.gz cpython-d9d1d4ac6fda7f4c898b55194be37b03b89450e9.tar.bz2 |
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.c | 190 |
1 files changed, 118 insertions, 72 deletions
diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 57d02fe..91a3127 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 */ |