From 78b763f63032a7185c0905c319ead9e9b35787b6 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Tue, 11 Apr 2023 09:38:37 +0100 Subject: gh-103176: sys._current_exceptions() returns mapping to exception instances instead of exc_info tuples (#103177) --- Doc/library/sys.rst | 4 ++++ Doc/whatsnew/3.12.rst | 8 ++++++++ Lib/test/test_sys.py | 6 +++--- .../Library/2023-04-01-23-01-31.gh-issue-103176.FBsdxa.rst | 2 ++ Python/pystate.c | 13 ++++++------- 5 files changed, 23 insertions(+), 10 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-04-01-23-01-31.gh-issue-103176.FBsdxa.rst diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 00721ef..e37d57e 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -220,6 +220,10 @@ always available. .. audit-event:: sys._current_exceptions "" sys._current_exceptions + .. versionchanged:: 3.12 + Each value in the dictionary is now a single exception instance, rather + than a 3-tuple as returned from ``sys.exc_info()``. + .. function:: breakpointhook() This hook function is called by built-in :func:`breakpoint`. By default, diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 651caed..0eb1636 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -499,6 +499,10 @@ sys :data:`sys.last_type`, :data:`sys.last_value` and :data:`sys.last_traceback`. (Contributed by Irit Katriel in :gh:`102778`.) +* :func:`sys._current_exceptions` now returns a mapping from thread-id to an + exception instance, rather than to a ``(typ, exc, tb)`` tuple. + (Contributed by Irit Katriel in :gh:`103176`.) + Optimizations ============= @@ -940,6 +944,10 @@ Changes in the Python API synchronization is needed, implement locking within the cached property getter function or around multi-threaded access points. +* :func:`sys._current_exceptions` now returns a mapping from thread-id to an + exception instance, rather than to a ``(typ, exc, tb)`` tuple. + (Contributed by Irit Katriel in :gh:`103176`.) + Build Changes ============= diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index d7456d6..890ffbf 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -532,13 +532,13 @@ class SysModuleTest(unittest.TestCase): main_id = threading.get_ident() self.assertIn(main_id, d) self.assertIn(thread_id, d) - self.assertEqual((None, None, None), d.pop(main_id)) + self.assertEqual(None, d.pop(main_id)) # Verify that the captured thread frame is blocked in g456, called # from f123. This is a little tricky, since various bits of # threading.py are also in the thread's call stack. - exc_type, exc_value, exc_tb = d.pop(thread_id) - stack = traceback.extract_stack(exc_tb.tb_frame) + exc_value = d.pop(thread_id) + stack = traceback.extract_stack(exc_value.__traceback__.tb_frame) for i, (filename, lineno, funcname, sourceline) in enumerate(stack): if funcname == "f123": break diff --git a/Misc/NEWS.d/next/Library/2023-04-01-23-01-31.gh-issue-103176.FBsdxa.rst b/Misc/NEWS.d/next/Library/2023-04-01-23-01-31.gh-issue-103176.FBsdxa.rst new file mode 100644 index 0000000..b89f9ba --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-04-01-23-01-31.gh-issue-103176.FBsdxa.rst @@ -0,0 +1,2 @@ +:func:`sys._current_exceptions` now returns a mapping from thread-id to an +exception instance, rather than to a ``(typ, exc, tb)`` tuple. diff --git a/Python/pystate.c b/Python/pystate.c index d09c1d5..37cef97 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1986,14 +1986,13 @@ _PyThread_CurrentExceptions(void) if (id == NULL) { goto fail; } - PyObject *exc_info = _PyErr_StackItemToExcInfoTuple(err_info); - if (exc_info == NULL) { - Py_DECREF(id); - goto fail; - } - int stat = PyDict_SetItem(result, id, exc_info); + PyObject *exc = err_info->exc_value; + assert(exc == NULL || + exc == Py_None || + PyExceptionInstance_Check(exc)); + + int stat = PyDict_SetItem(result, id, exc == NULL ? Py_None : exc); Py_DECREF(id); - Py_DECREF(exc_info); if (stat < 0) { goto fail; } -- cgit v0.12