gh-105071: add PyUnstable_Exc_PrepReraiseStar to expose except* imple… · wrongnull/cpython@b7aadb4 · GitHub
Skip to content

Commit b7aadb4

Browse files
authored
pythongh-105071: add PyUnstable_Exc_PrepReraiseStar to expose except* implementation in the unstable API (python#105072)
1 parent bd98b65 commit b7aadb4

7 files changed

Lines changed: 196 additions & 1 deletion

File tree

Doc/c-api/exceptions.rst

Lines changed: 10 additions & 0 deletions

Include/cpython/pyerrors.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ PyAPI_FUNC(int) _PyException_AddNote(
116116
PyObject *exc,
117117
PyObject *note);
118118

119+
PyAPI_FUNC(PyObject*) PyUnstable_Exc_PrepReraiseStar(
120+
PyObject *orig,
121+
PyObject *excs);
122+
119123
/* In signalmodule.c */
120124

121125
int PySignal_SetWakeupFd(int fd);

Lib/test/test_capi/test_exceptions.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from test import support
66
from test.support import import_helper
77
from test.support.script_helper import assert_python_failure
8+
from test.support.testcase import ExceptionIsLikeMixin
89

910
from .test_misc import decode_stderr
1011

@@ -189,5 +190,97 @@ def __repr__(self):
189190
'Normalization failed: type=Broken args=<unknown>')
190191

191192

193+
class Test_PyUnstable_Exc_PrepReraiseStar(ExceptionIsLikeMixin, unittest.TestCase):
194+
195+
def setUp(self):
196+
super().setUp()
197+
try:
198+
raise ExceptionGroup("eg", [TypeError('bad type'), ValueError(42)])
199+
except ExceptionGroup as e:
200+
self.orig = e
201+
202+
def test_invalid_args(self):
203+
with self.assertRaisesRegex(TypeError, "orig must be an exception"):
204+
_testcapi.unstable_exc_prep_reraise_star(42, [None])
205+
206+
with self.assertRaisesRegex(TypeError, "excs must be a list"):
207+
_testcapi.unstable_exc_prep_reraise_star(self.orig, 42)
208+
209+
with self.assertRaisesRegex(TypeError, "not an exception"):
210+
_testcapi.unstable_exc_prep_reraise_star(self.orig, [TypeError(42), 42])
211+
212+
with self.assertRaisesRegex(ValueError, "orig must be a raised exception"):
213+
_testcapi.unstable_exc_prep_reraise_star(ValueError(42), [TypeError(42)])
214+
215+
with self.assertRaisesRegex(ValueError, "orig must be a raised exception"):
216+
_testcapi.unstable_exc_prep_reraise_star(ExceptionGroup("eg", [ValueError(42)]),
217+
[TypeError(42)])
218+
219+
220+
def test_nothing_to_reraise(self):
221+
self.assertEqual(
222+
_testcapi.unstable_exc_prep_reraise_star(self.orig, [None]), None)
223+
224+
try:
225+
raise ValueError(42)
226+
except ValueError as e:
227+
orig = e
228+
self.assertEqual(
229+
_testcapi.unstable_exc_prep_reraise_star(orig, [None]), None)
230+
231+
def test_reraise_orig(self):
232+
orig = self.orig
233+
res = _testcapi.unstable_exc_prep_reraise_star(orig, [orig])
234+
self.assertExceptionIsLike(res, orig)
235+
236+
def test_raise_orig_parts(self):
237+
orig = self.orig
238+
match, rest = orig.split(TypeError)
239+
240+
test_cases = [
241+
([match, rest], orig),
242+
([rest, match], orig),
243+
([match], match),
244+
([rest], rest),
245+
([], None),
246+
]
247+
248+
for input, expected in test_cases:
249+
with self.subTest(input=input):
250+
res = _testcapi.unstable_exc_prep_reraise_star(orig, input)
251+
self.assertExceptionIsLike(res, expected)
252+
253+
254+
def test_raise_with_new_exceptions(self):
255+
orig = self.orig
256+
257+
match, rest = orig.split(TypeError)
258+
new1 = OSError('bad file')
259+
new2 = RuntimeError('bad runtime')
260+
261+
test_cases = [
262+
([new1, match, rest], ExceptionGroup("", [new1, orig])),
263+
([match, new1, rest], ExceptionGroup("", [new1, orig])),
264+
([match, rest, new1], ExceptionGroup("", [new1, orig])),
265+
266+
([new1, new2, match, rest], ExceptionGroup("", [new1, new2, orig])),
267+
([new1, match, new2, rest], ExceptionGroup("", [new1, new2, orig])),
268+
([new2, rest, match, new1], ExceptionGroup("", [new2, new1, orig])),
269+
([rest, new2, match, new1], ExceptionGroup("", [new2, new1, orig])),
270+
271+
272+
([new1, new2, rest], ExceptionGroup("", [new1, new2, rest])),
273+
([new1, match, new2], ExceptionGroup("", [new1, new2, match])),
274+
([rest, new2, new1], ExceptionGroup("", [new2, new1, rest])),
275+
([new1, new2], ExceptionGroup("", [new1, new2])),
276+
([new2, new1], ExceptionGroup("", [new2, new1])),
277+
]
278+
279+
for (input, expected) in test_cases:
280+
with self.subTest(input=input):
281+
res = _testcapi.unstable_exc_prep_reraise_star(orig, input)
282+
self.assertExceptionIsLike(res, expected)
283+
284+
192285
if __name__ == "__main__":
193286
unittest.main()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add ``PyUnstable_Exc_PrepReraiseStar`` to the unstable C api to expose the implementation of :keyword:`except* <except_star>`.

Modules/_testcapi/clinic/exceptions.c.h

Lines changed: 32 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/_testcapi/exceptions.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,22 @@ _testcapi_traceback_print_impl(PyObject *module, PyObject *traceback,
288288
Py_RETURN_NONE;
289289
}
290290

291+
/*[clinic input]
292+
_testcapi.unstable_exc_prep_reraise_star
293+
orig: object
294+
excs: object
295+
/
296+
To test PyUnstable_Exc_PrepReraiseStar.
297+
[clinic start generated code]*/
298+
299+
static PyObject *
300+
_testcapi_unstable_exc_prep_reraise_star_impl(PyObject *module,
301+
PyObject *orig, PyObject *excs)
302+
/*[clinic end generated code: output=850cf008e0563c77 input=27fbcda2203eb301]*/
303+
{
304+
return PyUnstable_Exc_PrepReraiseStar(orig, excs);
305+
}
306+
291307

292308
/*
293309
* Define the PyRecurdingInfinitelyError_Type
@@ -328,6 +344,7 @@ static PyMethodDef test_methods[] = {
328344
_TESTCAPI_SET_EXCEPTION_METHODDEF
329345
_TESTCAPI_TRACEBACK_PRINT_METHODDEF
330346
_TESTCAPI_WRITE_UNRAISABLE_EXC_METHODDEF
347+
_TESTCAPI_UNSTABLE_EXC_PREP_RERAISE_STAR_METHODDEF
331348
{NULL},
332349
};
333350

Objects/exceptions.c

Lines changed: 39 additions & 0 deletions

0 commit comments

Comments
 (0)