Skip to main content

A lightweight, type-safe dependency injection container with automatic wiring, scoped lifetimes, and zero dependencies

Project description

diwire

Modern dependency injection for Python

PyPI version Python versions License: MIT codecov

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

diwire-0.0.1.tar.gz (163.8 kB view details)

Uploaded Source

Built Distribution

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

diwire-0.0.1-py3-none-any.whl (29.9 kB view details)

Uploaded Python 3

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

Hashes for diwire-0.0.1.tar.gz
Algorithm Hash digest
SHA256 74c4e5e67cbbedb93f93ecd6bbffb03ce032c4d53db1b84151ccb18f69d24332
MD5 a628cd24b16d8ba993ef5b27045dbda9
BLAKE2b-256 646033a2a365972c9a36ae9fcf41f6432c206a8c606ef0c60b7131a46e4de58e

See more details on using hashes here.

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

Hashes for diwire-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3704f97721dc72f84df90a2e3c2f3fafa423d3abeaddc06120af2afbf36c00b7
MD5 f701cf5400448a137bf6c17062bb046f
BLAKE2b-256 0c1b590d66fce67e99687a72073818f959545ade3778f32464d26f84ae19f91b

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