Skip to content

Commit 3780414

Browse files
[3.12] gh-103791: handle BaseExceptionGroup in contextlib.suppress() (GH-111910) (#111955)
gh-103791: handle `BaseExceptionGroup` in `contextlib.suppress()` (GH-111910) (cherry picked from commit d61313b) Co-authored-by: Zac Hatfield-Dodds <[email protected]>
1 parent 4b0c875 commit 3780414

File tree

4 files changed

+25
-4
lines changed

4 files changed

+25
-4
lines changed

Doc/library/contextlib.rst

+3-3
Original file line numberDiff line numberDiff line change
@@ -304,15 +304,15 @@ Functions and classes provided:
304304

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

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

311311
.. versionadded:: 3.4
312312

313313
.. versionchanged:: 3.12
314314
``suppress`` now supports suppressing exceptions raised as
315-
part of an :exc:`ExceptionGroup`.
315+
part of an :exc:`BaseExceptionGroup`.
316316

317317
.. function:: redirect_stdout(new_target)
318318

Lib/contextlib.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ def __exit__(self, exctype, excinst, exctb):
457457
return
458458
if issubclass(exctype, self._exceptions):
459459
return True
460-
if issubclass(exctype, ExceptionGroup):
460+
if issubclass(exctype, BaseExceptionGroup):
461461
match, rest = excinst.split(self._exceptions)
462462
if rest is None:
463463
return True

Lib/test/test_contextlib.py

+18
Original file line numberDiff line numberDiff line change
@@ -1287,6 +1287,24 @@ def test_exception_groups(self):
12871287
[KeyError("ke1"), KeyError("ke2")],
12881288
),
12891289
)
1290+
# Check handling of BaseExceptionGroup, using GeneratorExit so that
1291+
# we don't accidentally discard a ctrl-c with KeyboardInterrupt.
1292+
with suppress(GeneratorExit):
1293+
raise BaseExceptionGroup("message", [GeneratorExit()])
1294+
# If we raise a BaseException group, we can still suppress parts
1295+
with self.assertRaises(BaseExceptionGroup) as eg1:
1296+
with suppress(KeyError):
1297+
raise BaseExceptionGroup("message", [GeneratorExit("g"), KeyError("k")])
1298+
self.assertExceptionIsLike(
1299+
eg1.exception, BaseExceptionGroup("message", [GeneratorExit("g")]),
1300+
)
1301+
# If we suppress all the leaf BaseExceptions, we get a non-base ExceptionGroup
1302+
with self.assertRaises(ExceptionGroup) as eg1:
1303+
with suppress(GeneratorExit):
1304+
raise BaseExceptionGroup("message", [GeneratorExit("g"), KeyError("k")])
1305+
self.assertExceptionIsLike(
1306+
eg1.exception, ExceptionGroup("message", [KeyError("k")]),
1307+
)
12901308

12911309

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

0 commit comments

Comments
 (0)