Skip to content

Commit cfc0755

Browse files
committed
change strict_exception_groups default to True
1 parent 9c496fa commit cfc0755

File tree

15 files changed

+585
-195
lines changed

15 files changed

+585
-195
lines changed

docs/source/reference-core.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -802,9 +802,9 @@ to set the default behavior for any nursery in your program that doesn't overrid
802802
wrapping, so you'll get maximum compatibility with code that was written to
803803
support older versions of Trio.
804804

805-
To maintain backwards compatibility, the default is ``strict_exception_groups=False``.
806-
The default will eventually change to ``True`` in a future version of Trio, once
807-
Python 3.11 and later versions are in wide use.
805+
The default is set to ``strict_exception_groups=True`` in line with the default behaviour
806+
of ``TaskGroup`` in asyncio and anyio. This is also to avoid any bugs caused by only
807+
catching one type of exceptions/exceptiongroups.
808808

809809
.. _exceptiongroup: https://pypi.org/project/exceptiongroup/
810810

newsfragments/2786.breaking.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
``strict_exception_groups`` now defaults to True in ``trio.run`` and ``trio.start_guest_run``, as well as ``trio.open_nursery`` as a result of that.
2+
This is unfortunately very tricky to change with a deprecation period, as raising a ``DeprecationWarning`` whenever ``strict_exception_groups`` is not specified would raise a lot of unnecessary warnings.

src/trio/_core/_run.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,7 @@ class NurseryManager:
917917
918918
"""
919919

920-
strict_exception_groups: bool = attr.ib(default=False)
920+
strict_exception_groups: bool = attr.ib(default=True)
921921

922922
@enable_ki_protection
923923
async def __aenter__(self) -> Nursery:
@@ -985,8 +985,8 @@ def open_nursery(
985985
986986
Args:
987987
strict_exception_groups (bool): If true, even a single raised exception will be
988-
wrapped in an exception group. This will eventually become the default
989-
behavior. If not specified, uses the value passed to :func:`run`.
988+
wrapped in an exception group. If not specified, uses the value passed to
989+
:func:`run`, which defaults to true.
990990
991991
"""
992992
if strict_exception_groups is None:
@@ -2150,7 +2150,7 @@ def run(
21502150
clock: Clock | None = None,
21512151
instruments: Sequence[Instrument] = (),
21522152
restrict_keyboard_interrupt_to_checkpoints: bool = False,
2153-
strict_exception_groups: bool = False,
2153+
strict_exception_groups: bool = True,
21542154
) -> RetT:
21552155
"""Run a Trio-flavored async function, and return the result.
21562156
@@ -2207,9 +2207,9 @@ def run(
22072207
main thread (this is a Python limitation), or if you use
22082208
:func:`open_signal_receiver` to catch SIGINT.
22092209
2210-
strict_exception_groups (bool): If true, nurseries will always wrap even a single
2211-
raised exception in an exception group. This can be overridden on the level of
2212-
individual nurseries. This will eventually become the default behavior.
2210+
strict_exception_groups (bool): Unless set to false, nurseries will always wrap
2211+
even a single raised exception in an exception group. This can be overridden
2212+
on the level of individual nurseries.
22132213
22142214
Returns:
22152215
Whatever ``async_fn`` returns.
@@ -2267,7 +2267,7 @@ def start_guest_run(
22672267
clock: Clock | None = None,
22682268
instruments: Sequence[Instrument] = (),
22692269
restrict_keyboard_interrupt_to_checkpoints: bool = False,
2270-
strict_exception_groups: bool = False,
2270+
strict_exception_groups: bool = True,
22712271
) -> None:
22722272
"""Start a "guest" run of Trio on top of some other "host" event loop.
22732273

src/trio/_core/_tests/test_ki.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
import outcome
1010
import pytest
1111

12+
from trio import testing
13+
from trio.testing import ExpectedExceptionGroup
14+
1215
try:
1316
from async_generator import async_generator, yield_
1417
except ImportError: # pragma: no cover
@@ -293,7 +296,7 @@ async def check_unprotected_kill() -> None:
293296
nursery.start_soon(sleeper, "s2", record_set)
294297
nursery.start_soon(raiser, "r1", record_set)
295298

296-
with pytest.raises(KeyboardInterrupt):
299+
with testing.raises(ExpectedExceptionGroup(KeyboardInterrupt)):
297300
_core.run(check_unprotected_kill)
298301
assert record_set == {"s1 ok", "s2 ok", "r1 raise ok"}
299302

@@ -309,7 +312,7 @@ async def check_protected_kill() -> None:
309312
nursery.start_soon(_core.enable_ki_protection(raiser), "r1", record_set)
310313
# __aexit__ blocks, and then receives the KI
311314

312-
with pytest.raises(KeyboardInterrupt):
315+
with testing.raises(ExpectedExceptionGroup(KeyboardInterrupt)):
313316
_core.run(check_protected_kill)
314317
assert record_set == {"s1 ok", "s2 ok", "r1 cancel ok"}
315318

@@ -331,7 +334,8 @@ def kill_during_shutdown() -> None:
331334

332335
token.run_sync_soon(kill_during_shutdown)
333336

334-
with pytest.raises(KeyboardInterrupt):
337+
# Does not wrap in an ExceptionGroup(!!)
338+
with testing.raises(KeyboardInterrupt):
335339
_core.run(check_kill_during_shutdown)
336340

337341
# KI arrives very early, before main is even spawned
@@ -344,6 +348,7 @@ def before_run(self) -> None:
344348
async def main_1() -> None:
345349
await _core.checkpoint()
346350

351+
# Does not wrap in an ExceptionGroup(!!)
347352
with pytest.raises(KeyboardInterrupt):
348353
_core.run(main_1, instruments=[InstrumentOfDeath()])
349354

src/trio/_core/_tests/test_multierror.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ async def test_MultiErrorNotHashable() -> None:
136136
assert exc1 != exc2
137137
assert exc1 != exc3
138138

139-
with pytest.raises(MultiError):
139+
with pytest.raises(ExceptionGroup):
140140
async with open_nursery() as nursery:
141141
nursery.start_soon(raise_nothashable, 42)
142142
nursery.start_soon(raise_nothashable, 4242)

0 commit comments

Comments
 (0)