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.3.tar.gz (197.0 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.3-py3-none-any.whl (33.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: diwire-0.0.3.tar.gz
  • Upload date:
  • Size: 197.0 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.3.tar.gz
Algorithm Hash digest
SHA256 40ba8565bd1082ac254e033026e1ce74c21eb8d5115ca2c301e187999121ebd3
MD5 60c9395d59874067ffc53bef133e8b5a
BLAKE2b-256 0017d1baaa2fb919a67675ff5a71d985bd03f2723c4a4a36e5171cd3b0ec860f

See more details on using hashes here.

File details

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

File metadata

  • Download URL: diwire-0.0.3-py3-none-any.whl
  • Upload date:
  • Size: 33.1 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.3-py3-none-any.whl
Algorithm Hash digest
SHA256 86d40f2a08fe0f2eb74737fbe07046943d8b9b4b0692530f9991b652867cdb4e
MD5 c69c056afca03d3835592559fd55c6e1
BLAKE2b-256 954c8bed8ad92a8bbd4a9a85d7301208c2a7a4707468b6133a72cf34b997bde4

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