diff -r 1c72e9c1b3b4 Lib/test/test_codeccallbacks.py --- a/Lib/test/test_codeccallbacks.py Sat May 02 09:47:28 2015 +0100 +++ b/Lib/test/test_codeccallbacks.py Sat May 02 14:43:04 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 1c72e9c1b3b4 Python/codecs.c --- a/Python/codecs.c Sat May 02 09:47:28 2015 +0100 +++ b/Python/codecs.c Sat May 02 14:43:04 2015 +0300 @@ -689,15 +689,16 @@ 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; + if (PyObject_IsSubclass(cls, PyExc_UnicodeEncodeError)) { if (PyUnicodeEncodeError_GetEnd(exc, &end)) return NULL; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if (PyObject_IsSubclass(cls, PyExc_UnicodeDecodeError)) { if (PyUnicodeDecodeError_GetEnd(exc, &end)) return NULL; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) { + else if (PyObject_IsSubclass(cls, PyExc_UnicodeTranslateError)) { if (PyUnicodeTranslateError_GetEnd(exc, &end)) return NULL; } @@ -712,8 +713,9 @@ PyObject *PyCodec_IgnoreErrors(PyObject PyObject *PyCodec_ReplaceErrors(PyObject *exc) { Py_ssize_t start, end, i, len; + PyObject *cls = (PyObject *)exc->ob_type; - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + if (PyObject_IsSubclass(cls, PyExc_UnicodeEncodeError)) { PyObject *res; int kind; void *data; @@ -732,14 +734,14 @@ PyObject *PyCodec_ReplaceErrors(PyObject assert(_PyUnicode_CheckConsistency(res, 1)); return Py_BuildValue("(Nn)", res, end); } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if (PyObject_IsSubclass(cls, PyExc_UnicodeDecodeError)) { 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 (PyObject_IsSubclass(cls, PyExc_UnicodeTranslateError)) { PyObject *res; int kind; void *data; @@ -766,7 +768,8 @@ PyObject *PyCodec_ReplaceErrors(PyObject PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc) { - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + PyObject *cls = (PyObject *)exc->ob_type; + if (PyObject_IsSubclass(cls, PyExc_UnicodeEncodeError)) { PyObject *restuple; PyObject *object; Py_ssize_t i; @@ -872,8 +875,9 @@ PyObject *PyCodec_BackslashReplaceErrors unsigned char *outp; int ressize; Py_UCS4 c; + PyObject *cls = (PyObject *)exc->ob_type; - if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + if (PyObject_IsSubclass(cls, PyExc_UnicodeDecodeError)) { unsigned char *p; if (PyUnicodeDecodeError_GetStart(exc, &start)) return NULL; @@ -903,7 +907,7 @@ PyObject *PyCodec_BackslashReplaceErrors Py_DECREF(object); return Py_BuildValue("(Nn)", res, end); } - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + if (PyObject_IsSubclass(cls, PyExc_UnicodeEncodeError)) { if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; if (PyUnicodeEncodeError_GetEnd(exc, &end)) @@ -911,7 +915,7 @@ PyObject *PyCodec_BackslashReplaceErrors if (!(object = PyUnicodeEncodeError_GetObject(exc))) return NULL; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) { + else if (PyObject_IsSubclass(cls, PyExc_UnicodeTranslateError)) { if (PyUnicodeTranslateError_GetStart(exc, &start)) return NULL; if (PyUnicodeTranslateError_GetEnd(exc, &end)) @@ -977,7 +981,8 @@ static int ucnhash_initialized = 0; PyObject *PyCodec_NameReplaceErrors(PyObject *exc) { - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { + PyObject *cls = (PyObject *)exc->ob_type; + if (PyObject_IsSubclass(cls, PyExc_UnicodeEncodeError)) { PyObject *restuple; PyObject *object; Py_ssize_t i; @@ -1150,7 +1155,8 @@ 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; + if (PyObject_IsSubclass(cls, PyExc_UnicodeEncodeError)) { unsigned char *outp; if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; @@ -1227,7 +1233,7 @@ PyCodec_SurrogatePassErrors(PyObject *ex Py_DECREF(object); return restuple; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if (PyObject_IsSubclass(cls, PyExc_UnicodeDecodeError)) { unsigned char *p; Py_UCS4 ch = 0; if (PyUnicodeDecodeError_GetStart(exc, &start)) @@ -1312,7 +1318,8 @@ 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; + if (PyObject_IsSubclass(cls, PyExc_UnicodeEncodeError)) { char *outp; if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; @@ -1343,7 +1350,7 @@ PyCodec_SurrogateEscapeErrors(PyObject * Py_DECREF(object); return restuple; } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + else if (PyObject_IsSubclass(cls, PyExc_UnicodeDecodeError)) { PyObject *str; unsigned char *p; Py_UCS2 ch[4]; /* decode up to 4 bad bytes. */