Documentation
AnyDI is a simple Dependency Injection library for Python 3.10+. It works with sync and async applications and uses type annotations (PEP 484).
Main features:
- Type-safe: Uses type hints for dependency resolution.
- Async support: Works with both sync and async code.
- Scopes: Provides singleton, transient, and request scopes. Supports custom scope definitions.
- Named providers: Use
Annotated[...]for multiple providers per type. - Resource management: Context manager protocol support for lifecycle management.
- Modular: Container and module composition for large applications.
- Auto-scan: Automatic discovery of injectable callables.
- Lazy references: Module-level access to dependencies without injection.
- Generic support: Automatic TypeVar resolution for generic base classes.
- Framework integrations: Extensions for popular frameworks.
- Testing: Provider override mechanism for test isolation.
pip install anydiclass GreetingService:
def greet(self, name: str) -> str:
return f"Hello, {name}!"from anydi import Container
from app.services import GreetingService
container = Container()
@container.provider(scope="singleton")
def service() -> GreetingService:
return GreetingService()from app.container import container
from app.services import GreetingService
service = container.resolve(GreetingService)
if __name__ == "__main__":
print(service.greet("World"))from anydi import Provide
from app.container import container
from app.services import GreetingService
def greet(service: Provide[GreetingService]) -> str:
return service.greet("World")
if __name__ == "__main__":
print(container.run(greet))from app.container import container
from app.services import GreetingService
service = container.ref(GreetingService)
def greet() -> str:
return service.greet("World")
if __name__ == "__main__":
print(greet())The container owns the providers, scopes and lifespan either way. Injection and lazy references are two styles of reaching the same dependency.
from unittest import mock
from app.container import container
from app.services import GreetingService
from app.main import greet
def test_greet() -> None:
service_mock = mock.Mock(spec=GreetingService)
service_mock.greet.return_value = "Mocked"
with container.test_mode(), container.override(GreetingService, service_mock):
result = container.run(greet)
assert result == "Mocked"from typing import Annotated
import anydi.ext.fastapi
from fastapi import FastAPI
from anydi import Provide
from app.container import container
from app.services import GreetingService
app = FastAPI()
@app.get("/greeting")
async def greet(
service: Provide[GreetingService]
) -> dict[str, str]:
return {"greeting": service.greet("World")}
anydi.ext.fastapi.install(app, container)from unittest import mock
from fastapi.testclient import TestClient
from app.api import app
from app.container import container
from app.services import GreetingService
client = TestClient(app)
def test_api_greeting() -> None:
service_mock = mock.Mock(spec=GreetingService)
service_mock.greet.return_value = "Mocked"
with container.test_mode(), container.override(GreetingService, service_mock):
response = client.get("/greeting")
assert response.json() == {"greeting": "Mocked"}Install the Django integration extras:
pip install 'anydi-django[ninja]'Expose the container factory (app/container.py):
from anydi import Container
from app.services import GreetingService
container = Container()
@container.provider(scope="singleton")
def service() -> GreetingService:
return GreetingService()Configure Django (settings.py):
INSTALLED_APPS = [
...,
"anydi_django",
]
ANYDI = {
"CONTAINER_FACTORY": "app.container.container",
"PATCH_NINJA": True,
}Wire Django Ninja (urls.py):
from typing import Annotated, Any
from anydi import Provide
from django.http import HttpRequest
from django.urls import path
from ninja import NinjaAPI
from app.services import GreetingService
api = NinjaAPI()
@api.get("/greeting")
def greet(request: HttpRequest, service: Provide[GreetingService]) -> Any:
return {"greeting": service.greet("World")}
urlpatterns = [
path("api/", api.urls),
]Guides:
Framework integrations:
Everything else: