Skip to content

Replaced the NoCurrentAsyncBackend exception with NoEventLoopError#1049

Merged
agronholm merged 7 commits intomasterfrom
fix-1048
Dec 17, 2025
Merged

Replaced the NoCurrentAsyncBackend exception with NoEventLoopError#1049
agronholm merged 7 commits intomasterfrom
fix-1048

Conversation

@agronholm
Copy link
Owner

Changes

This replaces the private NoCurrentAsyncBackend exception with the existing NoEventLoopError.

Fixes #1048.

Checklist

If this is a user-facing code change, like a bugfix or a new feature, please ensure that
you've fulfilled the following conditions (where applicable):

  • You've added tests (in tests/) which would fail without your patch
  • You've updated the documentation (in docs/), in case of behavior changes or new
    features
  • You've added a new changelog entry (in docs/versionhistory.rst).

If this is a trivial change, like a typo fix or a code reformatting, then you can ignore
these instructions.

Updating the changelog

If there are no entries after the last release, use **UNRELEASED** as the version.
If, say, your patch fixes issue #123, the entry should look like this:

- Fix big bad boo-boo in task groups
  (`#123 <https://github.com/agronholm/anyio/issues/123>`_; PR by @yourgithubaccount)

If there's no issue linked, just link to your pull request instead by updating the
changelog after you've created the PR.

Copy link
Collaborator

@gschaffner gschaffner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also add :raises NoEventLoopError: to various public functions in private modules. Currently, the PR has mostly only added it to public functions in public modules.

TBH, there are a lot of functions that can raise NoEventLoopError via get_async_backend(). Would it make sense to just leave off :raises NoEventLoopError:? It seems tedious to write :raises NoEventLoopError: on every public API that can call get_async_backend(). I am not aware of anyone asking for :raises ~sniffio.AsyncLibraryNotFoundError: to be explicitly documented across AnyIO's APIs in the past, anyway. I think it is implied that it can be raised from lots of AnyIO APIs, and it is self-explanatory when it happens.

@agronholm agronholm requested a review from gschaffner December 17, 2025 01:38
Copy link
Collaborator

@gschaffner gschaffner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. Only comment: Re:

However, I'm not so sure about sync functions. For instance, if anyio.Event always used the back-end implementation you couldn't pre-set it without raising that exception. (Fortunately anyio is smarter than that.)

Thus the existence of this raises: can be a low-visual-clutter reminder that you need to be in async context to call that function/method, without the docs having to mention this explicitly everywhere it's relevant.

OK, so the consensus is that it's better to leave it out of the docs altogether?

Matthias's point regarding :raises NoEventLoopError: on sync functions1 makes sense to me. However it has some maintenance cost for little user benefit, so leaving it out entirely also seems fine to me.

Footnotes

  1. I.e. a bunch of constructors, get_cancelled_exc_class, current_time, etc.

@agronholm
Copy link
Owner Author

Looks good to me. Only comment: Re:

However, I'm not so sure about sync functions. For instance, if anyio.Event always used the back-end implementation you couldn't pre-set it without raising that exception. (Fortunately anyio is smarter than that.)
Thus the existence of this raises: can be a low-visual-clutter reminder that you need to be in async context to call that function/method, without the docs having to mention this explicitly everywhere it's relevant.

OK, so the consensus is that it's better to leave it out of the docs altogether?

Matthias's point regarding :raises NoEventLoopError: on sync functions1 makes sense to me. However it has some maintenance cost for little user benefit, so leaving it out entirely also seems fine to me.

Footnotes

  1. I.e. a bunch of constructors, get_cancelled_exc_class, current_time, etc.

Then I suppose I'll add it back?

@smurfix
Copy link
Collaborator

smurfix commented Dec 17, 2025

However it has some maintenance cost for little user benefit

I don't know about the "little benefit" … in any case, what's the alternative when you do need to discover whether e.g. you can allocate the lock for your singleton object at startup time, try it from the Python REPL and check whether that fails?

@agronholm
Copy link
Owner Author

I added the :raises to all relevant sync functions I could find. @smurfix all good now?

BTW, allocating a lock w/o an event loop has worked for a while now. It's only when you start using the methods in it that require an event loop when it looks up an binds to the actual event loop.

@smurfix
Copy link
Collaborator

smurfix commented Dec 17, 2025

I added the :raises to all relevant sync functions I could find.

Thanks. LGTM.

@agronholm agronholm merged commit 1730f5a into master Dec 17, 2025
18 checks passed
@agronholm agronholm deleted the fix-1048 branch December 17, 2025 12:20
@agronholm
Copy link
Owner Author

Thanks for the reviews!

agronholm added a commit that referenced this pull request Jan 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Regression in Async Libraries discovery

3 participants