Use cases example — Dependency Injector 4.46.0 documentation (original) (raw)

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}")