diff options
author | Barry Warsaw <barry@python.org> | 2001-01-15 20:40:19 (GMT) |
---|---|---|
committer | Barry Warsaw <barry@python.org> | 2001-01-15 20:40:19 (GMT) |
commit | d6a9e84c8193076e776a1b419148f3043e2f6330 (patch) | |
tree | c8fa0c1326e936671bab39e6a6e94138b6bf120f /Objects/classobject.c | |
parent | 4a420a0a753119bab88d60603a4305b3586982bd (diff) | |
download | cpython-d6a9e84c8193076e776a1b419148f3043e2f6330.zip cpython-d6a9e84c8193076e776a1b419148f3043e2f6330.tar.gz cpython-d6a9e84c8193076e776a1b419148f3043e2f6330.tar.bz2 |
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.
Diffstat (limited to 'Objects/classobject.c')
-rw-r--r-- | Objects/classobject.c | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/Objects/classobject.c b/Objects/classobject.c index f7fd30c..4dc72d2 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -1693,12 +1693,38 @@ 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 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_getattr(register PyMethodObject *im, PyObject *name) +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 @@ -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 */ |