python: add anyio support for trio compatibility #4275
+965
−103
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
Add anyio support to the Python bindings. Closes #4239
This PR includes a benchmark script for validation - before merge, it should be deleted in a final commit.
Summary
Migrate Python async bindings from
asynciotoanyiofor Trio compatibility.asyncioprimitives withanyioequivalents (to_thread.run_sync)threading.Event(notanyio.Event) to preserve sync-context initializationabandon_on_cancel=Truefor clean task cancellationtimeoutparameter on worker operations to work with anyioAll original behaviors preserved:
__init__My goal here was to maintain existing behavior. However, I did add two things relevant to anyio semantics:
_run()for fine-grained control.Users wanting timeouts should use
anyio.fail_after()ormove_on_after()(documented inmodule docstring). The internal parameter exists for subclasses or edge cases.
Testing
uvx ruff checkpassesuvx ruff format --checkpassesOf course this still needs to be tested with Turso server.
Performance Benchmark
Measured anyio overhead vs original asyncio implementation on Apple Silicon M3.
Results
Analysis
Trio compatibility is worth the tradeoff in my opinion; local-only workloads can use uvloop if optimization is needed.
Reproducing
Why anyio? Justifying a depenency
Adding dependencies to any project must require a justification. Trio is well-loved for IO-bound concurrency. So mainly this PR expands the userbase of Turso to Python projects that depend on Trio.
Why to not merge this PR
I would totally understand not wanting to add a dependency to a lightweight bindings package. However, I think it is justified given anyio's fundamental role in the ecosystem, backward compatibility, and improvements in cancel-ability.
Description AI Usage
I used Claude Code with Opus 4.5 (with thinking) as an assistant in making a coding plan, figuring out how to maintain exact behavior with asyncio, writing a benchmark, and coding some of the actual changes. I also used it to generate more test cases and write the PR text.