from test import support
from test.support import import_helper
from test.support.script_helper import assert_python_failure
+from test.support.testcase import ExceptionIsLikeMixin
from .test_misc import decode_stderr
'Normalization failed: type=Broken args=<unknown>')
+class Test_PyUnstable_Exc_PrepReraiseStar(ExceptionIsLikeMixin, unittest.TestCase):
+
+ def setUp(self):
+ super().setUp()
+ try:
+ raise ExceptionGroup("eg", [TypeError('bad type'), ValueError(42)])
+ except ExceptionGroup as e:
+ self.orig = e
+
+ def test_invalid_args(self):
+ with self.assertRaisesRegex(TypeError, "orig must be an exception"):
+ _testcapi.unstable_exc_prep_reraise_star(42, [None])
+
+ with self.assertRaisesRegex(TypeError, "excs must be a list"):
+ _testcapi.unstable_exc_prep_reraise_star(self.orig, 42)
+
+ with self.assertRaisesRegex(TypeError, "not an exception"):
+ _testcapi.unstable_exc_prep_reraise_star(self.orig, [TypeError(42), 42])
+
+ with self.assertRaisesRegex(ValueError, "orig must be a raised exception"):
+ _testcapi.unstable_exc_prep_reraise_star(ValueError(42), [TypeError(42)])
+
+ with self.assertRaisesRegex(ValueError, "orig must be a raised exception"):
+ _testcapi.unstable_exc_prep_reraise_star(ExceptionGroup("eg", [ValueError(42)]),
+ [TypeError(42)])
+
+
+ def test_nothing_to_reraise(self):
+ self.assertEqual(
+ _testcapi.unstable_exc_prep_reraise_star(self.orig, [None]), None)
+
+ try:
+ raise ValueError(42)
+ except ValueError as e:
+ orig = e
+ self.assertEqual(
+ _testcapi.unstable_exc_prep_reraise_star(orig, [None]), None)
+
+ def test_reraise_orig(self):
+ orig = self.orig
+ res = _testcapi.unstable_exc_prep_reraise_star(orig, [orig])
+ self.assertExceptionIsLike(res, orig)
+
+ def test_raise_orig_parts(self):
+ orig = self.orig
+ match, rest = orig.split(TypeError)
+
+ test_cases = [
+ ([match, rest], orig),
+ ([rest, match], orig),
+ ([match], match),
+ ([rest], rest),
+ ([], None),
+ ]
+
+ for input, expected in test_cases:
+ with self.subTest(input=input):
+ res = _testcapi.unstable_exc_prep_reraise_star(orig, input)
+ self.assertExceptionIsLike(res, expected)
+
+
+ def test_raise_with_new_exceptions(self):
+ orig = self.orig
+
+ match, rest = orig.split(TypeError)
+ new1 = OSError('bad file')
+ new2 = RuntimeError('bad runtime')
+
+ test_cases = [
+ ([new1, match, rest], ExceptionGroup("", [new1, orig])),
+ ([match, new1, rest], ExceptionGroup("", [new1, orig])),
+ ([match, rest, new1], ExceptionGroup("", [new1, orig])),
+
+ ([new1, new2, match, rest], ExceptionGroup("", [new1, new2, orig])),
+ ([new1, match, new2, rest], ExceptionGroup("", [new1, new2, orig])),
+ ([new2, rest, match, new1], ExceptionGroup("", [new2, new1, orig])),
+ ([rest, new2, match, new1], ExceptionGroup("", [new2, new1, orig])),
+
+
+ ([new1, new2, rest], ExceptionGroup("", [new1, new2, rest])),
+ ([new1, match, new2], ExceptionGroup("", [new1, new2, match])),
+ ([rest, new2, new1], ExceptionGroup("", [new2, new1, rest])),
+ ([new1, new2], ExceptionGroup("", [new1, new2])),
+ ([new2, new1], ExceptionGroup("", [new2, new1])),
+ ]
+
+ for (input, expected) in test_cases:
+ with self.subTest(input=input):
+ res = _testcapi.unstable_exc_prep_reraise_star(orig, input)
+ self.assertExceptionIsLike(res, expected)
+
+
if __name__ == "__main__":
unittest.main()
exit:
return return_value;
}
-/*[clinic end generated code: output=ec1b2e62adea9846 input=a9049054013a1b77]*/
+
+PyDoc_STRVAR(_testcapi_unstable_exc_prep_reraise_star__doc__,
+"unstable_exc_prep_reraise_star($module, orig, excs, /)\n"
+"--\n"
+"\n"
+"To test PyUnstable_Exc_PrepReraiseStar.");
+
+#define _TESTCAPI_UNSTABLE_EXC_PREP_RERAISE_STAR_METHODDEF \
+ {"unstable_exc_prep_reraise_star", _PyCFunction_CAST(_testcapi_unstable_exc_prep_reraise_star), METH_FASTCALL, _testcapi_unstable_exc_prep_reraise_star__doc__},
+
+static PyObject *
+_testcapi_unstable_exc_prep_reraise_star_impl(PyObject *module,
+ PyObject *orig, PyObject *excs);
+
+static PyObject *
+_testcapi_unstable_exc_prep_reraise_star(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *orig;
+ PyObject *excs;
+
+ if (!_PyArg_CheckPositional("unstable_exc_prep_reraise_star", nargs, 2, 2)) {
+ goto exit;
+ }
+ orig = args[0];
+ excs = args[1];
+ return_value = _testcapi_unstable_exc_prep_reraise_star_impl(module, orig, excs);
+
+exit:
+ return return_value;
+}
+/*[clinic end generated code: output=fd6aef54f195c77b input=a9049054013a1b77]*/
PyObject *
_PyExc_PrepReraiseStar(PyObject *orig, PyObject *excs)
{
+ /* orig must be a raised & caught exception, so it has a traceback */
assert(PyExceptionInstance_Check(orig));
+ assert(_PyBaseExceptionObject_cast(orig)->traceback != NULL);
+
assert(PyList_Check(excs));
Py_ssize_t numexcs = PyList_GET_SIZE(excs);
return result;
}
+PyObject *
+PyUnstable_Exc_PrepReraiseStar(PyObject *orig, PyObject *excs)
+{
+ if (orig == NULL || !PyExceptionInstance_Check(orig)) {
+ PyErr_SetString(PyExc_TypeError, "orig must be an exception instance");
+ return NULL;
+ }
+ if (excs == NULL || !PyList_Check(excs)) {
+ PyErr_SetString(PyExc_TypeError,
+ "excs must be a list of exception instances");
+ return NULL;
+ }
+ Py_ssize_t numexcs = PyList_GET_SIZE(excs);
+ for (Py_ssize_t i = 0; i < numexcs; i++) {
+ PyObject *exc = PyList_GET_ITEM(excs, i);
+ if (exc == NULL || !(PyExceptionInstance_Check(exc) || Py_IsNone(exc))) {
+ PyErr_Format(PyExc_TypeError,
+ "item %d of excs is not an exception", i);
+ return NULL;
+ }
+ }
+
+ /* Make sure that orig has something as traceback, in the interpreter
+ * it always does becuase it's a raised exception.
+ */
+ PyObject *tb = PyException_GetTraceback(orig);
+
+ if (tb == NULL) {
+ PyErr_Format(PyExc_ValueError, "orig must be a raised exception");
+ return NULL;
+ }
+ Py_DECREF(tb);
+
+ return _PyExc_PrepReraiseStar(orig, excs);
+}
+
static PyMemberDef BaseExceptionGroup_members[] = {
{"message", T_OBJECT, offsetof(PyBaseExceptionGroupObject, msg), READONLY,
PyDoc_STR("exception message")},