mirror of
https://github.com/python/cpython.git
synced 2025-10-09 08:31:26 +00:00
Committing PEP 232, function attribute feature, approved by Guido.
Closes SF patch #103123. funcobject.h: PyFunctionObject: add the func_dict slot. funcobject.c: PyFunction_New(): Initialize the func_dict slot to NULL. func_getattr(): Rename to func_getattro() and change the signature. It's more efficient to use attro methods and dig the C string out than it is to re-convert a C string to a PyString. Also, add support for getting the __dict__ (a.k.a. func_dict) attribute, and for getting an arbitrary function attribute. func_setattr(): Rename to func_setattro() and change the signature for the same reason. Also add support for setting __dict__ (a.k.a. func_dict) and any arbitrary function attribute. func_dealloc(): Be sure to DECREF the func_dict slot. func_traverse(): Be sure to traverse func_dict too. PyFunction_Type: make the necessary func_?etattro() changes. classobject.c: instancemethod_memberlist: Add __dict__ instancemethod_setattro(): New method to set arbitrary attributes on methods (really the underlying im_func). Raise TypeError when the instance is bound or when you're trying to set one of the reserved im_* attributes. instancemethod_getattr(): Renamed to instancemethod_getattro() since that's what it really is. Also, added support fo getting arbitrary attributes through the im_func. PyMethod_Type: Do the ?etattr{,o} dance.
This commit is contained in:
parent
4a420a0a75
commit
d6a9e84c81
3 changed files with 115 additions and 16 deletions
|
@ -1693,13 +1693,39 @@ static struct memberlist instancemethod_memberlist[] = {
|
|||
/* Dummies that are not handled by getattr() except for __members__ */
|
||||
{"__doc__", T_INT, 0},
|
||||
{"__name__", T_INT, 0},
|
||||
{"__dict__", T_OBJECT, 0},
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
static PyObject *
|
||||
instancemethod_getattr(register PyMethodObject *im, PyObject *name)
|
||||
static int
|
||||
instancemethod_setattro(register PyMethodObject *im, PyObject *name,
|
||||
PyObject *v)
|
||||
{
|
||||
char *sname = PyString_AsString(name);
|
||||
|
||||
if (PyEval_GetRestricted() ||
|
||||
strcmp(sname, "im_func") == 0 ||
|
||||
strcmp(sname, "im_self") == 0 ||
|
||||
strcmp(sname, "im_class") == 0)
|
||||
{
|
||||
PyErr_Format(PyExc_TypeError, "read-only attribute: %s",
|
||||
sname);
|
||||
return -1;
|
||||
}
|
||||
if (im->im_self != NULL) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"cannot set attributes through bound methods");
|
||||
return -1;
|
||||
}
|
||||
return PyObject_SetAttr(im->im_func, name, v);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
instancemethod_getattro(register PyMethodObject *im, PyObject *name)
|
||||
{
|
||||
PyObject *rtn;
|
||||
char *sname = PyString_AsString(name);
|
||||
if (sname[0] == '_') {
|
||||
/* Inherit __name__ and __doc__ from the callable object
|
||||
implementing the method */
|
||||
|
@ -1712,7 +1738,15 @@ instancemethod_getattr(register PyMethodObject *im, PyObject *name)
|
|||
"instance-method attributes not accessible in restricted mode");
|
||||
return NULL;
|
||||
}
|
||||
return PyMember_Get((char *)im, instancemethod_memberlist, sname);
|
||||
if (sname[0] == '_' && strcmp(sname, "__dict__") == 0)
|
||||
return PyObject_GetAttr(im->im_func, name);
|
||||
|
||||
rtn = PyMember_Get((char *)im, instancemethod_memberlist, sname);
|
||||
if (rtn == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
||||
PyErr_Clear();
|
||||
rtn = PyObject_GetAttr(im->im_func, name);
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1832,8 +1866,8 @@ PyTypeObject PyMethod_Type = {
|
|||
(hashfunc)instancemethod_hash, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
(getattrofunc)instancemethod_getattr, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
(getattrofunc)instancemethod_getattro, /*tp_getattro*/
|
||||
(setattrofunc)instancemethod_setattro, /*tp_setattro*/
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /*tp_flags*/
|
||||
0, /* tp_doc */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue