Container copyingΒΆ

You can create declarative container copies using @containers.copy() decorator.

import sqlite3
from unittest import mock

from dependency_injector import containers, providers

class Service:
    def __init__(self, db):
        self.db = db

class SourceContainer(containers.DeclarativeContainer):

    database = providers.Singleton(sqlite3.connect, ":memory:")
    service = providers.Factory(Service, db=database)

# Copy ``SourceContainer`` providers into ``DestinationContainer``:
class DestinationContainer(SourceContainer):

    database = providers.Singleton(mock.Mock)

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

    service = container.service()
    assert isinstance(service.db, mock.Mock)

Decorator @containers.copy() copies providers from source container to destination container. Destination container provider will replace source provider, if names match.

Decorator @containers.copy() helps you when you create derived declarative containers from the base one. Base container often keeps default dependencies while derived containers define overriding providers. Without @containers.copy() decorator, overridden providers are available in the derived container, but base class dependencies continue to be bound to the base class providers.

class Base(containers.DeclarativeContainer):
    dependency = providers.Dependency(instance_of=str, default="Default value")
    service = providers.Factory(Service, dependency=dependency)

class Derived1(Base):
    dependency = providers.Dependency(instance_of=str, default="Derived 1")

# @containers.copy(Base)  # <-- No @copy decorator
class Derived2(Base):
    dependency = providers.Dependency(instance_of=str, default="Derived 2")

if __name__ == "__main__":
    container1 = Derived1()
    service1 = container1.service()
    print(service1.dependency)  # Derived 1

    container2 = Derived2()
    service2 = container2.service()
    print(service2.dependency)  # Default value