Skip to main content

Python Dependency Injection Framework

A dependency injection framework for Python inspired by .NET's DI container system. This framework provides a clean and intuitive way to manage dependencies in your Python applications.

Features

  • Service registration with multiple lifetime scopes (Singleton, Transient, Scoped)
  • Interface-based and concrete type registration
  • Keyed services - Register multiple implementations of the same interface with keys
  • Static container management - Global ServiceProvider for easy application-wide access
  • FastAPI integration - Built-in support for FastAPI dependency injection
  • Constructor injection with automatic dependency resolution
  • Interface-based dependency resolution
  • Circular dependency detection
  • Type-safe service resolution
  • Easy-to-use registration API
  • Factory function support
  • Thread-safe operations

Quick Start

from di_container import ServiceProvider, ServiceLifetime

# Configure services once at application startup
def configure_services(container):
    container.register(IUserService, UserService, ServiceLifetime.SINGLETON)
    container.register(IRepository, DatabaseRepository, ServiceLifetime.SCOPED)
    container.register(Logger, lifetime=ServiceLifetime.SINGLETON)

ServiceProvider.configure(configure_services)

# Use services anywhere in your application
user_service = ServiceProvider.resolve(IUserService)
logger = ServiceProvider.resolve(Logger)

# Or use convenience functions
from di_container import get_service
user_service = get_service(IUserService)

Installation

pip install di-done-right

# For FastAPI integration support
pip install di-done-right[fastapi]

# For development
pip install di-done-right[dev]

Usage Examples

Basic Registration

from di_container import DIContainer, ServiceLifetime

container = DIContainer()

# Interface to implementation
container.register(IUserService, UserService, ServiceLifetime.SINGLETON)

# Concrete type to itself
container.register(DatabaseService, lifetime=ServiceLifetime.SINGLETON)
container.register(Logger)  # Default TRANSIENT lifetime

# Instance registration
config = Configuration("connection_string")
container.register_instance(IConfiguration, config)

# Factory registration
container.register_factory(IEmailService, create_email_service)

# Keyed registrations
container.register_keyed(IPaymentService, "paypal", PayPalService)
container.register_keyed_instance(IConfig, "dev", dev_config)
container.register_keyed_factory(ICache, "redis", create_redis_cache)

Service Resolution

# Resolve services with automatic dependency injection
user_service = container.resolve(IUserService)
logger = container.resolve(Logger)

# Resolve keyed services
paypal_service = container.resolve_keyed(IPaymentService, "paypal")
stripe_service = container.resolve_keyed(IPaymentService, "stripe")

# Optional resolution (returns None if not found)
apple_pay = container.try_resolve_keyed(IPaymentService, "applepay")

Static Container Setup

from di_container import ServiceProvider, get_service

# Configure services once at startup
def configure_services(container):
    container.register(ILogger, ConsoleLogger, ServiceLifetime.SINGLETON)
    container.register(IUserService, UserService, ServiceLifetime.TRANSIENT)

ServiceProvider.configure(configure_services)

# Use anywhere in your application
logger = ServiceProvider.resolve(ILogger)
user_service = get_service(IUserService)  # Convenience function

FastAPI Integration

from fastapi import FastAPI, Depends
from di_container.fastapi_integration import FastAPIIntegration, inject

# Configure services
def configure_services(container):
    container.register(IUserService, UserService, ServiceLifetime.SINGLETON)

app = FastAPI(lifespan=FastAPIIntegration.create_lifespan_manager(configure_services))

# Use dependency injection in routes
@app.get("/users/{user_id}")
async def get_user(
    user_id: int,
    user_service: IUserService = Depends(inject(IUserService))
):
    return user_service.get_user(user_id)

Keyed Services

# Register multiple implementations with keys
container.register_keyed(IPaymentService, "paypal", PayPalService)
container.register_keyed(IPaymentService, "stripe", StripeService)
container.register_keyed(IPaymentService, "crypto", CryptoService)

# Resolve by key
payment_service = container.resolve_keyed(IPaymentService, "paypal")
# Or with ServiceProvider
payment_service = ServiceProvider.resolve_keyed(IPaymentService, "paypal")

# Get all services for a type
all_payment_services = container.get_all_services(IPaymentService)

Scoped Services

container.register(IEmailService, EmailService, ServiceLifetime.SCOPED)

scope = container.begin_scope()
try:
    email_service1 = container.resolve(IEmailService)
    email_service2 = container.resolve(IEmailService)
    # email_service1 is email_service2 -> True (same instance in scope)
finally:
    container.end_scope()

Documentation and Examples

Getting Started

See the Quick Reference Guide for common patterns and immediate usage.

Comprehensive Documentation

The Complete User Documentation includes:

  • Detailed API reference
  • Advanced usage patterns
  • FastAPI integration guide
  • Real-world examples
  • Best practices and troubleshooting

Example Applications

Check the examples/ directory for working demonstrations:

  • basic_usage.py - Basic container usage
  • advanced_usage.py - Advanced features like factories and instances
  • concrete_types_usage.py - Working with concrete types without interfaces
  • keyed_services_usage.py - Multiple implementations with keys
  • static_container_usage.py - Global container management
  • fastapi_example.py - FastAPI integration
  • comprehensive_example.py - Complete e-commerce system example

Structure

  • di_container/ - Core DI framework
    • container.py - Main DI container implementation
    • registration.py - Service registration and configuration
    • exceptions.py - Custom exceptions
    • enums.py - Enumerations and constants
  • examples/ - Usage examples
  • tests/ - Unit tests

Contributing

This project follows Python best practices and includes comprehensive testing.

Metadata

Release files for di-done-right 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for di-done-right 1.0.1
File Size Uploaded Provenance Actions
di_done_right-1.0.1.tar.gz 39.6 kB Without provenance Details for di_done_right-1.0.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for di-done-right 1.0.1
File Interpreter ABI Platform Actions
di_done_right-1.0.1-py3-none-any.whl Python 3 none any Details for di_done_right-1.0.1-py3-none-any.whl

Total release size: 53.3 kB

Release files / di_done_right-1.0.1.tar.gz

Download URL di_done_right-1.0.1.tar.gz
Size 39.6 kB
Tags Source
SHA-256 checksum
How to use checksums
bccdc4c1d8804cf0311f84482e7e037e1cc12e25341ecf3a064348d0abfc8877
BLAKE2b-256 checksum
How to use checksums
91c448ea36ce3981e778fe3cb261afce7cdd0c452fc86091c861d02d07aa855e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.14

Release files / di_done_right-1.0.1-py3-none-any.whl

Download URL di_done_right-1.0.1-py3-none-any.whl
Size 13.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4bfe8dbcbbc3dff1dcde9a085bf2e4c3e8b0f27778ba996deb7d274563b72f34
BLAKE2b-256 checksum
How to use checksums
200440cb4ea14a5fdb4eb108feb84df1bdcc450713621e181a5021b48f4223a7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.14

Security for di-done-right 1.0.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page