Lightweight, container-agnostic dependency injection for Python — typed, explicit, composable.
Project description
typewirepy
Lightweight, container-agnostic dependency injection for Python — typed, explicit, composable.
Features
- Zero runtime dependencies — only stdlib
- Fully typed — strict mypy + pyright out of the box
- Async-first — native
async/await; sync wrappers included - Immutable wires — safe to share across threads and modules
- Scopes — singleton (default) and transient
- Generator lifecycle —
yield-based creators with automatic cleanup - FastAPI integration —
WireDepends()bridges wires to FastAPI'sDepends()
Installation
pip install typewirepy
With FastAPI support:
pip install typewirepy[fastapi]
Quick Start
Async (primary)
from typewirepy import Scope, TypeWireContainer, type_wire_group_of, type_wire_of
config_wire = type_wire_of(token="Config", creator=lambda: {"db_url": "sqlite://"})
db_wire = type_wire_of(
token="Database",
imports={"config": config_wire},
create_with=lambda deps: f"db({deps['config']['db_url']})",
)
app_wires = type_wire_group_of([config_wire, db_wire])
async def main():
async with TypeWireContainer() as container:
await app_wires.apply(container)
db = await db_wire.get_instance(container)
print(db) # "db(sqlite://)"
Sync
from typewirepy import TypeWireContainer, type_wire_of
wire = type_wire_of(token="Greeting", creator=lambda: "hello")
with TypeWireContainer.sync() as container:
wire.apply_sync(container)
print(wire.get_instance_sync(container)) # "hello"
Key Concepts
Wires
A wire is an immutable description of a dependency — its token (name), how to create it, and what it depends on. Create wires with type_wire_of():
- Leaf wire — uses
creator(zero-arg callable) - Composed wire — uses
create_with+importsto receive resolved dependencies
Imports
Imports declare which other wires a composed wire depends on. They're passed as a dict[str, TypeWire] and delivered to create_with as a dict (Convention A) or as keyword arguments (Convention B):
# Convention A: dict parameter
type_wire_of(token="Svc", imports={"db": db_wire}, create_with=lambda deps: deps["db"])
# Convention B: keyword-only parameters
def create_svc(*, db: Database) -> Service: ...
type_wire_of(token="Svc", imports={"db": db_wire}, create_with=create_svc)
Scopes
Scope.SINGLETON(default) — resolved once, cached for the container's lifetimeScope.TRANSIENT— resolved fresh on every call
Groups
A TypeWireGroup bundles wires together for batch application:
group = type_wire_group_of([config_wire, db_wire, service_wire])
await group.apply(container)
Override wires for testing with with_extra_wires():
test_group = group.with_extra_wires([service_wire.with_creator(lambda _: mock_svc)])
FastAPI Integration
from contextlib import asynccontextmanager
from fastapi import FastAPI
from typewirepy import TypeWireContainer, type_wire_group_of, type_wire_of
from typewirepy.integrations.fastapi import WireDepends
db_wire = type_wire_of(token="DB", creator=lambda: "db_connection")
app_wires = type_wire_group_of([db_wire])
@asynccontextmanager
async def lifespan(app: FastAPI):
async with TypeWireContainer() as container:
await app_wires.apply(container)
app.state.typewire_container = container
yield
app = FastAPI(lifespan=lifespan)
@app.get("/")
async def root(db: str = WireDepends(db_wire)):
return {"db": db}
Contributing
See CONTRIBUTING.md.
License
MIT
Project details
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 typewirepy-0.1.0.tar.gz.
File metadata
- Download URL: typewirepy-0.1.0.tar.gz
- Upload date:
- Size: 61.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","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 |
2eb67fa48faab7bd3e2bd1d603c909c3d7b98c6f9d2bedd3dfe081d2ca642faf
|
|
| MD5 |
f7ff1145506ccecad3c718a3057a5296
|
|
| BLAKE2b-256 |
ca38a47cea11e3f3c4177c04dc33b7cebd80d13cbe0500924f01afa48051bc21
|
File details
Details for the file typewirepy-0.1.0-py3-none-any.whl.
File metadata
- Download URL: typewirepy-0.1.0-py3-none-any.whl
- Upload date:
- Size: 12.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","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 |
fae123c1930fa371aef48f049c07211914e73462da1836abd179e3aa18edb43d
|
|
| MD5 |
7e68c7acfdef792cb4b596e0b2edc2d5
|
|
| BLAKE2b-256 |
498336c89507aabd0703916e9ba7d869c56b1594db8ce5a75f1b2f753372922b
|