Skip to main content

AnyDI

Simple Dependency Injection library that uses Python type annotations.

CI Coverage Documentation CodSpeed


Documentation

http://anydi.readthedocs.io/


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.

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))

Or use a lazy reference (app/main.py)

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.

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.test_mode(), 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.test_mode(), 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),
]

Documentation

Guides:

Framework integrations:

Everything else:

Metadata

Release files for anydi 0.81.0

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

Source distribution (sdist)

Source distribution for anydi 0.81.0
File Size Uploaded Provenance Actions
anydi-0.81.0.tar.gz 43.2 kB Without provenance Details for anydi-0.81.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for anydi 0.81.0
File Interpreter ABI Platform Actions
anydi-0.81.0-py3-none-any.whl Python 3 none any Details for anydi-0.81.0-py3-none-any.whl

Total release size: 96.3 kB

Release files / anydi-0.81.0.tar.gz

Download URL anydi-0.81.0.tar.gz
Size 43.2 kB
Tags Source
SHA-256 checksum
How to use checksums
2107554291fe90fe8477a58f01014e3573dc31e76a452f958ae86972d6998441
BLAKE2b-256 checksum
How to use checksums
72b9a75cb9331d0c871798029cb010c37777c41d7a00be4a56775c95f9264fa9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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 / anydi-0.81.0-py3-none-any.whl

Download URL anydi-0.81.0-py3-none-any.whl
Size 53.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
211b67eeedaa63ba54c06f255d610e4db7f05402d026914325883fa56f47d112
BLAKE2b-256 checksum
How to use checksums
3abf2c499ab52a1a695b95310ce7e205276b891625b691363c8101083dd5b5d7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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 anydi 0.81.0

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.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.81.0 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