[Python-checkins] r64791 - in python/trunk: Lib/test/test_exceptions.py Objects/exceptions.c Objects/object.c

nick.coghlan python-checkins at python.org
Tue Jul 8 16:08:04 CEST 2008


Author: nick.coghlan
Date: Tue Jul  8 16:08:04 2008
New Revision: 64791

Log:
Issue 2517: Allow unicode messages in Exceptions again by correctly bypassing the instance dictionary when looking up __unicode__ on new-style classes

Modified:
   python/trunk/Lib/test/test_exceptions.py
   python/trunk/Objects/exceptions.c
   python/trunk/Objects/object.c

Modified: python/trunk/Lib/test/test_exceptions.py
==============================================================================
--- python/trunk/Lib/test/test_exceptions.py	(original)
+++ python/trunk/Lib/test/test_exceptions.py	Tue Jul  8 16:08:04 2008
@@ -342,6 +342,7 @@
         self.failUnless(unicode(Exception))
         self.failUnless(str(Exception('a')))
         self.failUnless(unicode(Exception(u'a')))
+        self.failUnless(unicode(Exception(u'\xe1')))
 
 
 def test_main():

Modified: python/trunk/Objects/exceptions.c
==============================================================================
--- python/trunk/Objects/exceptions.c	(original)
+++ python/trunk/Objects/exceptions.c	Tue Jul  8 16:08:04 2008
@@ -117,6 +117,28 @@
     return out;
 }
 
+#ifdef Py_USING_UNICODE
+static PyObject *
+BaseException_unicode(PyBaseExceptionObject *self)
+{
+    PyObject *out;
+
+    switch (PyTuple_GET_SIZE(self->args)) {
+    case 0:
+        out = PyUnicode_FromString("");
+        break;
+    case 1:
+        out = PyObject_Unicode(PyTuple_GET_ITEM(self->args, 0));
+        break;
+    default:
+        out = PyObject_Unicode(self->args);
+        break;
+    }
+
+    return out;
+}
+#endif
+
 static PyObject *
 BaseException_repr(PyBaseExceptionObject *self)
 {
@@ -181,6 +203,9 @@
 static PyMethodDef BaseException_methods[] = {
    {"__reduce__", (PyCFunction)BaseException_reduce, METH_NOARGS },
    {"__setstate__", (PyCFunction)BaseException_setstate, METH_O },
+#ifdef Py_USING_UNICODE   
+   {"__unicode__", (PyCFunction)BaseException_unicode, METH_NOARGS },
+#endif
    {NULL, NULL, 0, NULL},
 };
 

Modified: python/trunk/Objects/object.c
==============================================================================
--- python/trunk/Objects/object.c	(original)
+++ python/trunk/Objects/object.c	Tue Jul  8 16:08:04 2008
@@ -458,6 +458,7 @@
 	PyObject *res;
 	PyObject *func;
 	PyObject *str;
+	int unicode_method_found = 0;
 	static PyObject *unicodestr;
 
 	if (v == NULL) {
@@ -471,26 +472,46 @@
 		Py_INCREF(v);
 		return v;
 	}
-	/* XXX As soon as we have a tp_unicode slot, we should
-	   check this before trying the __unicode__
-	   method. */
+
+	/* Try the __unicode__ method */
 	if (unicodestr == NULL) {
 		unicodestr= PyString_InternFromString("__unicode__");
 		if (unicodestr == NULL)
 			return NULL;
 	}
-	func = PyObject_GetAttr(v, unicodestr);
-	if (func != NULL) {
-		res = PyEval_CallObject(func, (PyObject *)NULL);
-		Py_DECREF(func);
+	if (PyInstance_Check(v)) {
+		/* We're an instance of a classic class */
+		/* Try __unicode__ from the instance -- alas we have no type */
+		func = PyObject_GetAttr(v, unicodestr);
+		if (func != NULL) {
+			unicode_method_found = 1;
+			res = PyObject_CallFunctionObjArgs(func, NULL);
+			Py_DECREF(func);
+		}
+		else {
+			PyErr_Clear(); 
+		}
 	}
 	else {
-		PyErr_Clear();
+		/* Not a classic class instance, try __unicode__ from type */
+		/* _PyType_Lookup doesn't create a reference */
+		func = _PyType_Lookup(Py_TYPE(v), unicodestr);
+		if (func != NULL) {
+			unicode_method_found = 1;
+			res = PyObject_CallFunctionObjArgs(func, v, NULL);
+		}
+		else {
+			PyErr_Clear();
+		}
+	}
+
+	/* Didn't find __unicode__ */
+	if (!unicode_method_found) {
 		if (PyUnicode_Check(v)) {
 			/* For a Unicode subtype that's didn't overwrite __unicode__,
 			   return a true Unicode object with the same data. */
 			return PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(v),
-			                             PyUnicode_GET_SIZE(v));
+						     PyUnicode_GET_SIZE(v));
 		}
 		if (PyString_CheckExact(v)) {
 			Py_INCREF(v);
@@ -503,6 +524,7 @@
 				res = PyObject_Repr(v);
 		}
 	}
+
 	if (res == NULL)
 		return NULL;
 	if (!PyUnicode_Check(res)) {


More information about the Python-checkins mailing list