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.2.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.2-py3-none-any.whl (30.0 kB view details)

Uploaded Python 3

File details

Details for the file diwire-0.0.2.tar.gz.

File metadata

  • Download URL: diwire-0.0.2.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.2.tar.gz
Algorithm Hash digest
SHA256 bd0bedf09aae7cd9686991558fe4ff311c8a322f3099b7b3d0dd9c8db6fcc2fc
MD5 eefc505a75bf25631fc4c25f6aedeeb5
BLAKE2b-256 be39d65bb6d16308538d5900090882dd67af9749d2cecedad3bec1405073e0db

See more details on using hashes here.

File details

Details for the file diwire-0.0.2-py3-none-any.whl.

File metadata

  • Download URL: diwire-0.0.2-py3-none-any.whl
  • Upload date:
  • Size: 30.0 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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 b41bc41c510706742c21696fec7c55adb62f8de661d32f95e863708132ca2fce
MD5 e3b999acf1abe1c05b9d27e9f0b66e4f
BLAKE2b-256 7aacc9d679cea6096b1dcd86d72405df303425820f39640e0844204f902f0df4

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