Container overridingΒΆ
The container can be overridden by the other container. All of the providers from the overriding container will override the providers with the same names in the overridden container.
from dependency_injector import containers, providers
class Service:
...
class ServiceStub:
...
class Container(containers.DeclarativeContainer):
service = providers.Factory(Service)
class OverridingContainer(containers.DeclarativeContainer):
service = providers.Factory(ServiceStub)
if __name__ == "__main__":
container = Container()
overriding_container = OverridingContainer()
container.override(overriding_container)
service = container.service()
assert isinstance(service, ServiceStub)
It helps in a testing. Also you can use it for configuring project for the different environments: replace an API client with a stub on the dev or stage.
The container also has:
container.overridden
- tuple of all overriding containers.container.reset_last_overriding()
- reset last overriding for each provider in the container.container.reset_override()
- reset all overriding in the container.
DynamicContainer
has the same functionality.
Another possible way to override container providers on declarative level is
@containers.override()
decorator:
import sqlite3
from unittest import mock
from dependency_injector import containers, providers
class Container(containers.DeclarativeContainer):
database = providers.Singleton(sqlite3.connect, ":memory:")
# Overriding ``Container`` with ``OverridingContainer``:
@containers.override(Container)
class OverridingContainer(containers.DeclarativeContainer):
database = providers.Singleton(mock.Mock)
if __name__ == "__main__":
container = Container()
database = container.database()
assert isinstance(database, mock.Mock)
Decorator @containers.override()
takes a container for overriding as an argument.
This container providers will be overridden by the providers with the same names from
the decorated container.
It helps to change the behaviour of application by importing extension modules but not a code change. Imported module can override providers in main container. While the code uses main container as before, the overridden providers provide components defined in the extension module.