Use cases example¶
This example demonstrates a usage of the DependenciesContainer
provider.
The source code is available on the Github.
Application structure¶
Example application has next structure:
./
└── example/
├── __init__.py
├── __main__.py
├── adapters.py
├── containers.py
└── usecases.py
Containers¶
Listing of the example/containers.py
:
"""Containers module."""
from dependency_injector import containers, providers
from . import adapters, usecases
class Adapters(containers.DeclarativeContainer):
email_sender = providers.Singleton(adapters.SmtpEmailSender)
class TestAdapters(containers.DeclarativeContainer):
email_sender = providers.Singleton(adapters.EchoEmailSender)
class UseCases(containers.DeclarativeContainer):
adapters = providers.DependenciesContainer()
signup = providers.Factory(
usecases.SignupUseCase,
email_sender=adapters.email_sender,
)
Main module¶
Listing of the example/__main__.py
:
"""Main module."""
import sys
from .containers import UseCases, Adapters, TestAdapters
def main(environment: str, email: str) -> None:
if environment == "prod":
adapters = Adapters()
elif environment == "test":
adapters = TestAdapters()
else:
raise RuntimeError("Unknown environment")
use_cases = UseCases(adapters=adapters)
use_case = use_cases.signup()
use_case.execute(email)
if __name__ == "__main__":
main(*sys.argv[1:])
Run the application¶
Instructions for running in the “test” mode:
python run.py test example@example.com
Instructions for running in the “prod” mode:
python run.py prod example@example.com
Adapters and use cases¶
Listing of the example/adapters.py
:
"""Adapters module."""
import abc
class EmailSender(metaclass=abc.ABCMeta):
@abc.abstractmethod
def send(self, to: str, body: str) -> None:
...
class SmtpEmailSender:
def send(self, to: str, body: str) -> None:
print(f"Sending an email to {to} over SMTP, body=\"{body}\"")
class EchoEmailSender:
def send(self, to: str, body: str) -> None:
print(f"Fake sending an email to {to}, body=\"{body}\"")
Listing of the example/usecases.py
:
"""Use cases module."""
import abc
from .adapters import EmailSender
class UseCase(metaclass=abc.ABCMeta):
@abc.abstractmethod
def execute(self) -> None:
...
class SignupUseCase:
def __init__(self, email_sender: EmailSender) -> None:
self.email_sender = email_sender
def execute(self, email: str) -> None:
print(f"Sign up user {email}")
self.email_sender.send(email, f"Welcome, {email}")