gh-103176: sys._current_exceptions() returns mapping to exception instances instead of exc_info tuples (#103177)

This commit is contained in:
Irit Katriel 2023-04-11 09:38:37 +01:00 committed by GitHub
parent 8026cda10c
commit 78b763f630
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 23 additions and 10 deletions

View file

@ -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,

View file

@ -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
=============

View file

@ -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

View file

@ -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.

View file

@ -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;
}