diff --git a/README.md b/README.md index eb6f773..97915ad 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ | [modern-di-fastapi](https://github.com/modern-python/modern-di-fastapi) | [![Supported versions](https://img.shields.io/pypi/pyversions/modern-di-fastapi.svg)](https://pypi.python.org/pypi/modern-di-fastapi) [![downloads](https://img.shields.io/pypi/dm/modern-di-fastapi.svg)](https://pypistats.org/packages/modern-di-fastapi) | | [modern-di-faststream ](https://github.com/modern-python/modern-di-faststream) | [![Supported versions](https://img.shields.io/pypi/pyversions/modern-di-faststream.svg)](https://pypi.python.org/pypi/modern-di-faststream) [![downloads](https://img.shields.io/pypi/dm/modern-di-faststream.svg)](https://pypistats.org/packages/modern-di-faststream) | | [modern-di-litestar ](https://github.com/modern-python/modern-di-litestar) | [![Supported versions](https://img.shields.io/pypi/pyversions/modern-di-litestar.svg)](https://pypi.python.org/pypi/modern-di-litestar) [![downloads](https://img.shields.io/pypi/dm/modern-di-litestar.svg)](https://pypistats.org/packages/modern-di-litestar) | +| [modern-di-typer](https://github.com/modern-python/modern-di-typer) | [![Supported versions](https://img.shields.io/pypi/pyversions/modern-di-typer.svg)](https://pypi.python.org/pypi/modern-di-typer) [![downloads](https://img.shields.io/pypi/dm/modern-di-typer.svg)](https://pypistats.org/packages/modern-di-typer) | `modern-di` is a python dependency injection framework which supports the following: @@ -16,7 +17,7 @@ - Scopes and context management - Python 3.10+ support - Fully typed and tested -- Integrations with `FastAPI`, `FastStream` and `LiteStar` +- Integrations with `FastAPI`, `FastStream`,`LiteStar` and `Typer` Usage examples: diff --git a/docs/integrations/typer.md b/docs/integrations/typer.md new file mode 100644 index 0000000..8e76623 --- /dev/null +++ b/docs/integrations/typer.md @@ -0,0 +1,108 @@ +# Usage with `Typer` + +## How to use + +1. Install `modern-di-typer`: + +=== "uv" + + ```bash + uv add modern-di-typer + ``` + +=== "pip" + + ```bash + pip install modern-di-typer + ``` + +=== "poetry" + + ```bash + poetry add modern-di-typer + ``` + +2. Apply this code example to your application: + +```python +import datetime +import typing + +import modern_di +import modern_di_typer +import typer +from modern_di import Container, Group, Scope, providers + + +app = typer.Typer() + + +def create_singleton() -> datetime.datetime: + return datetime.datetime.now(tz=datetime.timezone.utc) + + +class AppGroup(Group): + singleton = providers.Factory( + scope=Scope.APP, + creator=create_singleton, + cache_settings=providers.CacheSettings() + ) + + +ALL_GROUPS = [AppGroup] + +container = Container(groups=ALL_GROUPS) +modern_di_typer.setup_di(app, container) + + +@app.command() +@modern_di_typer.inject +def my_command( + instance: typing.Annotated[ + datetime.datetime, + modern_di_typer.FromDI(datetime.datetime), # Resolve by type instead of provider + ], +) -> None: + typer.echo(instance) + + +if __name__ == "__main__": + with container: + app() +``` + +## Action scope + +To resolve `Scope.ACTION` dependencies, inject `modern_di.Container` — `@inject` supplies the +`REQUEST`-scoped container it creates per invocation. Call `build_child_container()` on it to enter +`ACTION` scope: + +```python +import modern_di +import modern_di_typer +import typing +from modern_di import Group, Scope, providers + + +class AppGroup(Group): + job = providers.Factory(scope=Scope.ACTION, creator=..., bound_type=None) + + +@app.command() +@modern_di_typer.inject +def run_job( + container: typing.Annotated[modern_di.Container, modern_di_typer.FromDI(modern_di.Container)], +) -> None: + with container.build_child_container() as action_container: + job = action_container.resolve_provider(AppGroup.job) + job.run() +``` + +## API + +| Symbol | Description | +|---|---| +| `setup_di(app, container)` | Register the app-scoped container with a Typer app | +| `@inject` | Decorator that resolves `FromDI`-annotated parameters before the command runs | +| `FromDI(provider_or_type)` | Marker for `Annotated[T, FromDI(...)]`; accepts a provider instance or a plain type | +| `fetch_di_container(ctx)` | Returns the app-scoped container from `ctx.obj` | diff --git a/mkdocs.yml b/mkdocs.yml index 141d66e..75e0aa5 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -15,6 +15,7 @@ nav: - FastAPI: integrations/fastapi.md - FastStream: integrations/faststream.md - Litestar: integrations/litestar.md + - Typer: integrations/typer.md - Testing: - Fixtures: testing/fixtures.md - Troubleshooting: