Integrations

diwire works best with libraries that expose dependencies via a generated __init__ signature and type hints.

Supported constructor/field extraction

These work out of the box (no adapters required):

  • dataclasses (stdlib)

  • typing.NamedTuple

  • attrs (@attrs.define)

  • Pydantic BaseModel (v2)

  • msgspec.Struct

Runnable example: Supported frameworks.

pydantic-settings

If you use pydantic-settings, diwire includes a small integration:

  • subclasses of pydantic_settings.BaseSettings are auto-registered as root-scoped Lifetime.SCOPED values (singleton behavior)

  • the default factory is cls()

Runnable example: Pydantic settings.

pytest plugin

diwire ships with an optional pytest plugin that can resolve parameters annotated as Injected[T] directly in test functions from a root test container.

Runnable example: Pytest plugin.

mypy plugin

diwire also ships with an optional mypy plugin for precise @resolver_context.inject typing.

  • preserves strict typing for non-injected parameters

  • makes Injected[T] parameters optional in decorated call signatures

  • adds optional diwire_resolver: ResolverProtocol to decorated call signatures

  • supports both @resolver_context.inject and @resolver_context.inject(...)

Enable it in pyproject.toml:

[tool.mypy]
plugins = ["diwire.integrations.mypy_plugin"]

Web frameworks (FastAPI + Litestar + aiohttp + Flask + Django)

diwire includes dedicated web integrations for FastAPI, Litestar, aiohttp, Flask, and Django. Use @resolver_context.inject(scope=Scope.REQUEST) on handlers/endpoints and register request access with add_request_context(container).

See FastAPI, Litestar, aiohttp, Flask (WSGI), Django, and the runnable script FastAPI.

FastAPI, Litestar, aiohttp, and Django require request-context middleware to bind the active request/connection object. Flask does not require middleware because the integration reads from Flask’s request-local context.

Celery tasks

diwire supports Celery task injection without a dedicated adapter module. Use @resolver_context.inject(scope=Scope.REQUEST) directly on task functions and annotate dependencies as Injected[T].

See Celery.