Skip to main content

A modern dependency injection framework for Python inspired by .NET DI

Project description

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 -e .

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.

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

di_done_right-1.0.0.tar.gz (33.6 kB view details)

Uploaded Source

Built Distribution

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

di_done_right-1.0.0-py3-none-any.whl (13.7 kB view details)

Uploaded Python 3

File details

Details for the file di_done_right-1.0.0.tar.gz.

File metadata

  • Download URL: di_done_right-1.0.0.tar.gz
  • Upload date:
  • Size: 33.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for di_done_right-1.0.0.tar.gz
Algorithm Hash digest
SHA256 f97734c2eed5cfa162fe7d6408345250e01a8a4a7eb31427414c607e54ff392f
MD5 f48245d96273dbf232d632689faf7032
BLAKE2b-256 1bdd2fe74f07405ddec7e30ce9ca9816d2727e423534892eaf4bea93f6b15542

See more details on using hashes here.

File details

Details for the file di_done_right-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: di_done_right-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 13.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for di_done_right-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 67b88eac379c823e8725c01fc213b3dc433d56b97206e8ff11d1d46b9343e0b0
MD5 a07fb6d94c7a48c0b8cd7a260b75f580
BLAKE2b-256 48a1ae4bd5f3aa54453d69d538945d50e32b06f7b7d00eb9e344135ab0643aeb

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