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.
  • 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:

Full Documentation:

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

anydi-0.76.0.tar.gz (36.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

anydi-0.76.0-py3-none-any.whl (45.2 kB view details)

Uploaded Python 3

File details

Details for the file anydi-0.76.0.tar.gz.

File metadata

  • Download URL: anydi-0.76.0.tar.gz
  • Upload date:
  • Size: 36.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","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

Hashes for anydi-0.76.0.tar.gz
Algorithm Hash digest
SHA256 87df8ed555244a2e9796dacdb25b407a78f8b7a49cbd3be89c3f670664f3dc07
MD5 dc622f6523d1446b0e60df27a4de2c42
BLAKE2b-256 5cd554ed44f3f1edc0258e0349085378efa1deba7beadb3d9af68f1fd7eba9ce

See more details on using hashes here.

File details

Details for the file anydi-0.76.0-py3-none-any.whl.

File metadata

  • Download URL: anydi-0.76.0-py3-none-any.whl
  • Upload date:
  • Size: 45.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","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

Hashes for anydi-0.76.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3ed9f25e3c171d05ff36f3983369afe65d5c63b2e17d94152d0edab6f10db493
MD5 5f2299026742b34e6b59806af1727d1d
BLAKE2b-256 3bd7985b2c9aea8da3add419a7b63b658b6df695473293f12a73839505f1c7c4

See more details on using hashes here.

Release history Release notifications | RSS feed

0.80.0

2 files

0.79.1

2 files

0.79.0

2 files

0.78.0

2 files

0.77.0

2 files

This release

0.76.0 This release

2 files

0.75.0

2 files

0.74.2

2 files

0.74.1

2 files

0.74.0

2 files

0.73.0

2 files

0.72.0

2 files

0.71.0

2 files

0.70.2

2 files

0.70.1

2 files

0.70.0

2 files

0.69.0

2 files

0.68.0

2 files

0.67.2

2 files

0.67.1

2 files

0.67.0

2 files

0.66.0

2 files

0.65.0

2 files

0.64.0

2 files

0.63.0

2 files

0.62.0

2 files

0.61.0

2 files

0.60.2

2 files

0.60.1

2 files

0.60.0

2 files

0.59.0

2 files

0.58.0

2 files

0.57.0

2 files

0.56.0

2 files

0.55.1

2 files

0.55.0

2 files

0.54.1

2 files

0.54.0

2 files

0.53.0

2 files

0.52.0

2 files

0.50.0

2 files

0.48.2

2 files

0.48.1

2 files

0.48.0

2 files

0.47.0

2 files

0.46.0

2 files

0.45.1

2 files

0.45.0

2 files

0.44.1

2 files

0.44.0

2 files

0.43.0

2 files

0.42.0

2 files

0.41.0

2 files

0.40.0

2 files

0.39.3

2 files

0.39.2

2 files

0.39.1

2 files

0.39.0

2 files

0.38.1

2 files

0.38.0

2 files

0.37.4

2 files

0.37.3

2 files

0.37.2

2 files

0.37.1

2 files

0.37.0

2 files

0.36.0

2 files

0.35.0

2 files

0.34.1

2 files

0.34.0

2 files

0.33.1

2 files

0.33.0

2 files

0.32.2

2 files

0.32.1

2 files

0.32.0

2 files

0.31.0

2 files

0.30.0

2 files

0.29.2

2 files

0.29.1

2 files

0.29.0

2 files

0.28.0

2 files

0.27.1

2 files

0.27.0

2 files

0.26.8

2 files

0.26.7

2 files

0.26.6

2 files

0.26.5

2 files

0.26.4

2 files

0.26.3

2 files

0.26.2

2 files

0.26.1

2 files

0.26.0

2 files

0.25.2

2 files

0.25.1

2 files

0.25.0

2 files

0.24.3

2 files

0.24.2

2 files

0.24.1

2 files

0.24.0

2 files

0.23.0

2 files

0.22.3

2 files

0.22.2

2 files

0.22.1

2 files

0.22.0

2 files

0.21.1

2 files

0.21.0

2 files

0.20.0

2 files

0.19.2

2 files

0.19.1

2 files

0.19.0

2 files

0.18.1

2 files

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