Integration of Modern-DI to Typer
pip install modern-di-typer
import typing
import typer
import modern_di
from modern_di import Scope, providers, Group
from modern_di_typer import FromDI, inject, setup_di
class Dependencies(Group):
settings = providers.Factory(creator=lambda: {"debug": True})
service = providers.Factory(scope=Scope.REQUEST, creator=MyService, bound_type=None)
app = typer.Typer()
container = modern_di.Container(groups=[Dependencies])
setup_di(app, container)
@app.command()
@inject
def my_command(
name: typing.Annotated[str, typer.Argument()],
service: typing.Annotated[MyService, FromDI(Dependencies.service)],
) -> None:
service.run(name)
if __name__ == "__main__":
with container:
app()To resolve Scope.ACTION dependencies, inject modern_di.Container (the REQUEST-scoped container created by @inject) and build a child:
import modern_di
from modern_di import Scope, providers, Group
from modern_di_typer import FromDI, inject
class Dependencies(Group):
job = providers.Factory(scope=Scope.ACTION, creator=MyJob, bound_type=None)
@app.command()
@inject
def my_command(
container: typing.Annotated[modern_di.Container, FromDI(modern_di.Container)],
) -> None:
with container.build_child_container() as action_container:
job = action_container.resolve_provider(Dependencies.job)
job.run()setup_di(app, container)— register the container with a Typer appinject— decorator that resolvesFromDI-annotated parameters before the command runs; also exposestyper.Contextwithctx.obj["di_container"]for manual useFromDI(provider)— marker used inAnnotated[T, FromDI(...)]; accepts a provider instance or a typefetch_di_container(ctx)— returns the app-scoped container fromctx.obj