Skip to content

Commit a853e2f

Browse files
authored
[3.13] gh-128799: Add frame of except* to traceback when wrapping a naked exception (#128971) (#129299)
1 parent fcb2656 commit a853e2f

File tree

3 files changed

+40
-0
lines changed

3 files changed

+40
-0
lines changed

Lib/test/test_traceback.py

+27
Original file line numberDiff line numberDiff line change
@@ -2938,6 +2938,33 @@ def exc():
29382938
report = self.get_report(exc)
29392939
self.assertEqual(report, expected)
29402940

2941+
def test_exception_group_wrapped_naked(self):
2942+
# See gh-128799
2943+
2944+
def exc():
2945+
try:
2946+
raise Exception(42)
2947+
except* Exception as e:
2948+
raise
2949+
2950+
expected = (f' + Exception Group Traceback (most recent call last):\n'
2951+
f' | File "{__file__}", line {self.callable_line}, in get_exception\n'
2952+
f' | exception_or_callable()\n'
2953+
f' | ~~~~~~~~~~~~~~~~~~~~~^^\n'
2954+
f' | File "{__file__}", line {exc.__code__.co_firstlineno + 3}, in exc\n'
2955+
f' | except* Exception as e:\n'
2956+
f' | raise\n'
2957+
f' | ExceptionGroup: (1 sub-exception)\n'
2958+
f' +-+---------------- 1 ----------------\n'
2959+
f' | Traceback (most recent call last):\n'
2960+
f' | File "{__file__}", line {exc.__code__.co_firstlineno + 2}, in exc\n'
2961+
f' | raise Exception(42)\n'
2962+
f' | Exception: 42\n'
2963+
f' +------------------------------------\n')
2964+
2965+
report = self.get_report(exc)
2966+
self.assertEqual(report, expected)
2967+
29412968
def test_KeyboardInterrupt_at_first_line_of_frame(self):
29422969
# see GH-93249
29432970
def f():
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add frame of ``except*`` to traceback when it wraps a naked exception.

Python/ceval.c

+12
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "pycore_setobject.h" // _PySet_Update()
2828
#include "pycore_sliceobject.h" // _PyBuildSlice_ConsumeRefs
2929
#include "pycore_sysmodule.h" // _PySys_Audit()
30+
#include "pycore_traceback.h" // _PyTraceBack_FromFrame
3031
#include "pycore_tuple.h" // _PyTuple_ITEMS()
3132
#include "pycore_typeobject.h" // _PySuper_Lookup()
3233
#include "pycore_uop_ids.h" // Uops
@@ -2018,6 +2019,17 @@ _PyEval_ExceptionGroupMatch(PyObject* exc_value, PyObject *match_type,
20182019
if (wrapped == NULL) {
20192020
return -1;
20202021
}
2022+
PyThreadState *tstate = _PyThreadState_GET();
2023+
_PyInterpreterFrame *frame = _PyThreadState_GetFrame(tstate);
2024+
PyFrameObject *f = _PyFrame_GetFrameObject(frame);
2025+
if (f != NULL) {
2026+
PyObject *tb = _PyTraceBack_FromFrame(NULL, f);
2027+
if (tb == NULL) {
2028+
return -1;
2029+
}
2030+
PyException_SetTraceback(wrapped, tb);
2031+
Py_DECREF(tb);
2032+
}
20212033
*match = wrapped;
20222034
}
20232035
*rest = Py_NewRef(Py_None);

0 commit comments

Comments
 (0)