diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 65a3a8a48a8809..730bac5f59c098 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -360,10 +360,20 @@ def test_capi3(): self.assertRaises(SystemError, _testcapi.raise_exception, InvalidException, 1) + def test_capi4(): + import _testcapi + 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 not sys.platform.startswith('java'): test_capi1() test_capi2() test_capi3() + test_capi4() def test_WindowsError(self): try: diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 3617fafe9b4fdd..fd4e3bcb3fd088 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -716,6 +716,35 @@ pyobject_bytes_from_null(PyObject *self, PyObject *Py_UNUSED(ignored)) return PyObject_Bytes(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) { @@ -3141,6 +3170,7 @@ function_set_kw_defaults(PyObject *self, PyObject *args) static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *); static PyMethodDef TestMethods[] = { + {"exc_set_object_fetch", exc_set_object_fetch, METH_VARARGS}, {"raise_exception", raise_exception, METH_VARARGS}, {"raise_memoryerror", raise_memoryerror, METH_NOARGS}, {"set_errno", set_errno, METH_VARARGS},