Skip to main content

Injection

PyPI - Version GitHub License

PyPI - Python Version

Latest Release Documentation Status

Tests And Linting codecov

Ruff Hatch project uv MyPy Strict

GitHub Downloads (all assets, all releases) PyPI - Month Downloads GitHub Repo stars


Easy dependency injection for all, works with Python 3.8-3.13. Main features and advantages:

  • support Python 3.8-3.13;
  • works with FastAPI, Litestar, Flask and Django REST Framework;
  • support dependency injection via Annotated in FastAPI;
  • support async injections;
  • support auto injection by types;
  • resources with function scope;
  • no wiring;
  • overriding dependencies for testing;
  • 100% code coverage;
  • the code is fully typed and checked with mypy;
  • good documentation;
  • intuitive and almost identical api with dependency-injector, which will allow you to easily migrate to injection (see migration from dependency injector);

Installation

pip install deps-injection

Compatibility between web frameworks and injection features

Framework Dependency injection with @inject Overriding providers Dependency injection with @autoinject
FastAPI ✅ ✅ ➖
Flask ✅ ✅ ✅
Django REST Framework ✅ ✅ ✅
Litestar ✅ ✅ ➖

Quickstart with FastAPI, SQLAlchemy and pytest (sync sqlite)

from contextlib import contextmanager
from random import Random
from typing import Annotated, Any, Callable, Dict, Iterator

import pytest
from fastapi import Depends, FastAPI
from sqlalchemy import create_engine, text
from sqlalchemy.orm import Session, sessionmaker
from starlette.testclient import TestClient

from injection import DeclarativeContainer, Provide, inject, providers


@contextmanager
def db_session_resource(session_factory: Callable[..., Session]) -> Iterator[Session]:
    session = session_factory()
    try:
        yield session
    except Exception:
        session.rollback()
    finally:
        session.close()


class SomeDAO:
    def __init__(self, db_session: Session) -> None:
        self.db_session = db_session

    def get_some_data(self, num: int) -> int:
        stmt = text("SELECT :num").bindparams(num=num)
        data: int = self.db_session.execute(stmt).scalar_one()
        return data


class DIContainer(DeclarativeContainer):
    db_engine = providers.Singleton(
        create_engine,
        url="sqlite:///db.db",
        pool_size=20,
        max_overflow=0,
        pool_pre_ping=False,
    )

    session_factory = providers.Singleton(
        sessionmaker,
        db_engine.cast,
        autoflush=False,
        autocommit=False,
    )

    db_session = providers.Resource(
        db_session_resource,
        session_factory=session_factory.cast,
        function_scope=True,
    )

    some_dao = providers.Factory(SomeDAO, db_session=db_session.cast)


SomeDAODependency = Annotated[SomeDAO, Depends(Provide[DIContainer.some_dao])]

app = FastAPI()


@app.get("/values/{value}")
@inject
async def sqla_resource_handler_async(
    value: int,
    some_dao: SomeDAODependency,
) -> Dict[str, Any]:
    value = some_dao.get_some_data(num=value)
    return {"detail": value}


@pytest.fixture(scope="session")
def test_client() -> TestClient:
    client = TestClient(app)
    return client


def test_sqla_resource(test_client: TestClient) -> None:
    rnd = Random()
    random_int = rnd.randint(-(10**6), 10**6)

    response = test_client.get(f"/values/{random_int}")

    assert response.status_code == 200
    assert not DIContainer.db_session.initialized
    body = response.json()
    assert body["detail"] == random_int

Quickstart with FastAPI, SQLAlchemy and pytest (async sqlite)

from contextlib import asynccontextmanager
from random import Random
from typing import Annotated, Any, Callable, Dict, AsyncIterator

import pytest
from fastapi import Depends, FastAPI
from sqlalchemy import text
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession
from starlette.testclient import TestClient

from injection import DeclarativeContainer, Provide, inject, providers


