[Python-checkins] r72461 - in python/trunk: Include/object.h Lib/test/test_descr.py Objects/object.c Objects/typeobject.c
benjamin.peterson
python-checkins at python.org
Fri May 8 05:06:01 CEST 2009
Author: benjamin.peterson
Date: Fri May 8 05:06:00 2009
New Revision: 72461
Log:
add _PyObject_LookupSpecial to handle fetching special method lookup
Modified:
python/trunk/Include/object.h
python/trunk/Lib/test/test_descr.py
python/trunk/Objects/object.c
python/trunk/Objects/typeobject.c
Modified: python/trunk/Include/object.h
==============================================================================
--- python/trunk/Include/object.h (original)
+++ python/trunk/Include/object.h Fri May 8 05:06:00 2009
@@ -451,6 +451,7 @@
PyAPI_FUNC(PyObject *) PyType_GenericNew(PyTypeObject *,
PyObject *, PyObject *);
PyAPI_FUNC(PyObject *) _PyType_Lookup(PyTypeObject *, PyObject *);
+PyAPI_FUNC(PyObject *) _PyObject_LookupSpecial(PyObject *, char *, PyObject **);
PyAPI_FUNC(unsigned int) PyType_ClearCache(void);
PyAPI_FUNC(void) PyType_Modified(PyTypeObject *);
Modified: python/trunk/Lib/test/test_descr.py
==============================================================================
--- python/trunk/Lib/test/test_descr.py (original)
+++ python/trunk/Lib/test/test_descr.py Fri May 8 05:06:00 2009
@@ -1665,6 +1665,58 @@
self.assertEqual(E().foo, C.foo) # i.e., unbound
self.assert_(repr(C.foo.__get__(C(1))).startswith("<bound method "))
+ def test_special_method_lookup(self):
+ # The lookup of special methods bypasses __getattr__ and
+ # __getattribute__, but they still can be descriptors.
+
+ def run_context(manager):
+ with manager:
+ pass
+ def iden(self):
+ return self
+ def hello(self):
+ return "hello"
+
+ # It would be nice to have every special method tested here, but I'm
+ # only listing the ones I can remember outside of typeobject.c, since it
+ # does it right.
+ specials = [
+ ("__unicode__", unicode, hello),
+ # These two fail because the compiler generates LOAD_ATTR to look
+ # them up. We'd have to add a new opcode to fix this, and it's
+ # probably not worth it.
+ # ("__enter__", run_context, iden),
+ # ("__exit__", run_context, iden),
+ ]
+
+ class Checker(object):
+ def __getattr__(self, attr, test=self):
+ test.fail("__getattr__ called with {0}".format(attr))
+ def __getattribute__(self, attr, test=self):
+ test.fail("__getattribute__ called with {0}".format(attr))
+ class SpecialDescr(object):
+ def __init__(self, impl):
+ self.impl = impl
+ def __get__(self, obj, owner):
+ record.append(1)
+ return self
+ def __call__(self, *args):
+ return self.impl(*args)
+
+
+ for name, runner, meth_impl in specials:
+ class X(Checker):
+ pass
+ setattr(X, name, staticmethod(meth_impl))
+ runner(X())
+
+ record = []
+ class X(Checker):
+ pass
+ setattr(X, name, SpecialDescr(meth_impl))
+ runner(X())
+ self.assertEqual(record, [1], name)
+
def test_specials(self):
# Testing special operators...
# Test operators like __hash__ for which a built-in default exists
Modified: python/trunk/Objects/object.c
==============================================================================
--- python/trunk/Objects/object.c (original)
+++ python/trunk/Objects/object.c Fri May 8 05:06:00 2009
@@ -488,12 +488,6 @@
return v;
}
- /* Try the __unicode__ method */
- if (unicodestr == NULL) {
- unicodestr= PyString_InternFromString("__unicode__");
- if (unicodestr == NULL)
- return NULL;
- }
if (PyInstance_Check(v)) {
/* We're an instance of a classic class */
/* Try __unicode__ from the instance -- alas we have no type */
@@ -508,15 +502,12 @@
}
}
else {
- /* Not a classic class instance, try __unicode__ from type */
- /* _PyType_Lookup doesn't create a reference */
- func = _PyType_Lookup(Py_TYPE(v), unicodestr);
+ /* Not a classic class instance, try __unicode__. */
+ func = _PyObject_LookupSpecial(v, "__unicode__", &unicodestr);
if (func != NULL) {
unicode_method_found = 1;
res = PyObject_CallFunctionObjArgs(func, v, NULL);
- }
- else {
- PyErr_Clear();
+ Py_DECREF(func);
}
}
Modified: python/trunk/Objects/typeobject.c
==============================================================================
--- python/trunk/Objects/typeobject.c (original)
+++ python/trunk/Objects/typeobject.c Fri May 8 05:06:00 2009
@@ -1179,6 +1179,8 @@
when the _PyType_Lookup() call fails;
- lookup_method() always raises an exception upon errors.
+
+ - _PyObject_LookupSpecial() exported for the benefit of other places.
*/
static PyObject *
@@ -1211,6 +1213,12 @@
return res;
}
+PyObject *
+_PyObject_LookupSpecial(PyObject *self, char *attrstr, PyObject **attrobj)
+{
+ return lookup_maybe(self, attrstr, attrobj);
+}
+
/* A variation of PyObject_CallMethod that uses lookup_method()
instead of PyObject_GetAttrString(). This uses the same convention
as lookup_method to cache the interned name string object. */
More information about the Python-checkins
mailing list