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 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 usageadvanced_usage.py- Advanced features like factories and instancesconcrete_types_usage.py- Working with concrete types without interfaceskeyed_services_usage.py- Multiple implementations with keysstatic_container_usage.py- Global container managementfastapi_example.py- FastAPI integrationcomprehensive_example.py- Complete e-commerce system example
Structure
di_container/- Core DI frameworkcontainer.py- Main DI container implementationregistration.py- Service registration and configurationexceptions.py- Custom exceptionsenums.py- Enumerations and constants
examples/- Usage examplestests/- Unit tests
Contributing
This project follows Python best practices and includes comprehensive testing.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file di_done_right-1.0.1.tar.gz.
File metadata
- Download URL: di_done_right-1.0.1.tar.gz
- Upload date:
- Size: 39.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bccdc4c1d8804cf0311f84482e7e037e1cc12e25341ecf3a064348d0abfc8877
|
|
| MD5 |
e6c59479d509238ed23790bf14ee1055
|
|
| BLAKE2b-256 |
91c448ea36ce3981e778fe3cb261afce7cdd0c452fc86091c861d02d07aa855e
|
File details
Details for the file di_done_right-1.0.1-py3-none-any.whl.
File metadata
- Download URL: di_done_right-1.0.1-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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4bfe8dbcbbc3dff1dcde9a085bf2e4c3e8b0f27778ba996deb7d274563b72f34
|
|
| MD5 |
7dc064aa6b70c28ad53cff01a72ae750
|
|
| BLAKE2b-256 |
200440cb4ea14a5fdb4eb108feb84df1bdcc450713621e181a5021b48f4223a7
|