summaryrefslogtreecommitdiffstats
path: root/Objects/classobject.c
diff options
context:
space:
mode:
authorBarry Warsaw <barry@python.org>2001-01-15 20:40:19 (GMT)
committerBarry Warsaw <barry@python.org>2001-01-15 20:40:19 (GMT)
commitd6a9e84c8193076e776a1b419148f3043e2f6330 (patch)
treec8fa0c1326e936671bab39e6a6e94138b6bf120f /Objects/classobject.c
parent4a420a0a753119bab88d60603a4305b3586982bd (diff)
downloadcpython-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.c42
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 */