diff --git a/Lib/test/test_capi/test_exceptions.py b/Lib/test/test_capi/test_exceptions.py index 55f131699a2567..06d12b70ae1a12 100644 --- a/Lib/test/test_capi/test_exceptions.py +++ b/Lib/test/test_capi/test_exceptions.py @@ -169,5 +169,14 @@ class Broken(Exception, metaclass=Meta): with self.assertRaises(ZeroDivisionError) as e: _testcapi.exc_set_object(Broken, Broken()) + def test_fetch_exception_with_broken_init(self): + + class FlakyException(Exception): + def __init__(self): + raise ValueError("Broken __init__") + + fetched_type_name = _testcapi.exc_set_object_fetch(FlakyException, ()) + self.assertEqual(fetched_type_name, 'FlakyException') + if __name__ == "__main__": unittest.main() diff --git a/Modules/_testcapi/exceptions.c b/Modules/_testcapi/exceptions.c index a0575213987ffc..ad87a4e9236d35 100644 --- a/Modules/_testcapi/exceptions.c +++ b/Modules/_testcapi/exceptions.c @@ -92,6 +92,35 @@ exc_set_object(PyObject *self, PyObject *args) return NULL; } +static PyObject * +exc_set_object_fetch(PyObject *self, PyObject *args) +{ + PyObject *exc; + PyObject *obj; + PyObject *type; + PyObject *value; + PyObject *tb; + + if (!PyArg_ParseTuple(args, "OO:exc_set_object", &exc, &obj)) { + return NULL; + } + + PyErr_SetObject(exc, obj); + PyErr_Fetch(&type, &value, &tb); + Py_XDECREF(value); + Py_XDECREF(tb); + if (!PyType_Check(type)) { + Py_XDECREF(type); + PyErr_SetString(PyExc_RuntimeError, + "PyErr_Fetch() produced invalid type"); + return NULL; + } + PyObject *fetched_type_name = PyUnicode_FromString( + ((PyTypeObject *) type)->tp_name); + Py_XDECREF(type); + return fetched_type_name; +} + static PyObject * raise_exception(PyObject *self, PyObject *args) { @@ -262,6 +291,7 @@ static PyMethodDef test_methods[] = { {"make_exception_with_doc", _PyCFunction_CAST(make_exception_with_doc), METH_VARARGS | METH_KEYWORDS}, {"exc_set_object", exc_set_object, METH_VARARGS}, + {"exc_set_object_fetch", exc_set_object_fetch, METH_VARARGS}, {"raise_exception", raise_exception, METH_VARARGS}, {"raise_memoryerror", raise_memoryerror, METH_NOARGS}, {"set_exc_info", test_set_exc_info, METH_VARARGS},