Dependency Injection library
Project description
AnyDI
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.
- Simple: Minimal boilerplate with straightforward API.
- Fast: Low overhead dependency resolution.
- 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.
- Generic support: Automatic TypeVar resolution for generic base classes.
- Framework integrations: Extensions for popular frameworks.
- Testing: Provider override mechanism for test isolation.
Installation
pip install anydi
Quick Example
Define a Service (app/services.py)
class GreetingService:
def greet(self, name: str) -> str:
return f"Hello, {name}!"
Create the Container and Providers (app/container.py)
from anydi import Container
from app.services import GreetingService
container = Container()
@container.provider(scope="singleton")
def service() -> GreetingService:
return GreetingService()
Resolve Dependencies Directly
from app.container import container
from app.services import GreetingService
service = container.resolve(GreetingService)
if __name__ == "__main__":
print(service.greet("World"))
Inject Into Functions (app/main.py)
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))
Test with Overrides (tests/test_app.py)
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.override(GreetingService, service_mock):
result = container.run(greet)
assert result == "Mocked"
Integrate with FastAPI (app/api.py)
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)
Test the FastAPI Integration (test_api.py)
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.override(GreetingService, service_mock):
response = client.get("/greeting")
assert response.json() == {"greeting": "Mocked"}
Integrate with Django Ninja
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),
]
Learn More
Want to know more? Here are helpful resources:
Core Documentation:
- Core Concepts - Learn about containers, providers, scopes, and dependency injection
- Providers - How to register providers and manage resources
- Scopes - How to use built-in and custom scopes
- Dependency Injection - Different ways to inject dependencies
- Testing - How to test your code with provider overrides
Framework Integrations:
- FastAPI - How to use with FastAPI
- Django - How to use with Django and Django Ninja
- FastStream - How to use with message brokers
- Typer - How to use in CLI applications
- Pydantic Settings - How to manage configuration
Full Documentation:
- Read the Docs - All documentation with examples and guides
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file anydi-0.73.0.tar.gz.
File metadata
- Download URL: anydi-0.73.0.tar.gz
- Upload date:
- Size: 36.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1444f1690943e96c629be800c3a4a46ffcf4707b7934f180256b8f92e2b9f2e6
|
|
| MD5 |
60fb531067c086fb87441023ba2006de
|
|
| BLAKE2b-256 |
30e3713c3bda9fbf0173129159ce5d29091d17150f2a52830a5da5b05cbc0d98
|
File details
Details for the file anydi-0.73.0-py3-none-any.whl.
File metadata
- Download URL: anydi-0.73.0-py3-none-any.whl
- Upload date:
- Size: 45.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1732150dc6fc70cc396ab0296eca0e6360237faa86cd3a32c3642b4e3afb1d1b
|
|
| MD5 |
9baba82fd21eb47a97a55c564de1f32a
|
|
| BLAKE2b-256 |
9d8ac53a5a07d0bd1e9d334400b23eaa22641e4443f2ed92c43394d14a329b60
|