Skip to content

Commit

Permalink
gh-103791: handle BaseExceptionGroup in contextlib.suppress() (#1…
Browse files Browse the repository at this point in the history
  • Loading branch information
Zac-HD authored Nov 10, 2023
1 parent 64fea32 commit d61313b
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 4 deletions.
6 changes: 3 additions & 3 deletions Doc/library/contextlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -304,15 +304,15 @@ Functions and classes provided:

This context manager is :ref:`reentrant <reentrant-cms>`.

If the code within the :keyword:`!with` block raises an
:exc:`ExceptionGroup`, suppressed exceptions are removed from the
If the code within the :keyword:`!with` block raises a
:exc:`BaseExceptionGroup`, suppressed exceptions are removed from the
group. If any exceptions in the group are not suppressed, a group containing them is re-raised.

.. versionadded:: 3.4

.. versionchanged:: 3.12
``suppress`` now supports suppressing exceptions raised as
part of an :exc:`ExceptionGroup`.
part of an :exc:`BaseExceptionGroup`.

.. function:: redirect_stdout(new_target)

Expand Down
2 changes: 1 addition & 1 deletion Lib/contextlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ def __exit__(self, exctype, excinst, exctb):
return
if issubclass(exctype, self._exceptions):
return True
if issubclass(exctype, ExceptionGroup):
if issubclass(exctype, BaseExceptionGroup):
match, rest = excinst.split(self._exceptions)
if rest is None:
return True
Expand Down
18 changes: 18 additions & 0 deletions Lib/test/test_contextlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -1297,6 +1297,24 @@ def test_exception_groups(self):
[KeyError("ke1"), KeyError("ke2")],
),
)
# Check handling of BaseExceptionGroup, using GeneratorExit so that
# we don't accidentally discard a ctrl-c with KeyboardInterrupt.
with suppress(GeneratorExit):
raise BaseExceptionGroup("message", [GeneratorExit()])
# If we raise a BaseException group, we can still suppress parts
with self.assertRaises(BaseExceptionGroup) as eg1:
with suppress(KeyError):
raise BaseExceptionGroup("message", [GeneratorExit("g"), KeyError("k")])
self.assertExceptionIsLike(
eg1.exception, BaseExceptionGroup("message", [GeneratorExit("g")]),
)
# If we suppress all the leaf BaseExceptions, we get a non-base ExceptionGroup
with self.assertRaises(ExceptionGroup) as eg1:
with suppress(GeneratorExit):
raise BaseExceptionGroup("message", [GeneratorExit("g"), KeyError("k")])
self.assertExceptionIsLike(
eg1.exception, ExceptionGroup("message", [KeyError("k")]),
)


class TestChdir(unittest.TestCase):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:class:`contextlib.suppress` now supports suppressing exceptions raised as
part of a :exc:`BaseExceptionGroup`, in addition to the recent support for
:exc:`ExceptionGroup`.

0 comments on commit d61313b

Please sign in to comment.