From 9b3af1fa1638b8cd49768ce9fb51b242d25f5170 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Mon, 16 Jun 2025 13:23:54 -0400 Subject: [PATCH] Switch to strict-eg nurseries almost everywhere That is just throughout the core library, not the tests yet. Again, we simply change over to using our (nearly equivalent?) `.trionics.collapse_eg()` in place of the already deprecated `strict_exception_groups=False` flag in the following internals, - the conc-fan-out tn use in `._discovery.find_actor()`. - `._portal.open_portal()`'s internal tn used to spawn a bg rpc-msg-loop task. - the daemon and "run-in-actor" layered tn pair allocated in `._supervise._open_and_supervise_one_cancels_all_nursery()`. The remaining loose-eg usage in `._root` and `._runtime` seem to be necessary to keep the test suite green?? For the moment these are left out. --- tractor/_discovery.py | 15 ++++++++++----- tractor/_portal.py | 20 +++++++++++--------- tractor/_rpc.py | 1 - tractor/_supervise.py | 25 +++++++++++++------------ 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/tractor/_discovery.py b/tractor/_discovery.py index fd3e4b1c..71b4b52a 100644 --- a/tractor/_discovery.py +++ b/tractor/_discovery.py @@ -28,7 +28,10 @@ from typing import ( from contextlib import asynccontextmanager as acm from tractor.log import get_logger -from .trionics import gather_contexts +from .trionics import ( + gather_contexts, + collapse_eg, +) from .ipc import _connect_chan, Channel from ._addr import ( UnwrappedAddress, @@ -88,7 +91,6 @@ async def get_registry( yield regstr_ptl - @acm async def get_root( **kwargs, @@ -249,9 +251,12 @@ async def find_actor( for addr in registry_addrs ) portals: list[Portal] - async with gather_contexts( - mngrs=maybe_portals, - ) as portals: + async with ( + collapse_eg(), + gather_contexts( + mngrs=maybe_portals, + ) as portals, + ): # log.runtime( # 'Gathered portals:\n' # f'{portals}' diff --git a/tractor/_portal.py b/tractor/_portal.py index c741df7d..d889521d 100644 --- a/tractor/_portal.py +++ b/tractor/_portal.py @@ -39,7 +39,10 @@ import warnings import trio -from .trionics import maybe_open_nursery +from .trionics import ( + maybe_open_nursery, + collapse_eg, +) from ._state import ( current_actor, ) @@ -558,14 +561,13 @@ async def open_portal( assert actor was_connected: bool = False - async with maybe_open_nursery( - tn, - shield=shield, - strict_exception_groups=False, - # ^XXX^ TODO? soo roll our own then ?? - # -> since we kinda want the "if only one `.exception` then - # just raise that" interface? - ) as tn: + async with ( + collapse_eg(), + maybe_open_nursery( + tn, + shield=shield, + ) as tn, + ): if not channel.connected(): await channel.connect() diff --git a/tractor/_rpc.py b/tractor/_rpc.py index d679661c..56ac1216 100644 --- a/tractor/_rpc.py +++ b/tractor/_rpc.py @@ -756,7 +756,6 @@ async def _invoke( BaseExceptionGroup, BaseException, trio.Cancelled, - ) as _scope_err: scope_err = _scope_err if ( diff --git a/tractor/_supervise.py b/tractor/_supervise.py index e1775292..c647c784 100644 --- a/tractor/_supervise.py +++ b/tractor/_supervise.py @@ -42,6 +42,7 @@ from ._runtime import Actor from ._portal import Portal from .trionics import ( is_multi_cancelled, + collapse_eg, ) from ._exceptions import ( ContextCancelled, @@ -324,9 +325,10 @@ class ActorNursery: server: IPCServer = self._actor.ipc_server with trio.move_on_after(3) as cs: - async with trio.open_nursery( - strict_exception_groups=False, - ) as tn: + async with ( + collapse_eg(), + trio.open_nursery() as tn, + ): subactor: Actor proc: trio.Process @@ -419,10 +421,10 @@ async def _open_and_supervise_one_cancels_all_nursery( # `ActorNursery.start_actor()`). # errors from this daemon actor nursery bubble up to caller - async with trio.open_nursery( - strict_exception_groups=False, - # ^XXX^ TODO? instead unpack any RAE as per "loose" style? - ) as da_nursery: + async with ( + collapse_eg(), + trio.open_nursery() as da_nursery, + ): try: # This is the inner level "run in actor" nursery. It is # awaited first since actors spawned in this way (using @@ -432,11 +434,10 @@ async def _open_and_supervise_one_cancels_all_nursery( # immediately raised for handling by a supervisor strategy. # As such if the strategy propagates any error(s) upwards # the above "daemon actor" nursery will be notified. - async with trio.open_nursery( - strict_exception_groups=False, - # ^XXX^ TODO? instead unpack any RAE as per "loose" style? - ) as ria_nursery: - + async with ( + collapse_eg(), + trio.open_nursery() as ria_nursery, + ): an = ActorNursery( actor, ria_nursery,