From a853e2f0760613dc513955ee46143f6d411d352f Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Thu, 30 Jan 2025 12:20:13 +0000 Subject: [PATCH] [3.13] gh-128799: Add frame of except* to traceback when wrapping a naked exception (#128971) (#129299) --- Lib/test/test_traceback.py | 27 +++++++++++++++++++ ...-01-18-01-06-58.gh-issue-128799.vSNagk.rst | 1 + Python/ceval.c | 12 +++++++++ 3 files changed, 40 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-01-18-01-06-58.gh-issue-128799.vSNagk.rst diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 2f543bccf566d5..f89fe8b26dc1bf 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -2938,6 +2938,33 @@ def exc(): report = self.get_report(exc) 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): # see GH-93249 def f(): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-18-01-06-58.gh-issue-128799.vSNagk.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-18-01-06-58.gh-issue-128799.vSNagk.rst new file mode 100644 index 00000000000000..eb2361bb5d4525 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-18-01-06-58.gh-issue-128799.vSNagk.rst @@ -0,0 +1 @@ +Add frame of ``except*`` to traceback when it wraps a naked exception. diff --git a/Python/ceval.c b/Python/ceval.c index 2f67d40874ba41..763c8688266f9d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -27,6 +27,7 @@ #include "pycore_setobject.h" // _PySet_Update() #include "pycore_sliceobject.h" // _PyBuildSlice_ConsumeRefs #include "pycore_sysmodule.h" // _PySys_Audit() +#include "pycore_traceback.h" // _PyTraceBack_FromFrame #include "pycore_tuple.h" // _PyTuple_ITEMS() #include "pycore_typeobject.h" // _PySuper_Lookup() #include "pycore_uop_ids.h" // Uops @@ -2018,6 +2019,17 @@ _PyEval_ExceptionGroupMatch(PyObject* exc_value, PyObject *match_type, if (wrapped == NULL) { 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; } *rest = Py_NewRef(Py_None);