Skip to main content

Lightweight, container-agnostic dependency injection for Python — typed, explicit, composable.

Project description

typewirepy

CI Python 3.10+ License: MIT

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 lifecycleyield-based creators with automatic cleanup
  • FastAPI integrationWireDepends() bridges wires to FastAPI's Depends()

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 + imports to 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 lifetime
  • Scope.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

typewirepy-0.1.0.tar.gz (61.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

typewirepy-0.1.0-py3-none-any.whl (12.6 kB view details)

Uploaded Python 3

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

Hashes for typewirepy-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2eb67fa48faab7bd3e2bd1d603c909c3d7b98c6f9d2bedd3dfe081d2ca642faf
MD5 f7ff1145506ccecad3c718a3057a5296
BLAKE2b-256 ca38a47cea11e3f3c4177c04dc33b7cebd80d13cbe0500924f01afa48051bc21

See more details on using hashes here.

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

Hashes for typewirepy-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fae123c1930fa371aef48f049c07211914e73462da1836abd179e3aa18edb43d
MD5 7e68c7acfdef792cb4b596e0b2edc2d5
BLAKE2b-256 498336c89507aabd0703916e9ba7d869c56b1594db8ce5a75f1b2f753372922b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page