]> granicus.if.org Git - python/commitdiff
Issue 2517: Allow unicode messages in Exceptions again by correctly bypassing the...
authorNick Coghlan <ncoghlan@gmail.com>
Tue, 8 Jul 2008 14:08:04 +0000 (14:08 +0000)
committerNick Coghlan <ncoghlan@gmail.com>
Tue, 8 Jul 2008 14:08:04 +0000 (14:08 +0000)
Lib/test/test_exceptions.py
Objects/exceptions.c
Objects/object.c

index 77a6018f361324432da74f87e80d11bf280b25b3..8fa466cc888c2978d4b4031ac30b1c9f457522e8 100644 (file)
@@ -342,6 +342,7 @@ class ExceptionTests(unittest.TestCase):
         self.failUnless(unicode(Exception))
         self.failUnless(str(Exception('a')))
         self.failUnless(unicode(Exception(u'a')))
+        self.failUnless(unicode(Exception(u'\xe1')))
 
 
 def test_main():
index 48b47b06102747e214cfce232f2fdb90d2734d4f..c0254ff4a1cf6e2d1158cd005feea04dff1d0bc9 100644 (file)
@@ -117,6 +117,28 @@ BaseException_str(PyBaseExceptionObject *self)
     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 @@ BaseException_setstate(PyObject *self, PyObject *state)
 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},
 };
 
index ccb5ab78ce4f280c56b8e72fcd01815de00b99c9..f40fd9f5878da5e92c5603ef013cae423b9091ad 100644 (file)
@@ -458,6 +458,7 @@ PyObject_Unicode(PyObject *v)
        PyObject *res;
        PyObject *func;
        PyObject *str;
+       int unicode_method_found = 0;
        static PyObject *unicodestr;
 
        if (v == NULL) {
@@ -471,26 +472,46 @@ PyObject_Unicode(PyObject *v)
                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 @@ PyObject_Unicode(PyObject *v)
                                res = PyObject_Repr(v);
                }
        }
+
        if (res == NULL)
                return NULL;
        if (!PyUnicode_Check(res)) {