Commit baf0f8f2 authored by Guido van Rossum's avatar Guido van Rossum

- 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.
parent bfd334a4
...@@ -12,6 +12,15 @@ What's New in Python 2.4 alpha 1? ...@@ -12,6 +12,15 @@ What's New in Python 2.4 alpha 1?
Core and builtins 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, - Critical bugfix, for SF bug 839548: if a weakref with a callback,
its callback, and its weakly referenced object, all became part of its callback, and its weakly referenced object, all became part of
cyclic garbage during a single run of garbage collection, the order cyclic garbage during a single run of garbage collection, the order
......
...@@ -2138,19 +2138,34 @@ static PyMemberDef instancemethod_memberlist[] = { ...@@ -2138,19 +2138,34 @@ static PyMemberDef instancemethod_memberlist[] = {
{NULL} /* Sentinel */ {NULL} /* Sentinel */
}; };
/* The getattr() implementation for PyMethod objects is similar to /* Christian Tismer argued convincingly that method attributes should
PyObject_GenericGetAttr(), but instead of looking in __dict__ it (nearly) always override function attributes.
asks im_self for the attribute. Then the error handling is a bit The one exception is __doc__; there's a default __doc__ which
different because we want to preserve the exception raised by the should only be used for the class, not for instances */
delegate, unless we have an alternative from our class. */
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 * static PyObject *
instancemethod_getattro(PyObject *obj, PyObject *name) instancemethod_getattro(PyObject *obj, PyObject *name)
{ {
PyMethodObject *im = (PyMethodObject *)obj; PyMethodObject *im = (PyMethodObject *)obj;
PyTypeObject *tp = obj->ob_type; PyTypeObject *tp = obj->ob_type;
PyObject *descr = NULL, *res; PyObject *descr = NULL;
descrgetfunc f = NULL;
if (PyType_HasFeature(tp, Py_TPFLAGS_HAVE_CLASS)) { if (PyType_HasFeature(tp, Py_TPFLAGS_HAVE_CLASS)) {
if (tp->tp_dict == NULL) { if (tp->tp_dict == NULL) {
...@@ -2160,30 +2175,17 @@ instancemethod_getattro(PyObject *obj, PyObject *name) ...@@ -2160,30 +2175,17 @@ instancemethod_getattro(PyObject *obj, PyObject *name)
descr = _PyType_Lookup(tp, name); descr = _PyType_Lookup(tp, name);
} }
f = NULL;
if (descr != NULL) { if (descr != NULL) {
f = TP_DESCR_GET(descr->ob_type); descrgetfunc f = TP_DESCR_GET(descr->ob_type);
if (f != NULL && PyDescr_IsData(descr)) if (f != NULL)
return f(descr, obj, (PyObject *)obj->ob_type); return f(descr, obj, (PyObject *)obj->ob_type);
else {
Py_INCREF(descr);
return descr;
}
} }
res = PyObject_GetAttr(im->im_func, name); return 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;
} }
PyDoc_STRVAR(instancemethod_doc, PyDoc_STRVAR(instancemethod_doc,
...@@ -2490,7 +2492,7 @@ PyTypeObject PyMethod_Type = { ...@@ -2490,7 +2492,7 @@ PyTypeObject PyMethod_Type = {
0, /* tp_iternext */ 0, /* tp_iternext */
0, /* tp_methods */ 0, /* tp_methods */
instancemethod_memberlist, /* tp_members */ instancemethod_memberlist, /* tp_members */
0, /* tp_getset */ instancemethod_getset, /* tp_getset */
0, /* tp_base */ 0, /* tp_base */
0, /* tp_dict */ 0, /* tp_dict */
instancemethod_descr_get, /* tp_descr_get */ instancemethod_descr_get, /* tp_descr_get */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment