[Python-checkins] r72462 - in python/branches/py3k: 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:25:19 CEST 2009


Author: benjamin.peterson
Date: Fri May 8 05:25:19 2009
New Revision: 72462
Log:
Merged revisions 72461 via svnmerge from 
svn+ssh://pythondev@svn.python.org/python/trunk
........
 r72461 | benjamin.peterson | 2009年05月07日 22:06:00 -0500 (2009年5月07日) | 1 line
 
 add _PyObject_LookupSpecial to handle fetching special method lookup
........
Modified:
 python/branches/py3k/ (props changed)
 python/branches/py3k/Include/object.h
 python/branches/py3k/Lib/test/test_descr.py
 python/branches/py3k/Objects/object.c
 python/branches/py3k/Objects/typeobject.c
Modified: python/branches/py3k/Include/object.h
==============================================================================
--- python/branches/py3k/Include/object.h	(original)
+++ python/branches/py3k/Include/object.h	Fri May 8 05:25:19 2009
@@ -414,6 +414,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/branches/py3k/Lib/test/test_descr.py
==============================================================================
--- python/branches/py3k/Lib/test/test_descr.py	(original)
+++ python/branches/py3k/Lib/test/test_descr.py	Fri May 8 05:25:19 2009
@@ -1538,6 +1538,58 @@
 self.assertEqual(E().foo.__func__, 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 b"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 = [
+ ("__bytes__", bytes, 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/branches/py3k/Objects/object.c
==============================================================================
--- python/branches/py3k/Objects/object.c	(original)
+++ python/branches/py3k/Objects/object.c	Fri May 8 05:25:19 2009
@@ -474,12 +474,6 @@
 	PyObject *result, *func;
 	static PyObject *bytesstring = NULL;
 
-	if (bytesstring == NULL) {
-		bytesstring = PyUnicode_InternFromString("__bytes__");
-		if (bytesstring == NULL)
-			return NULL;
-	}
-
 	if (v == NULL)
 		return PyBytes_FromString("<NULL>");
 
@@ -488,10 +482,10 @@
 		return v;
 	}
 
- /* Doesn't create a reference */
-	func = _PyType_Lookup(Py_TYPE(v), bytesstring);
+	func = _PyObject_LookupSpecial(v, "__bytes__", &bytesstring);
 	if (func != NULL) {
 result = PyObject_CallFunctionObjArgs(func, v, NULL);
+	 Py_DECREF(func);
 if (result == NULL)
 		return NULL;
 if (!PyBytes_Check(result)) {
@@ -503,7 +497,6 @@
 }
 return result;
 	}
- PyErr_Clear();
 	return PyBytes_FromObject(v);
 }
 
Modified: python/branches/py3k/Objects/typeobject.c
==============================================================================
--- python/branches/py3k/Objects/typeobject.c	(original)
+++ python/branches/py3k/Objects/typeobject.c	Fri May 8 05:25:19 2009
@@ -1125,6 +1125,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 *
@@ -1157,6 +1159,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

AltStyle によって変換されたページ (->オリジナル) /