Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove MultiError and set strict_exception_groups=True by default #2785

Closed
7 of 8 tasks
Zac-HD opened this issue Sep 2, 2023 · 5 comments
Closed
7 of 8 tasks

Remove MultiError and set strict_exception_groups=True by default #2785

Zac-HD opened this issue Sep 2, 2023 · 5 comments

Comments

@Zac-HD
Copy link
Member

Zac-HD commented Sep 2, 2023

Goal

Our long-term goal is for Trio and our users to use the builtin ExceptionGroup type and except* syntax, and to always raise ExceptionGroup where we might ever do so. #2213 started moving us towards this goal, following discussion in #2211 (and #611), and this issue is about how and when we might finish it.

Proposal

Remove MultiError, using the builtin (or backported) ExceptionGroup type and catching logic instead. At the same time, change the default value of strict_exception_groups to True, to match the behavior of asyncio and anyio TaskGroup.

Later, when strict_exception_groups=False has become very rare or Python 3.10 reaches end of life, we'll remove the strict_exception_groups argument entirely. That's a future issue!

Timing and todos

With the growing popularity of ExceptionGroup in general and anyio in particular, I'm keen to ship this in the next few months - making Trio as "normal" as possible makes it much easier for prospective users to adopt and learn. That said, I think there are a few things we should or could get done first:

@jakkdl
Copy link
Member

jakkdl commented Oct 23, 2023

In #2301 you previously said

I don't think we need a deprecation message; just a two-step approach of first changing the default to strict_exception_groups=True and later removing the option. A logical time for the latter would be shortly after 3.10 goes end-of-life and except* can therefore be assumed, which suggests that the midpoint (late 2024) as a reasonable time to change the default. The docs suggest that it'll change "once Python 3.11 and later versions are in wide use" so we can be a bit flexible.

Unless this issue is just to prep for a release in a year, this seems like moving up the date of the transition quite a bit.

@Zac-HD
Copy link
Member Author

Zac-HD commented Oct 23, 2023

Yep, I now think we should change the default substantially sooner than I proposed last year. What changed?

  • asyncio.TaskGroup has the always-raise-a-group "strict" semantics
  • anyio matches that, and is becoming the normal way to write generally-compatible async libraries
    • this means that strict-by-default is (IMO) the better option for learners and new users, earlier than I expected
    • ⭐ libraries are almost always buggy when strict and non-strict semantics are mixed.
      Based on my experience over the last 18 months or so, I think it's pretty important for ecosystem correctness that we transition to the future default ASAP. I think it's the default that matters here though, so we can still allow legacy code to set strict=False.

If we wait another year, I'm concerned that we'll 'miss the wave'; if we catch it then I think support for Trio could end up standard in most async libraries. I've spoken to many maintainers who are interested in moving from asyncio to anyio, to support some mix of Trio users and TaskGroup-on-older-Pythons. IMO we need to be ready in time for mass adoption of Python 3.11, and that means starting ASAP.

@jakkdl
Copy link
Member

jakkdl commented Nov 2, 2023

All the major tasks are now resolved, only waiting on 0.23 to be released before going ahead with a PR for this. If anybody wants to consider the subtasks of looking for or documenting design patterns regarding inner nurseries it'd be lovely.

@jakkdl
Copy link
Member

jakkdl commented Nov 3, 2023

check for other places where Trio itself might raise groups when a single exception is intended

scanned for calls to open_nursery or MultiError:

  1. DTLSEndpoint.serve explicitly mentions having an inner nursery so seems fine to raise ExceptionGroups
  2. open_tcp_stream has special logic for turning the ExceptionGroup errors to an OSError
  3. serve_listeners seems expected it might raise groups.
    • called by serve_tcp and serve_ssl_over_tcp, who both seem fine to rause groups
  4. run_process looks like this will catch errors so they shouldn't get collected into a group.

I'm far from an expert on parsing concurrency code though, so if any of the above sounds strange please double-check it.

@Zac-HD
Copy link
Member Author

Zac-HD commented Mar 13, 2024

Closing this issue, see #2929 for the remaining docs tasks.

And my sincere thanks again to everyone who contributed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants