From c892ee438d10385fd9cf73eddfa70a5de1f1e7b2 Mon Sep 17 00:00:00 2001 From: Sachin Saharan Date: Fri, 22 Nov 2024 16:46:04 +0530 Subject: [PATCH] Set sys.last_value / sys.last_exc before entering the debugger **Background:** In commit 6eae532, we introduced a new utility in pyflyby named `saveframe`. This utility is designed to save error stack frames upon an exception. Users can also enter a debugger after an exception (using ipdb.pm()) and call `saveframe` to dump a specific frame. `saveframe` relies on `sys.last_value` (or `sys.last_exc` in Python 3.12) to retrieve the last exception object raised. These attributes are automatically set by Python after an uncaught exception occurs. **Issue:** When a user executes a script or command using `py ` or employs the `@debug_on_exception` decorator, the exception is caught, and the debugger is invoked. Consequently, `sys.last_value` (or `sys.last_exc`) is not set. If the user attempts to call `saveframe` within the debugger, it fails because the necessary exception information is unavailable. **Solution:** In this commit, we modified the code to explicitly set `sys.last_value` (or `sys.last_exc`) after an exception is caught and before entering the debugger. This ensures that users can directly enter the debugger and successfully call the `pyflyby.saveframe` function. Request: PyInf#12047 --- lib/python/pyflyby/_dbg.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/python/pyflyby/_dbg.py b/lib/python/pyflyby/_dbg.py index e1214680..10b84b7c 100644 --- a/lib/python/pyflyby/_dbg.py +++ b/lib/python/pyflyby/_dbg.py @@ -316,6 +316,14 @@ def _debug_exception(*exc_info, **kwargs): # will cause print_verbose_tb to include a line with just a colon. # TODO: avoid that line. exc_info = ("", "", exc_info) + if exc_info[1]: + # Explicitly set sys.last_value / sys.last_exc to ensure they are available + # in the debugger. One use case is that this allows users to call + # pyflyby.saveframe() within the debugger. + if sys.version_info < (3, 12): + sys.last_value = exc_info[1] + else: + sys.last_exc = exc_info[1] with _DebuggerCtx(tty=tty) as pdb: if debugger_attached: