Attodi is a small dependency-injection container for Python. You register
types (and optionally concrete implementations or pre-built instances) on a
ServiceCollection, then resolve fully-constructed instances from a
ServiceProvider, which builds constructor arguments automatically from
type hints.
- Python >= 3.12
pip install attodifrom attodi.core import ServiceCollection, ServiceProvider
class Greeter:
def __init__(self, name: str):
self.name = name
def greet(self) -> str:
return f"Hello, {self.name}!"
services = ServiceCollection()
services.add_singleton(str, service="World")
services.add_singleton(Greeter)
provider = ServiceProvider(services)
greeter = provider.get_service(Greeter)
print(greeter.greet()) # Hello, World!ServiceProvider inspects the constructor of the class being resolved,
matches its parameter type hints against registered services, resolves them
recursively, and instantiates the class with the results.
Register services with one of three lifetimes:
| Method | Lifetime | Behavior |
|---|---|---|
add_singleton(cls, concrete=None, service=None) |
Singleton |
One shared instance per ServiceProvider (or a pre-built service value). |
add_scoped(cls, concrete=None) |
Scoped |
One shared instance per scope (see create_scope). |
add_transient(cls, concrete=None) |
Transient |
A new instance every time it is resolved. |
services = ServiceCollection()
services.add_scoped(Database)
provider = ServiceProvider(services)
scope = provider.create_scope()
db = scope.get_service(Database)get_service returns the first matching registration; get_services
returns an iterator over every registration that matches a type (including
subclasses).
for service in provider.get_services(Person):
...GPL-3.0