Issue 2517: Allow unicode messages in Exceptions again by correctly bypassing the instance dictionary when looking up __unicode__ on new-style classes
This commit is contained in:
parent
dbc5987e2f
commit
524b7773cc
|
@ -342,6 +342,7 @@ class ExceptionTests(unittest.TestCase):
|
||||||
self.failUnless(unicode(Exception))
|
self.failUnless(unicode(Exception))
|
||||||
self.failUnless(str(Exception('a')))
|
self.failUnless(str(Exception('a')))
|
||||||
self.failUnless(unicode(Exception(u'a')))
|
self.failUnless(unicode(Exception(u'a')))
|
||||||
|
self.failUnless(unicode(Exception(u'\xe1')))
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
|
|
|
@ -117,6 +117,28 @@ BaseException_str(PyBaseExceptionObject *self)
|
||||||
return out;
|
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 *
|
static PyObject *
|
||||||
BaseException_repr(PyBaseExceptionObject *self)
|
BaseException_repr(PyBaseExceptionObject *self)
|
||||||
{
|
{
|
||||||
|
@ -181,6 +203,9 @@ BaseException_setstate(PyObject *self, PyObject *state)
|
||||||
static PyMethodDef BaseException_methods[] = {
|
static PyMethodDef BaseException_methods[] = {
|
||||||
{"__reduce__", (PyCFunction)BaseException_reduce, METH_NOARGS },
|
{"__reduce__", (PyCFunction)BaseException_reduce, METH_NOARGS },
|
||||||
{"__setstate__", (PyCFunction)BaseException_setstate, METH_O },
|
{"__setstate__", (PyCFunction)BaseException_setstate, METH_O },
|
||||||
|
#ifdef Py_USING_UNICODE
|
||||||
|
{"__unicode__", (PyCFunction)BaseException_unicode, METH_NOARGS },
|
||||||
|
#endif
|
||||||
{NULL, NULL, 0, NULL},
|
{NULL, NULL, 0, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -458,6 +458,7 @@ PyObject_Unicode(PyObject *v)
|
||||||
PyObject *res;
|
PyObject *res;
|
||||||
PyObject *func;
|
PyObject *func;
|
||||||
PyObject *str;
|
PyObject *str;
|
||||||
|
int unicode_method_found = 0;
|
||||||
static PyObject *unicodestr;
|
static PyObject *unicodestr;
|
||||||
|
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
|
@ -471,21 +472,41 @@ PyObject_Unicode(PyObject *v)
|
||||||
Py_INCREF(v);
|
Py_INCREF(v);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
/* XXX As soon as we have a tp_unicode slot, we should
|
|
||||||
check this before trying the __unicode__
|
/* Try the __unicode__ method */
|
||||||
method. */
|
|
||||||
if (unicodestr == NULL) {
|
if (unicodestr == NULL) {
|
||||||
unicodestr= PyString_InternFromString("__unicode__");
|
unicodestr= PyString_InternFromString("__unicode__");
|
||||||
if (unicodestr == NULL)
|
if (unicodestr == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
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);
|
func = PyObject_GetAttr(v, unicodestr);
|
||||||
if (func != NULL) {
|
if (func != NULL) {
|
||||||
res = PyEval_CallObject(func, (PyObject *)NULL);
|
unicode_method_found = 1;
|
||||||
|
res = PyObject_CallFunctionObjArgs(func, NULL);
|
||||||
Py_DECREF(func);
|
Py_DECREF(func);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* 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)) {
|
if (PyUnicode_Check(v)) {
|
||||||
/* For a Unicode subtype that's didn't overwrite __unicode__,
|
/* 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. */
|
||||||
|
@ -503,6 +524,7 @@ PyObject_Unicode(PyObject *v)
|
||||||
res = PyObject_Repr(v);
|
res = PyObject_Repr(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res == NULL)
|
if (res == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!PyUnicode_Check(res)) {
|
if (!PyUnicode_Check(res)) {
|
||||||
|
|
Loading…
Reference in New Issue