-
-
Notifications
You must be signed in to change notification settings - Fork 899
✨ Async support optionally using anyio #340
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
Draft
skeletorXVI
wants to merge
48
commits into
fastapi:master
Choose a base branch
from
skeletorXVI:feature/anyio-support
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 40 commits
Commits
Show all changes
48 commits
Select commit
Hold shift + click to select a range
78d6119
Added async support for command and callback including using anyio op…
skeletorXVI 3334fd8
Improve extendability, typing and async engine detection
skeletorXVI acd1746
Fix typo in pyproject.toml
skeletorXVI 801c890
Remove trio extra dependency
skeletorXVI 624ea30
Added documentation for async support
skeletorXVI d676044
Fix formatting
skeletorXVI 1b651f5
Modify completion unit tests to also cover async implementation with …
skeletorXVI 288e6e3
Merge remote-tracking branch 'origin/master' into feature/anyio-support
skeletorXVI 2aaa798
🎨 [pre-commit.ci] Auto format from pre-commit.com hooks
pre-commit-ci[bot] 61baacc
Merge remote-tracking branch 'origin/master' into feature/anyio-support
xqSimone d6b15f4
added missing tests
xqSimone 7c8285a
formatting
xqSimone 54c908a
fix trio import
xqSimone 638e724
update trio and anyio, fix tests
xqSimone aba2b6d
fix anyio version
xqSimone 60c1574
anyio 4.0.0 requires python 3.8
xqSimone 150fe7a
anyio 4.0.0 requires python 3.8 pipeline fix
xqSimone 4be4aa4
increase test coverage
xqSimone e3d9232
fix async tutorial006 and its tests
xqSimone c30baef
remove unused test
xqSimone b45e696
increase test coverage
xqSimone 1aba3c2
remove code for python < 3.8
xqSimone 9e5f303
revert unrelated changes to avoid merge conflicts
svlandeg 0a7ee50
revert unrelated changes to avoid merge conflicts
svlandeg 61785fe
fix typo
svlandeg 8d73664
Merge branch 'master' into feature/anyio-support
svlandeg 99b7cc1
🎨 [pre-commit.ci] Auto format from pre-commit.com hooks
pre-commit-ci[bot] 252dd49
add test requirements
svlandeg eed2a5a
Merge remote-tracking branch 'upstream_skeletor/feature/anyio-support…
svlandeg 290620c
try to make mypy happy for now
svlandeg 858a166
🎨 [pre-commit.ci] Auto format from pre-commit.com hooks
pre-commit-ci[bot] 54de531
try to make mypy happy for now (2)
svlandeg 2ee86fa
Merge remote-tracking branch 'upstream_skeletor/feature/anyio-support…
svlandeg 094ce2f
Merge branch 'master' into feature/anyio-support
svlandeg 2622e84
use capture_output
svlandeg 3a1508a
remove unused ignore statements
svlandeg a625f1e
restore app definition
svlandeg 654541d
remove assertion of exit code (for now)
svlandeg 48b441e
Merge branch 'master' into feature/anyio-support
svlandeg c23264b
dropping 3.7 test
svlandeg 20df81b
use new docs format
svlandeg 4873df6
streamline documentation
svlandeg c4e06e6
🎨 [pre-commit.ci] Auto format from pre-commit.com hooks
pre-commit-ci[bot] 63563c4
fix line numbers
svlandeg c5b48ce
Merge branch 'master' into feature/anyio-support
svlandeg 3e317fb
remove duplicate import
svlandeg f13613f
Merge branch 'master' into feature/anyio-support
svlandeg c1f9569
remove unused ignore statement
svlandeg File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| # Async support | ||
|
|
||
| ## Engines | ||
|
|
||
| Typer supports `asyncio` out of the box. <a href="https://github.com/python-trio/trio" class="external-link" target="_blank"><code>Trio</code></a> is supported through | ||
| <a href="https://github.com/agronholm/anyio" class="external-link" target="_blank"><code>anyio</code></a>, which can be installed as optional dependency: | ||
|
|
||
| <div class="termy"> | ||
|
|
||
| ```console | ||
| $ pip install typer[anyio] | ||
| ---> 100% | ||
| Successfully installed typer anyio | ||
| ``` | ||
|
|
||
| </div> | ||
|
|
||
| ### Default engine selection | ||
|
|
||
| *none* | anyio | trio | anyio + trio | ||
| --- | --- | --- | --- | ||
| asyncio | asyncio via anyio | asyncio* | trio via anyio | ||
|
|
||
| <small>* If you don't want to install `anyio` when using `trio`, provide your own async_runner function</small> | ||
|
|
||
| ## Using with run() | ||
|
|
||
| Async functions can be run just like normal functions: | ||
|
|
||
| ```Python | ||
| {!../docs_src/asynchronous/tutorial001.py!} | ||
| ``` | ||
|
|
||
| Or using `anyio`: | ||
|
|
||
| ```Python | ||
| {!../docs_src/asynchronous/tutorial002.py!} | ||
| ``` | ||
|
|
||
| <small>Important to note, `typer.run()` doesn't provide means to customize the async run behavior.</small> | ||
|
svlandeg marked this conversation as resolved.
Outdated
|
||
|
|
||
| ## Using with commands | ||
|
|
||
| Async functions can be registered as commands just like synchronous functions: | ||
|
|
||
| ```Python | ||
| {!../docs_src/asynchronous/tutorial003.py!} | ||
| ``` | ||
|
|
||
| Or using `anyio`: | ||
|
|
||
| ```Python | ||
| {!../docs_src/asynchronous/tutorial004.py!} | ||
| ``` | ||
|
|
||
| Or using `trio` via `anyio`: | ||
|
|
||
| ```Python | ||
| {!../docs_src/asynchronous/tutorial005.py!} | ||
| ``` | ||
|
|
||
| ## Using with callback | ||
|
|
||
| The callback function supports asynchronous functions just like commands including the `async_runner` parameter: | ||
|
|
||
| ```Python | ||
| {!../docs_src/asynchronous/tutorial006.py!} | ||
| ``` | ||
|
|
||
| Because the asynchronous functions are wrapped in a synchronous context before being executed, it is possible to mix async engines between the callback and commands. | ||
|
|
||
| ## Customizing async engine | ||
|
|
||
| Customizing the used async engine is as simple as providing an additional parameter to the Typer instance or the decorators. | ||
|
|
||
| The `async_runner` provided to the decorator always overwrites the typer instances `async_runner`. | ||
|
|
||
| Customize a single command: | ||
|
|
||
| ```Python | ||
| {!../docs_src/asynchronous/tutorial007.py!} | ||
| ``` | ||
|
|
||
| Customize the default engine for the Typer instance: | ||
|
|
||
| ```Python | ||
| {!../docs_src/asynchronous/tutorial008.py!} | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| import asyncio | ||
|
|
||
| import typer | ||
|
|
||
| app = typer.Typer() | ||
|
|
||
|
|
||
| @app.command() | ||
| async def main(): | ||
| await asyncio.sleep(1) | ||
| typer.echo("Hello World") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| app() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| import anyio | ||
| import typer | ||
|
|
||
| app = typer.Typer() | ||
|
|
||
|
|
||
| @app.command() | ||
| async def main(): | ||
| await anyio.sleep(1) | ||
| typer.echo("Hello World") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| app() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| import asyncio | ||
|
|
||
| import typer | ||
|
|
||
| app = typer.Typer(async_runner=asyncio.run) | ||
|
|
||
|
|
||
| @app.command() | ||
| async def wait(seconds: int): | ||
| await asyncio.sleep(seconds) | ||
| typer.echo(f"Waited for {seconds} seconds") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| app() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| import anyio | ||
| import typer | ||
|
|
||
| app = typer.Typer() | ||
|
|
||
|
|
||
| @app.command() | ||
| async def wait(seconds: int): | ||
| await anyio.sleep(seconds) | ||
| typer.echo(f"Waited for {seconds} seconds") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| app() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| import trio | ||
| import typer | ||
|
|
||
| app = typer.Typer() | ||
|
|
||
|
|
||
| @app.command() | ||
| async def wait(seconds: int): | ||
| await trio.sleep(seconds) | ||
| typer.echo(f"Waited for {seconds} seconds") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| app() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| import asyncio | ||
|
|
||
| import trio | ||
| import typer | ||
|
|
||
| app = typer.Typer() | ||
|
|
||
|
|
||
| @app.command() | ||
| async def wait_trio(seconds: int): | ||
| await trio.sleep(seconds) | ||
| typer.echo(f"Waited for {seconds} seconds using trio (default)") | ||
|
|
||
|
|
||
| @app.callback(async_runner=lambda c: asyncio.run(c)) | ||
| async def wait_asyncio(seconds: int): | ||
| await asyncio.sleep(seconds) | ||
| typer.echo( | ||
| f"Waited for {seconds} seconds before running command using asyncio (customized)" | ||
| ) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| app() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import asyncio | ||
|
|
||
| import trio | ||
| import typer | ||
|
|
||
| app = typer.Typer() | ||
|
|
||
|
|
||
| @app.command() | ||
| async def wait_trio(seconds: int): | ||
| await trio.sleep(seconds) | ||
| typer.echo(f"Waited for {seconds} seconds using trio (default)") | ||
|
|
||
|
|
||
| @app.command(async_runner=asyncio.run) | ||
| async def wait_asyncio(seconds: int): | ||
| await asyncio.sleep(seconds) | ||
| typer.echo(f"Waited for {seconds} seconds using asyncio (custom runner)") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| app() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import asyncio | ||
|
|
||
| import anyio | ||
| import typer | ||
|
|
||
| app = typer.Typer(async_runner=lambda c: anyio.run(lambda: c, backend="asyncio")) | ||
|
|
||
|
|
||
| @app.command() | ||
| async def wait_anyio(seconds: int): | ||
| await anyio.sleep(seconds) | ||
| typer.echo(f"Waited for {seconds} seconds using asyncio via anyio") | ||
|
|
||
|
|
||
| @app.command() | ||
| async def wait_asyncio(seconds: int): | ||
| await asyncio.sleep(seconds) | ||
| typer.echo(f"Waited for {seconds} seconds using asyncio") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| app() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import pytest | ||
| from filelock import FileLock | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def bashrc_lock(): | ||
| with FileLock(".bachrc.lock"): | ||
| yield | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def zshrc_lock(): | ||
| with FileLock(".zsh.lock"): | ||
| yield | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def fish_config_lock(): | ||
| with FileLock(".fish.lock"): | ||
| yield | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def powershell_profile_lock(): | ||
| with FileLock(".powershell.lock"): | ||
| yield |
58 changes: 58 additions & 0 deletions
58
tests/test_completion/for_testing/commands_help_tutorial001_async.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| import typer | ||
|
|
||
| app = typer.Typer(help="Awesome CLI user manager.") | ||
|
|
||
|
|
||
| @app.command() | ||
| async def create(username: str): | ||
| """ | ||
| Create a new user with USERNAME. | ||
| """ | ||
| typer.echo(f"Creating user: {username}") | ||
|
|
||
|
|
||
| @app.command() | ||
| async def delete( | ||
| username: str, | ||
| # force: bool = typer.Option(False, "--force") | ||
| force: bool = typer.Option( | ||
| False, | ||
| prompt="Are you sure you want to delete the user?", | ||
| help="Force deletion without confirmation.", | ||
| ), | ||
| ): | ||
| """ | ||
| Delete a user with USERNAME. | ||
|
|
||
| If --force is not used, will ask for confirmation. | ||
| """ | ||
| typer.echo(f"Deleting user: {username}" if force else "Operation cancelled") | ||
|
|
||
|
|
||
| @app.command() | ||
| async def delete_all( | ||
| force: bool = typer.Option( | ||
| False, | ||
| prompt="Are you sure you want to delete ALL users?", | ||
| help="Force deletion without confirmation.", | ||
| ), | ||
| ): | ||
| """ | ||
| Delete ALL users in the database. | ||
|
|
||
| If --force is not used, will ask for confirmation. | ||
| """ | ||
|
|
||
| typer.echo("Deleting all users" if force else "Operation cancelled") | ||
|
|
||
|
|
||
| @app.command() | ||
| async def init(): | ||
| """ | ||
| Initialize the users database. | ||
| """ | ||
| typer.echo("Initializing user database") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| app() |
17 changes: 17 additions & 0 deletions
17
tests/test_completion/for_testing/commands_index_tutorial002_async.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| import typer | ||
|
|
||
| app = typer.Typer() | ||
|
|
||
|
|
||
| @app.command() | ||
| def create(): | ||
| typer.echo("Creating user: Hiro Hamada") | ||
|
|
||
|
|
||
| @app.command() | ||
| def delete(): | ||
| typer.echo("Deleting user: Hiro Hamada") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| app() |
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.