func_getattro(), func_setattro(): Implement the new semantics for

setting and deleting a function's __dict__ attribute.  Deleting
    it, or setting it to a non-dictionary result in a TypeError.  Note
    that getting it the first time magically initializes it to an
    empty dict so that func.__dict__ will always appear to be a
    dictionary (never None).

    Closes SF bug #446645.
This commit is contained in:
Barry Warsaw 2001-08-14 18:23:58 +00:00
parent 5ef99a0bc5
commit 142865cae1

View file

@ -151,7 +151,18 @@ func_getattro(PyObject *op, PyObject *name)
"function attributes not accessible in restricted mode"); "function attributes not accessible in restricted mode");
return NULL; 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)
return NULL;
}
return PyObject_GenericGetAttr(op, name); return PyObject_GenericGetAttr(op, name);
} }
@ -190,19 +201,22 @@ func_setattro(PyObject *op, PyObject *name, PyObject *value)
} }
} }
else if (!strcmp(sname, "func_dict") || !strcmp(sname, "__dict__")) { else if (!strcmp(sname, "func_dict") || !strcmp(sname, "__dict__")) {
/* legal to del f.func_dict. Can only set func_dict to /* It is illegal to del f.func_dict. Can only set
* NULL or a dictionary. * func_dict to a dictionary.
*/ */
if (value == Py_None) if (value == NULL) {
value = NULL;
if (value != NULL && !PyDict_Check(value)) {
PyErr_SetString( PyErr_SetString(
PyExc_TypeError, PyExc_TypeError,
"func_dict must be set to a dict object"); "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; return -1;
} }
} }
return PyObject_GenericSetAttr(op, name, value); return PyObject_GenericSetAttr(op, name, value);
} }