@asynccontextmanager
async def db_session_resource(session_factory: Callable[..., AsyncSession]) -> AsyncIterator[AsyncSession]:
    session = session_factory()
    try:
        yield session
    except Exception:
        await session.rollback()
    finally:
        await session.close()


class SomeDAO:
    def __init__(self, db_session: AsyncSession) -> None:
        self.db_session = db_session

    async def get_some_data(self, num: int) -> int:
        stmt = text("SELECT :num").bindparams(num=num)
        result = await self.db_session.execute(stmt)
        data: int = result.scalar_one()
        return data


class DIContainer(DeclarativeContainer):
    # need to install aiosqlite and greenlet
    db_engine = providers.Singleton(
        create_async_engine,
        url="sqlite+aiosqlite:///db.db",
        pool_pre_ping=False,
    )

    session_factory = providers.Singleton(
        async_sessionmaker,
        db_engine.cast,
        autoflush=False,
        autocommit=False,
    )

    db_session = providers.Resource(
        db_session_resource,
        session_factory=session_factory.cast,
        function_scope=True,
    )

    some_dao = providers.Factory(SomeDAO, db_session=db_session.cast)


SomeDAODependency = Annotated[SomeDAO, Depends(Provide[DIContainer.some_dao])]

app = FastAPI()


@app.get("/values/{value}")
@inject
async def sqla_resource_handler_async(
        value: int,
        some_dao: SomeDAODependency,
) -> Dict[str, Any]:
    value = await some_dao.get_some_data(num=value)
    return {"detail": value}


@pytest.fixture(scope="session")
def test_client() -> TestClient:
    client = TestClient(app)
    return client


def test_async_sqla_resource(test_client: TestClient) -> None:
    rnd = Random()
    random_int = rnd.randint(-(10 ** 6), 10 ** 6)

    response = test_client.get(f"/values/{random_int}")

    assert response.status_code == 200
    assert not DIContainer.db_session.initialized
    body = response.json()
    assert body["detail"] == random_int

Metadata

Release files for deps-injection 1.8.1

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

Source distribution (sdist)

Source distribution for deps-injection 1.8.1
File Size Uploaded
deps_injection-1.8.1.tar.gz 12.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for deps-injection 1.8.1
File Interpreter ABI Platform
deps_injection-1.8.1-py3-none-any.whl Python 3 none any Details

Total release size: 29.9 kB

Release files / deps_injection-1.8.1.tar.gz

Download URL deps_injection-1.8.1.tar.gz
Size 12.9 kB
Tags Source
SHA-256 checksum
How to use checksums
cc9c87e81874e127e37eebda0a27a284bf92ade1fb5df0a986db94e9e2249eb6
BLAKE2b-256 checksum
How to use checksums
21cbee099e4aa0a4d7a308732f526d8beacb43851360c8db23bdd66f7fff1ba7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 21, 2025.

Transparency log

Release files / deps_injection-1.8.1-py3-none-any.whl

Download URL deps_injection-1.8.1-py3-none-any.whl
Size 17.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b01aba0e8fda23a7286ff2a55438ecba1b1118029f829782f82bbfe176fb69f8
BLAKE2b-256 checksum
How to use checksums
9503776adf710e6ca34ed2a7ca758cc1ba24115470aa623fea340a31d1f44969
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 21, 2025.

Transparency log

Release history Release notifications | RSS feed

This release

1.8.1 This release

2 release files

1.8.0

2 release files

1.7.2

2 release files

1.7.1

2 release files

1.7.0

2 release files

1.6.4

2 release files

1.6.3

2 release files

1.6.2

2 release files

1.6.1

2 release files

1.6.0

2 release files

1.5.4

2 release files

1.5.3

2 release files

1.5.2

2 release files

1.5.1

2 release files

1.5.0

2 release files

1.4.0

2 release files

1.3.0

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release 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