This function is safe to call before :c:func:`Py_Initialize`. When called
after runtime initialization, existing audit hooks are notified and may
silently abort the operation by raising an error subclassed from
- :class:`Exception` (other errors will not be silenced).
+ :class:`RuntimeError` (other errors will not be silenced).
The hook function is always called with an :term:`attached thread state` by
the Python interpreter that raised the event.
If the interpreter is initialized, this function raises an auditing event
``sys.addaudithook`` with no arguments. If any existing hooks raise an
- exception derived from :class:`Exception`, the new hook will not be
+ exception derived from :class:`RuntimeError`, the new hook will not be
added and the exception is cleared. As a result, callers cannot assume
that their hook has been added unless they control all existing hooks.
.. versionadded:: 3.8
+ .. versionchanged:: 3.8.1
+
+ Exceptions derived from :class:`Exception` but not :class:`RuntimeError`
+ are no longer suppressed.
+
.. _processcontrol:
pass
+def test_block_add_hook_valueerror():
+ # Non-RuntimeError exceptions (like ValueError) should propagate out
+ with assertRaises(ValueError):
+ with TestHook(
+ raise_on_events="sys.addaudithook", exc_type=ValueError
+ ) as hook1:
+ with TestHook() as hook2:
+ pass
+
+
def test_marshal():
import marshal
o = ("a", "b", "c", 1, 2, 3)
def test_block_add_hook_baseexception(self):
self.do_test("test_block_add_hook_baseexception")
+ def test_block_add_hook_valueerror(self):
+ self.do_test("test_block_add_hook_valueerror")
+
def test_marshal(self):
import_helper.import_module("marshal")
--- /dev/null
+``sys.addaudithook()`` now correctly suppresses only :exc:`RuntimeError` instead of all :exc:`Exception` subclasses when an existing audit hook raises during hook registration. Patch by Yeongu Kim.
/* Invoke existing audit hooks to allow them an opportunity to abort. */
if (_PySys_Audit(tstate, "sys.addaudithook", NULL) < 0) {
- if (_PyErr_ExceptionMatches(tstate, PyExc_Exception)) {
- /* We do not report errors derived from Exception */
+ if (_PyErr_ExceptionMatches(tstate, PyExc_RuntimeError)) {
+ /* We do not report errors derived from RuntimeError */
_PyErr_Clear(tstate);
Py_RETURN_NONE;
}