diff options
author | Nick Coghlan <ncoghlan@gmail.com> | 2008-07-08 14:08:04 (GMT) |
---|---|---|
committer | Nick Coghlan <ncoghlan@gmail.com> | 2008-07-08 14:08:04 (GMT) |
commit | 524b7773ccf6f462444c22da19cf138f0c6416e4 (patch) | |
tree | 12d989a7fb762bb204889e285c6119c7ad8bd7cb | |
parent | dbc5987e2fef558cd1410f79dbec4262b8a80d66 (diff) | |
download | cpython-524b7773ccf6f462444c22da19cf138f0c6416e4.zip cpython-524b7773ccf6f462444c22da19cf138f0c6416e4.tar.gz cpython-524b7773ccf6f462444c22da19cf138f0c6416e4.tar.bz2 |
Issue 2517: Allow unicode messages in Exceptions again by correctly bypassing the instance dictionary when looking up __unicode__ on new-style classes
-rw-r--r-- | Lib/test/test_exceptions.py | 1 | ||||
-rw-r--r-- | Objects/exceptions.c | 25 | ||||
-rw-r--r-- | Objects/object.c | 40 |
3 files changed, 57 insertions, 9 deletions
diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 77a6018..8fa466c 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -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(): diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 48b47b0..c0254ff 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -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}, }; diff --git a/Objects/object.c b/Objects/object.c index ccb5ab7..f40fd9f 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -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)) { |