Skip to main content

modern-di-litestar

PyPI version Supported Python versions Downloads Coverage CI License GitHub stars uv Ruff ty

modern-di integration for Litestar.

Full guide: Litestar integration docs

Usage example: litestar-sqlalchemy-template

Installation

uv add modern-di-litestar      # or: pip install modern-di-litestar

Usage

1. Define providers

import dataclasses
from modern_di import Group, Scope, providers


@dataclasses.dataclass(kw_only=True)
class Database:
    url: str


@dataclasses.dataclass(kw_only=True)
class UserRepository:
    db: Database


class AppDependencies(Group):
    database = providers.Factory(creator=Database, kwargs={"url": "sqlite:///app.db"})
    user_repo = providers.Factory(scope=Scope.REQUEST, creator=UserRepository)

2. Wire the plugin

import litestar
from modern_di import Container
from modern_di_litestar import ModernDIPlugin

groups = [AppDependencies]

container = Container(groups=groups)
app = litestar.Litestar(
    plugins=[ModernDIPlugin(container, autowired_groups=groups)],
)
container.validate()  # optional fail-fast; the plugin has registered its providers by now

Passing autowired_groups to ModernDIPlugin autowires each provider as a Litestar dependency keyed by its attribute name (database, user_repo), so a route receives one by declaring a parameter with that name. The name di_container is reserved for the plugin's own dependency (section 5). Creating the app raises ImproperlyConfiguredException if a group declares a provider under that name, or if a di_container dependency is already registered when the plugin initializes, whether through Litestar(dependencies=...) or an earlier plugin.

3. Inject into routes

Mark every injected parameter with NamedDependency[...] from litestar.di. Litestar 2.23 deprecated inferring a dependency from a plain annotation, and Litestar 3.0 removes it.

Explicit, per route with FromDI

from litestar.di import NamedDependency
from modern_di_litestar import FromDI


@litestar.get(
    "/users",
    dependencies={"repo": FromDI(UserRepository)},
)
async def list_users(repo: NamedDependency[UserRepository]) -> list[str]: ...

FromDI accepts a type (UserRepository) or a provider instance (AppDependencies.user_repo). Pass a provider instance only for providers outside autowired_groups: Litestar rejects one provider registered under two keys and raises ImproperlyConfiguredException.

Implicit, by autowired provider name

When autowired_groups is passed to ModernDIPlugin, a route receives a provider by naming a parameter after it:

@litestar.get("/users")
async def list_users(user_repo: NamedDependency[UserRepository]) -> list[str]: ...

4. Access the raw request or websocket via DI

def request_method(request: litestar.Request) -> str:
    return request.method


class AppDependencies(Group):
    ...
    request_method = providers.Factory(
        scope=Scope.REQUEST,
        creator=request_method,
        bound_type=None,
    )

litestar_request_provider and litestar_websocket_provider are pre-built ContextProvider instances that make the current Request / WebSocket objects resolvable within DI.

5. Sub-request (action) scopes

The plugin registers a di_container dependency that yields the per-connection child container (REQUEST scope for HTTP, SESSION scope for WebSocket). For work that should live shorter than a request, build a child container from it inside a route:

@litestar.get("/")
async def handler(di_container: NamedDependency[Container]) -> None:
    async with di_container.build_child_container() as action_container:
        result = action_container.resolve_provider(AppDependencies.some_action_scoped_factory)

6. Retrieve the root container

from modern_di_litestar import fetch_di_container

container = fetch_di_container(app)

7. Sharing a container

By default the plugin opens the root container before any of your startup code runs and closes it after all of your shutdown code has run. Your lifespan context managers and your on_startup and on_shutdown hooks can all resolve APP-scoped dependencies, and the APP-scoped finalizers run last. The plugin puts its own manager first in lifespan and its own hook last in on_shutdown. This holds for code passed to Litestar(...) or added by an on_app_init handler or a plugin listed before ModernDIPlugin. A plugin listed after it can still add a manager ahead of it or a shutdown hook behind it.

When the container outlives the app, for example because several apps or a worker share it, pass manage_lifespan=False and open and close it yourself:

container = Container(groups=groups)
app = litestar.Litestar(
    plugins=[ModernDIPlugin(container, autowired_groups=groups, manage_lifespan=False)],
)

async with container:
    ...  # run the app and anything else that shares the container

With the flag off the plugin still registers its providers and still builds and closes a child container for every request and websocket session. Only the root is left to you, and its APP-scoped finalizers run when your async with exits.

8. Streaming responses

Litestar runs dependency cleanup when the handler returns, before it sends the response, so the per-connection child container is already closed while a Stream or ServerSentEvent body runs. A REQUEST-scoped dependency injected with FromDI, such as a database session, has been finalized by then. To use REQUEST-scoped dependencies in the body, open a REQUEST child of the root container inside the generator, as the streaming section of the guide shows.

API

Symbol Description
ModernDIPlugin(container, autowired_groups=None, *, manage_lifespan=True) Litestar InitPlugin that wires the DI container into the app lifecycle. With manage_lifespan=False the app's lifespan leaves the root container alone and you open and close it yourself
FromDI(dependency) Returns a Litestar Provide that resolves a provider (or type) per connection
litestar_request_provider ContextProvider for the current litestar.Request (REQUEST scope)
litestar_websocket_provider ContextProvider for the current litestar.WebSocket (SESSION scope)
fetch_di_container(app) Retrieves the root container from app.state

Part of modern-python

Built on modern-di, a dependency-injection framework with an IoC container and scopes.

Browse the full list of templates and libraries in modern-python; the org profile has the categorized index.

Metadata

Release files for modern-di-litestar 4.2.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for modern-di-litestar 4.2.3
File Size Uploaded Provenance
modern_di_litestar-4.2.3.tar.gz 7.0 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for modern-di-litestar 4.2.3
File Interpreter ABI Platform
modern_di_litestar-4.2.3-py3-none-any.whl Python 3 none any Details

Total release size: 14.1 kB

Release files / modern_di_litestar-4.2.3.tar.gz

Download URL modern_di_litestar-4.2.3.tar.gz
Size 7.0 kB
Tags Source
SHA-256 checksum
How to use checksums
722dd0a70b670dadd1bf57c9903e82e0e7f7258956d431f302ab94698b026996
BLAKE2b-256 checksum
How to use checksums
0dca65d4caae91465b80fc7292432e701f3f68796767400e2c6ed7fa4f81154a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / modern_di_litestar-4.2.3-py3-none-any.whl

Download URL modern_di_litestar-4.2.3-py3-none-any.whl
Size 7.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e4eff74da19b00adf7c5da543b6956f68020fc997736d63ecd0b63a2f924c97c
BLAKE2b-256 checksum
How to use checksums
66e5b77daf8d8c481d4cc76085b38d44e2324c7eedc023c1fb507f41feba2326
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for modern-di-litestar 4.2.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

4.2.3 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page