Declarative containerΒΆ

DeclarativeContainer is a class-based style of the providers definition.

You create the declarative container subclass, put the providers as attributes and create the container instance.

from dependency_injector import containers, providers


class Container(containers.DeclarativeContainer):

    factory1 = providers.Factory(object)

    factory2 = providers.Factory(object)


if __name__ == "__main__":
    container = Container()

    object1 = container.factory1()
    object2 = container.factory2()

    print(container.providers)
    # {
    #     "factory1": <dependency_injector.providers.Factory(...),
    #     "factory2": <dependency_injector.providers.Factory(...),
    # }

The declarative container providers should only be used when you have the container instance. Working with the providers of the container on the class level will influence all further instances.

A declarative container cannot have any methods or attributes other than providers.

The container class provides next attributes:

  • providers - the dictionary of all the container providers

  • cls_providers - the dictionary of the container providers of the current container

  • inherited_providers - the dictionary of all the inherited container providers

from dependency_injector import containers, providers


class ContainerA(containers.DeclarativeContainer):

    provider1 = providers.Factory(object)


class ContainerB(ContainerA):

    provider2 = providers.Singleton(object)


assert ContainerA.providers == {
    "provider1": ContainerA.provider1,
}
assert ContainerB.providers == {
    "provider1": ContainerA.provider1,
    "provider2": ContainerB.provider2,
}

assert ContainerA.cls_providers == {
    "provider1": ContainerA.provider1,
}
assert ContainerB.cls_providers == {
    "provider2": ContainerB.provider2,
}

assert ContainerA.inherited_providers == {}
assert ContainerB.inherited_providers == {
    "provider1": ContainerA.provider1,
}

Injections in the declarative container are done the usual way:

import sqlite3

from dependency_injector import containers, providers


class UserService:
    def __init__(self, db: sqlite3.Connection):
        self.db = db


class AuthService:
    def __init__(self, db: sqlite3.Connection, user_service: UserService):
        self.db = db
        self.user_service = user_service


class Container(containers.DeclarativeContainer):

    database = providers.Singleton(sqlite3.connect, ":memory:")

    user_service = providers.Factory(
        UserService,
        db=database,
    )

    auth_service = providers.Factory(
        AuthService,
        db=database,
        user_service=user_service,
    )


if __name__ == "__main__":
    container = Container()

    user_service = container.user_service()
    auth_service = container.auth_service()

    assert user_service.db is auth_service.db is container.database()
    assert isinstance(auth_service.user_service, UserService)

You can override container providers while creating a container instance:

import sqlite3
from unittest import mock

from dependency_injector import containers, providers


class Container(containers.DeclarativeContainer):

    database = providers.Singleton(sqlite3.connect, ":memory:")


if __name__ == "__main__":
    container = Container(database=mock.Mock(sqlite3.Connection))

    database = container.database()
    assert isinstance(database, mock.Mock)

Alternatively, you can call container.override_providers() method when the container instance already exists:

container = Container()

container.override_providers(foo=mock.Mock(Foo), bar=mock.Mock(Bar))

assert isinstance(container.foo(), mock.Mock)
assert isinstance(container.bar(), mock.Mock)

You can also use container.override_providers() with a context manager to reset provided overriding after the context is closed:

container = Container()

with container.override_providers(foo=mock.Mock(Foo), bar=mock.Mock(Bar)):
    assert isinstance(container.foo(), mock.Mock)
    assert isinstance(container.bar(), mock.Mock)

assert isinstance(container.foo(), Foo)
assert isinstance(container.bar(), Bar)