diff -r fea94f9cb5a0 Lib/test/test_codeccallbacks.py --- a/Lib/test/test_codeccallbacks.py Mon May 04 15:32:48 2015 +0300 +++ b/Lib/test/test_codeccallbacks.py Mon May 04 16:08:10 2015 +0300 @@ -1046,6 +1046,24 @@ class CodecCallbackTest(unittest.TestCas with self.assertRaises(TypeError): data.decode(encoding, "test.replacing") + def test_fake_error_class(self): + handlers = [ + codecs.strict_errors, + codecs.ignore_errors, + codecs.replace_errors, + codecs.backslashreplace_errors, + codecs.namereplace_errors, + codecs.xmlcharrefreplace_errors, + codecs.lookup_error('surrogateescape'), + codecs.lookup_error('surrogatepass'), + ] + for cls in UnicodeEncodeError, UnicodeDecodeError, UnicodeTranslateError: + class FakeUnicodeError(str): + __class__ = cls + for handler in handlers: + with self.subTest(handler=handler, error_class=cls): + self.assertRaises(TypeError, handler, FakeUnicodeError()) + if __name__ == "__main__": unittest.main() diff -r fea94f9cb5a0 Python/codecs.c --- a/Python/codecs.c Mon May 04 15:32:48 2015 +0300 +++ b/Python/codecs.c Mon May 04 16:08:10 2015 +0300 @@ -662,18 +662,9 @@ PyObject *PyCodec_LookupError(const char static void wrong_exception_type(PyObject *exc) { - _Py_IDENTIFIER(__class__); - _Py_IDENTIFIER(__name__); - PyObject *type = _PyObject_GetAttrId(exc, &PyId___class__); - if (type != NULL) { - PyObject *name = _PyObject_GetAttrId(type, &PyId___name__); - Py_DECREF(type); - if (name != NULL) { - PyErr_Format(PyExc_TypeError, - "don't know how to handle %S in error callback", name); - Py_DECREF(name); - } - } + PyErr_Format(PyExc_TypeError, + "don't know how to handle %s in error callback", + exc->ob_type->tp_name); } PyObject *PyCodec_StrictErrors(PyObject *exc) @@ -689,15 +680,24 @@ PyObject *PyCodec_StrictErrors(PyObject PyObject *PyCodec_IgnoreErrors(PyObject *exc) { Py_ssize_t end; - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + PyObject *cls = (PyObject *)exc->ob_type; + int rc; + + if ((rc = PyObject_IsSubclass(cls, PyExc_UnicodeEncodeError))) { + if (rc < 0) + return NULL; if (PyUnicodeEncodeError_GetEnd(exc, &end)) return NULL; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if ((rc = PyObject_IsSubclass(cls, PyExc_UnicodeDecodeError))) { + if (rc < 0) + return NULL; if (PyUnicodeDecodeError_GetEnd(exc, &end)) return NULL; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) { + else if ((rc = PyObject_IsSubclass(cls, PyExc_UnicodeTranslateError))) { + if (rc < 0) + return NULL; if (PyUnicodeTranslateError_GetEnd(exc, &end)) return NULL; } @@ -712,11 +712,15 @@ PyObject *PyCodec_IgnoreErrors(PyObject PyObject *PyCodec_ReplaceErrors(PyObject *exc) { Py_ssize_t start, end, i, len; + PyObject *cls = (PyObject *)exc->ob_type; + int rc; - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + if ((rc = PyObject_IsSubclass(cls, PyExc_UnicodeEncodeError))) { PyObject *res; int kind; void *data; + if (rc < 0) + return NULL; if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; if (PyUnicodeEncodeError_GetEnd(exc, &end)) @@ -732,17 +736,21 @@ PyObject *PyCodec_ReplaceErrors(PyObject assert(_PyUnicode_CheckConsistency(res, 1)); return Py_BuildValue("(Nn)", res, end); } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if ((rc = PyObject_IsSubclass(cls, PyExc_UnicodeDecodeError))) { + if (rc < 0) + return NULL; if (PyUnicodeDecodeError_GetEnd(exc, &end)) return NULL; return Py_BuildValue("(Cn)", (int)Py_UNICODE_REPLACEMENT_CHARACTER, end); } - else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) { + else if ((rc = PyObject_IsSubclass(cls, PyExc_UnicodeTranslateError))) { PyObject *res; int kind; void *data; + if (rc < 0) + return NULL; if (PyUnicodeTranslateError_GetStart(exc, &start)) return NULL; if (PyUnicodeTranslateError_GetEnd(exc, &end)) @@ -766,7 +774,10 @@ PyObject *PyCodec_ReplaceErrors(PyObject PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc) { - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + PyObject *cls = (PyObject *)exc->ob_type; + int rc; + + if ((rc = PyObject_IsSubclass(cls, PyExc_UnicodeEncodeError))) { PyObject *restuple; PyObject *object; Py_ssize_t i; @@ -776,6 +787,8 @@ PyObject *PyCodec_XMLCharRefReplaceError unsigned char *outp; Py_ssize_t ressize; Py_UCS4 ch; + if (rc < 0) + return NULL; if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; if (PyUnicodeEncodeError_GetEnd(exc, &end)) @@ -872,9 +885,13 @@ PyObject *PyCodec_BackslashReplaceErrors unsigned char *outp; int ressize; Py_UCS4 c; + PyObject *cls = (PyObject *)exc->ob_type; + int rc; - if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + if ((rc = PyObject_IsSubclass(cls, PyExc_UnicodeDecodeError))) { unsigned char *p; + if (rc < 0) + return NULL; if (PyUnicodeDecodeError_GetStart(exc, &start)) return NULL; if (PyUnicodeDecodeError_GetEnd(exc, &end)) @@ -903,7 +920,9 @@ PyObject *PyCodec_BackslashReplaceErrors Py_DECREF(object); return Py_BuildValue("(Nn)", res, end); } - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + if ((rc = PyObject_IsSubclass(cls, PyExc_UnicodeEncodeError))) { + if (rc < 0) + return NULL; if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; if (PyUnicodeEncodeError_GetEnd(exc, &end)) @@ -911,7 +930,9 @@ PyObject *PyCodec_BackslashReplaceErrors if (!(object = PyUnicodeEncodeError_GetObject(exc))) return NULL; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) { + else if ((rc = PyObject_IsSubclass(cls, PyExc_UnicodeTranslateError))) { + if (rc < 0) + return NULL; if (PyUnicodeTranslateError_GetStart(exc, &start)) return NULL; if (PyUnicodeTranslateError_GetEnd(exc, &end)) @@ -977,7 +998,10 @@ static int ucnhash_initialized = 0; PyObject *PyCodec_NameReplaceErrors(PyObject *exc) { - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + PyObject *cls = (PyObject *)exc->ob_type; + int rc; + + if ((rc = PyObject_IsSubclass(cls, PyExc_UnicodeEncodeError))) { PyObject *restuple; PyObject *object; Py_ssize_t i; @@ -989,6 +1013,8 @@ PyObject *PyCodec_NameReplaceErrors(PyOb int replsize; Py_UCS4 c; char buffer[256]; /* NAME_MAXLEN */ + if (rc < 0) + return NULL; if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; if (PyUnicodeEncodeError_GetEnd(exc, &end)) @@ -1150,8 +1176,13 @@ PyCodec_SurrogatePassErrors(PyObject *ex Py_ssize_t start; Py_ssize_t end; PyObject *res; - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + PyObject *cls = (PyObject *)exc->ob_type; + int rc; + + if ((rc = PyObject_IsSubclass(cls, PyExc_UnicodeEncodeError))) { unsigned char *outp; + if (rc < 0) + return NULL; if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; if (PyUnicodeEncodeError_GetEnd(exc, &end)) @@ -1227,9 +1258,11 @@ PyCodec_SurrogatePassErrors(PyObject *ex Py_DECREF(object); return restuple; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if ((rc = PyObject_IsSubclass(cls, PyExc_UnicodeDecodeError))) { unsigned char *p; Py_UCS4 ch = 0; + if (rc < 0) + return NULL; if (PyUnicodeDecodeError_GetStart(exc, &start)) return NULL; if (PyUnicodeDecodeError_GetEnd(exc, &end)) @@ -1312,8 +1345,13 @@ PyCodec_SurrogateEscapeErrors(PyObject * Py_ssize_t start; Py_ssize_t end; PyObject *res; - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + PyObject *cls = (PyObject *)exc->ob_type; + int rc; + + if ((rc = PyObject_IsSubclass(cls, PyExc_UnicodeEncodeError))) { char *outp; + if (rc < 0) + return NULL; if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; if (PyUnicodeEncodeError_GetEnd(exc, &end)) @@ -1343,11 +1381,13 @@ PyCodec_SurrogateEscapeErrors(PyObject * Py_DECREF(object); return restuple; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if ((rc = PyObject_IsSubclass(cls, PyExc_UnicodeDecodeError))) { PyObject *str; unsigned char *p; Py_UCS2 ch[4]; /* decode up to 4 bad bytes. */ int consumed = 0; + if (rc < 0) + return NULL; if (PyUnicodeDecodeError_GetStart(exc, &start)) return NULL; if (PyUnicodeDecodeError_GetEnd(exc, &end))