A lightweight, type-safe dependency injection container with automatic wiring, scoped lifetimes, and zero dependencies
Project description
diwire
Modern dependency injection for Python
A lightweight, type-safe dependency injection container with automatic wiring, scoped lifetimes, and zero dependencies.
Features
- Automatic constructor injection - resolves entire dependency chains from type hints
- Function injection - inject dependencies into function parameters with
FromDI() - Scoped lifetimes - transient, singleton, and request/session-scoped instances
- Generator factories - automatic resource cleanup when scopes exit
- Circular dependency detection - clear error messages showing the full chain
- Thread & async safe - works seamlessly with threading and asyncio
- Zero dependencies - just Python 3.10+
Installation
uv add diwire
Quick Start
from dataclasses import dataclass
from diwire import Container, Lifetime
@dataclass
class Database:
host: str = "localhost"
@dataclass
class UserRepository:
db: Database # Injected automatically
@dataclass
class UserService:
repo: UserRepository # Entire chain resolved
container = Container(
# Set default lifetime for auto-registered types
autoregister_default_lifetime=Lifetime.TRANSIENT,
)
service = container.resolve(UserService)
# UserService -> UserRepository -> Database all wired automatically
print(service.repo.db.host) # "localhost"
Function Injection
Mark parameters with FromDI() to inject dependencies while keeping other parameters caller-provided:
from dataclasses import dataclass
from typing import Annotated
from diwire import Container, FromDI
@dataclass
class EmailService:
smtp_host: str = "smtp.example.com"
def send(self, to: str, subject: str) -> str:
return f"Sent '{subject}' to {to} via {self.smtp_host}"
def send_email(
to: str, # Provided by caller
*,
mailer: Annotated[EmailService, FromDI()], # Injected
) -> str:
return mailer.send(to, "Hello!")
container = Container()
send = container.resolve(send_email)
result = send(to="user@example.com") # mailer injected automatically
print(result) # "Sent 'Hello!' to user@example.com via smtp.example.com"
Scoped Dependencies
Manage request/session-level instances with scopes:
from enum import Enum
from diwire import Container, Lifetime
class Scope(str, Enum):
REQUEST = "request"
class DbSession:
def __init__(self) -> None:
self.session_id = id(self)
container = Container()
container.register(DbSession, lifetime=Lifetime.SCOPED_SINGLETON, scope=Scope.REQUEST)
with container.start_scope(Scope.REQUEST) as scope:
session1 = scope.resolve(DbSession)
session2 = scope.resolve(DbSession)
assert session1 is session2 # Same instance within scope
print(f"Same session: {session1.session_id}")
Examples
See the examples/ directory for more patterns including:
- Registration methods (class, factory, instance)
- Lifetime management
- Named components
- Repository pattern with unit of work
- Generator factories for resource cleanup
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file diwire-0.0.1.tar.gz.
File metadata
- Download URL: diwire-0.0.1.tar.gz
- Upload date:
- Size: 163.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
74c4e5e67cbbedb93f93ecd6bbffb03ce032c4d53db1b84151ccb18f69d24332
|
|
| MD5 |
a628cd24b16d8ba993ef5b27045dbda9
|
|
| BLAKE2b-256 |
646033a2a365972c9a36ae9fcf41f6432c206a8c606ef0c60b7131a46e4de58e
|
File details
Details for the file diwire-0.0.1-py3-none-any.whl.
File metadata
- Download URL: diwire-0.0.1-py3-none-any.whl
- Upload date:
- Size: 29.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3704f97721dc72f84df90a2e3c2f3fafa423d3abeaddc06120af2afbf36c00b7
|
|
| MD5 |
f701cf5400448a137bf6c17062bb046f
|
|
| BLAKE2b-256 |
0c1b590d66fce67e99687a72073818f959545ade3778f32464d26f84ae19f91b
|