summaryrefslogtreecommitdiff
path: root/Objects/classobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/classobject.c')
-rw-r--r--Objects/classobject.c58
1 files changed, 30 insertions, 28 deletions
diff --git a/Objects/classobject.c b/Objects/classobject.c
index 84b297cad9..17a5646781 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -2138,19 +2138,34 @@ static PyMemberDef instancemethod_memberlist[] = {
{NULL} /* Sentinel */
};
-/* The getattr() implementation for PyMethod objects is similar to
- PyObject_GenericGetAttr(), but instead of looking in __dict__ it
- asks im_self for the attribute. Then the error handling is a bit
- different because we want to preserve the exception raised by the
- delegate, unless we have an alternative from our class. */
+/* Christian Tismer argued convincingly that method attributes should
+ (nearly) always override function attributes.
+ The one exception is __doc__; there's a default __doc__ which
+ should only be used for the class, not for instances */
+
+static PyObject *
+instancemethod_get_doc(PyMethodObject *im, void *context)
+{
+ static PyObject *docstr;
+ if (docstr == NULL) {
+ docstr= PyString_InternFromString("__doc__");
+ if (docstr == NULL)
+ return NULL;
+ }
+ return PyObject_GetAttr(im->im_func, docstr);
+}
+
+static PyGetSetDef instancemethod_getset[] = {
+ {"__doc__", (getter)instancemethod_get_doc, NULL, NULL},
+ {0}
+};
static PyObject *
instancemethod_getattro(PyObject *obj, PyObject *name)
{
PyMethodObject *im = (PyMethodObject *)obj;
PyTypeObject *tp = obj->ob_type;
- PyObject *descr = NULL, *res;
- descrgetfunc f = NULL;
+ PyObject *descr = NULL;
if (PyType_HasFeature(tp, Py_TPFLAGS_HAVE_CLASS)) {
if (tp->tp_dict == NULL) {
@@ -2160,30 +2175,17 @@ instancemethod_getattro(PyObject *obj, PyObject *name)
descr = _PyType_Lookup(tp, name);
}
- f = NULL;
if (descr != NULL) {
- f = TP_DESCR_GET(descr->ob_type);
- if (f != NULL && PyDescr_IsData(descr))
+ descrgetfunc f = TP_DESCR_GET(descr->ob_type);
+ if (f != NULL)
return f(descr, obj, (PyObject *)obj->ob_type);
+ else {
+ Py_INCREF(descr);
+ return descr;
+ }
}
- res = PyObject_GetAttr(im->im_func, name);
- if (res != NULL || !PyErr_ExceptionMatches(PyExc_AttributeError))
- return res;
-
- if (f != NULL) {
- PyErr_Clear();
- return f(descr, obj, (PyObject *)obj->ob_type);
- }
-
- if (descr != NULL) {
- PyErr_Clear();
- Py_INCREF(descr);
- return descr;
- }
-
- assert(PyErr_Occurred());
- return NULL;
+ return PyObject_GetAttr(im->im_func, name);
}
PyDoc_STRVAR(instancemethod_doc,
@@ -2490,7 +2492,7 @@ PyTypeObject PyMethod_Type = {
0, /* tp_iternext */
0, /* tp_methods */
instancemethod_memberlist, /* tp_members */
- 0, /* tp_getset */
+ instancemethod_getset, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
instancemethod_descr_get, /* tp_descr_get */