[3.13] gh-128799: Add frame of except* to traceback when wrapping a naked exception (#128971) (#129299)

This commit is contained in:
Irit Katriel 2025-01-30 12:20:13 +00:00 committed by GitHub
parent fcb265671c
commit a853e2f076
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 40 additions and 0 deletions

View file

@ -2938,6 +2938,33 @@ def exc():
report = self.get_report(exc) report = self.get_report(exc)
self.assertEqual(report, expected) self.assertEqual(report, expected)
def test_exception_group_wrapped_naked(self):
# See gh-128799
def exc():
try:
raise Exception(42)
except* Exception as e:
raise
expected = (f' + Exception Group Traceback (most recent call last):\n'
f' | File "{__file__}", line {self.callable_line}, in get_exception\n'
f' | exception_or_callable()\n'
f' | ~~~~~~~~~~~~~~~~~~~~~^^\n'
f' | File "{__file__}", line {exc.__code__.co_firstlineno + 3}, in exc\n'
f' | except* Exception as e:\n'
f' | raise\n'
f' | ExceptionGroup: (1 sub-exception)\n'
f' +-+---------------- 1 ----------------\n'
f' | Traceback (most recent call last):\n'
f' | File "{__file__}", line {exc.__code__.co_firstlineno + 2}, in exc\n'
f' | raise Exception(42)\n'
f' | Exception: 42\n'
f' +------------------------------------\n')
report = self.get_report(exc)
self.assertEqual(report, expected)
def test_KeyboardInterrupt_at_first_line_of_frame(self): def test_KeyboardInterrupt_at_first_line_of_frame(self):
# see GH-93249 # see GH-93249
def f(): def f():

View file

@ -0,0 +1 @@
Add frame of ``except*`` to traceback when it wraps a naked exception.

View file

@ -27,6 +27,7 @@
#include "pycore_setobject.h" // _PySet_Update() #include "pycore_setobject.h" // _PySet_Update()
#include "pycore_sliceobject.h" // _PyBuildSlice_ConsumeRefs #include "pycore_sliceobject.h" // _PyBuildSlice_ConsumeRefs
#include "pycore_sysmodule.h" // _PySys_Audit() #include "pycore_sysmodule.h" // _PySys_Audit()
#include "pycore_traceback.h" // _PyTraceBack_FromFrame
#include "pycore_tuple.h" // _PyTuple_ITEMS() #include "pycore_tuple.h" // _PyTuple_ITEMS()
#include "pycore_typeobject.h" // _PySuper_Lookup() #include "pycore_typeobject.h" // _PySuper_Lookup()
#include "pycore_uop_ids.h" // Uops #include "pycore_uop_ids.h" // Uops
@ -2018,6 +2019,17 @@ _PyEval_ExceptionGroupMatch(PyObject* exc_value, PyObject *match_type,
if (wrapped == NULL) { if (wrapped == NULL) {
return -1; return -1;
} }
PyThreadState *tstate = _PyThreadState_GET();
_PyInterpreterFrame *frame = _PyThreadState_GetFrame(tstate);
PyFrameObject *f = _PyFrame_GetFrameObject(frame);
if (f != NULL) {
PyObject *tb = _PyTraceBack_FromFrame(NULL, f);
if (tb == NULL) {
return -1;
}
PyException_SetTraceback(wrapped, tb);
Py_DECREF(tb);
}
*match = wrapped; *match = wrapped;
} }
*rest = Py_NewRef(Py_None); *rest = Py_NewRef(Py_None);