]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
- When method objects have an attribute that can be satisfied either
authorGuido van Rossum <guido@python.org>
Sat, 22 Nov 2003 23:55:50 +0000 (23:55 +0000)
committerGuido van Rossum <guido@python.org>
Sat, 22 Nov 2003 23:55:50 +0000 (23:55 +0000)
  by the function object or by the method object, the function
  object's attribute usually wins.  Christian Tismer pointed out that
  that this is really a mistake, because this only happens for special
  methods (like __reduce__) where the method object's version is
  really more appropriate than the function's attribute.  So from now
  on, all method attributes will have precedence over function
  attributes with the same name.

Misc/NEWS
Objects/classobject.c

index 30fe4be67f8087da1ab63304fa95813006bf652f..f7b1e96710f7ed3cf4392153df7eca3e89298fc4 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,15 @@ What's New in Python 2.4 alpha 1?
 Core and builtins
 -----------------
 
+- When method objects have an attribute that can be satisfied either
+  by the function object or by the method object, the function
+  object's attribute usually wins.  Christian Tismer pointed out that
+  that this is really a mistake, because this only happens for special
+  methods (like __reduce__) where the method object's version is
+  really more appropriate than the function's attribute.  So from now
+  on, all method attributes will have precedence over function
+  attributes with the same name.
+
 - Critical bugfix, for SF bug 839548:  if a weakref with a callback,
   its callback, and its weakly referenced object, all became part of
   cyclic garbage during a single run of garbage collection, the order
index 84b297cad95c2ab0bc27117a34bc7252610da6c3..17a564678170ee207f4e2e58db7c35647263665b 100644 (file)
@@ -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 */