summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Coghlan <ncoghlan@gmail.com>2008-07-08 14:08:04 (GMT)
committerNick Coghlan <ncoghlan@gmail.com>2008-07-08 14:08:04 (GMT)
commit524b7773ccf6f462444c22da19cf138f0c6416e4 (patch)
tree12d989a7fb762bb204889e285c6119c7ad8bd7cb
parentdbc5987e2fef558cd1410f79dbec4262b8a80d66 (diff)
downloadcpython-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.py1
-rw-r--r--Objects/exceptions.c25
-rw-r--r--Objects/object.c40
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)) {