summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2008-11-17 22:45:50 (GMT)
committerBenjamin Peterson <benjamin@python.org>2008-11-17 22:45:50 (GMT)
commit9262b849fba5cb6930a59114cdd6f95ad2847abb (patch)
treeed344f20374c141944dea26d6082a118bca5a7ca /Objects
parentce0506ced3f04e751eb841111b43ce9c29fcdd07 (diff)
downloadcpython-9262b849fba5cb6930a59114cdd6f95ad2847abb.zip
cpython-9262b849fba5cb6930a59114cdd6f95ad2847abb.tar.gz
cpython-9262b849fba5cb6930a59114cdd6f95ad2847abb.tar.bz2
Merged revisions 67246 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r67246 | benjamin.peterson | 2008-11-17 16:39:09 -0600 (Mon, 17 Nov 2008) | 5 lines when __getattr__ is a descriptor, call it correctly; fixes #4230 patch from Ziga Seilnacht ........
Diffstat (limited to 'Objects')
-rw-r--r--Objects/typeobject.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 7f9551f..7f9a26d 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -4960,6 +4960,24 @@ slot_tp_getattro(PyObject *self, PyObject *name)
}
static PyObject *
+call_attribute(PyObject *self, PyObject *attr, PyObject *name)
+{
+ PyObject *res, *descr = NULL;
+ descrgetfunc f = Py_TYPE(attr)->tp_descr_get;
+
+ if (f != NULL) {
+ descr = f(attr, self, (PyObject *)(Py_TYPE(self)));
+ if (descr == NULL)
+ return NULL;
+ else
+ attr = descr;
+ }
+ res = PyObject_CallFunctionObjArgs(attr, name, NULL);
+ Py_XDECREF(descr);
+ return res;
+}
+
+static PyObject *
slot_tp_getattr_hook(PyObject *self, PyObject *name)
{
PyTypeObject *tp = Py_TYPE(self);
@@ -4978,24 +4996,39 @@ slot_tp_getattr_hook(PyObject *self, PyObject *name)
if (getattribute_str == NULL)
return NULL;
}
+ /* speed hack: we could use lookup_maybe, but that would resolve the
+ method fully for each attribute lookup for classes with
+ __getattr__, even when the attribute is present. So we use
+ _PyType_Lookup and create the method only when needed, with
+ call_attribute. */
getattr = _PyType_Lookup(tp, getattr_str);
if (getattr == NULL) {
/* No __getattr__ hook: use a simpler dispatcher */
tp->tp_getattro = slot_tp_getattro;
return slot_tp_getattro(self, name);
}
+ Py_INCREF(getattr);
+ /* speed hack: we could use lookup_maybe, but that would resolve the
+ method fully for each attribute lookup for classes with
+ __getattr__, even when self has the default __getattribute__
+ method. So we use _PyType_Lookup and create the method only when
+ needed, with call_attribute. */
getattribute = _PyType_Lookup(tp, getattribute_str);
if (getattribute == NULL ||
(Py_TYPE(getattribute) == &PyWrapperDescr_Type &&
((PyWrapperDescrObject *)getattribute)->d_wrapped ==
(void *)PyObject_GenericGetAttr))
res = PyObject_GenericGetAttr(self, name);
- else
- res = PyObject_CallFunctionObjArgs(getattribute, self, name, NULL);
+ else {
+ Py_INCREF(getattribute);
+ res = call_attribute(self, getattribute, name);
+ Py_DECREF(getattribute);
+ }
if (res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
- res = PyObject_CallFunctionObjArgs(getattr, self, name, NULL);
+ res = call_attribute(self, getattr, name);
}
+ Py_DECREF(getattr);
return res;
}