Index: Objects/object.c =================================================================== --- Objects/object.c (revision 64116) +++ Objects/object.c (working copy) @@ -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 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)) { Index: Objects/exceptions.c =================================================================== --- Objects/exceptions.c (revision 64116) +++ Objects/exceptions.c (working copy) @@ -117,7 +117,29 @@ 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) { PyObject *repr_suffix; @@ -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}, }; Index: Lib/test/test_exceptions.py =================================================================== --- Lib/test/test_exceptions.py (revision 64116) +++ Lib/test/test_exceptions.py (working copy) @@ -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():