Register dependencies
python-injection provides four main decorators to register your dependencies: @injectable, @singleton, @scoped, and @constant. These decorators can be applied to classes, sync functions, or async functions. The @scoped decorator additionally supports sync and async generator functions for context manager support. For pre-existing values, use the set_constant function.
All constructor parameters and factory function parameters are automatically resolved based on their type annotations.
Transient
A new instance is created every time the dependency is resolved.
Singleton
A single instance is created and shared across the entire application.
Constant
Register a pre-existing value as a dependency.
from dataclasses import dataclass
from injection import set_constant
@dataclass(frozen=True)
class Settings:
api_key: str
settings = set_constant(Settings("<secret_api_key>"))
You can also use type aliases to register constants for primitive types:
from injection import set_constant
type APIKey = str
api_key = set_constant("<secret_api_key>", APIKey, alias=True)
For lazy constants, use the @constant decorator:
Factories
All decorators work with both sync and async functions.
Make sure not to forget the return type annotation.
from injection import injectable
class Dependency:
...
@injectable
def _dependency_factory() -> Dependency:
# ...
return Dependency()
Abstract classes
Register an implementation for an abstract class or protocol.
Warning
Make sure the implementation is properly imported in your project for it to be registered (see auto-imports section).
from injection import injectable
from abc import ABC
class AbstractDependency(ABC):
...
@injectable(on=AbstractDependency)
class Dependency(AbstractDependency):
...
Scoped
A single instance is created per scope. Using a StrEnum for scope names is recommended.
Scoped with context manager
Scoped dependencies can be registered using generator functions (sync or async) to handle setup and teardown logic.
Note
If you're unfamiliar with context managers, see Python's context manager documentation.
from collections.abc import Iterator
from injection import scoped
class Dependency:
def open(self):
...
def close(self):
...
@scoped("<scope_name>")
def dependency_factory() -> Iterator[Dependency]:
dependency = Dependency()
dependency.open()
try:
yield dependency
finally:
dependency.close()
Profiles
Register a dependency for a specific profile. Using a StrEnum for profile names is recommended.