Injectipy¶
A Python dependency injection library using explicit scopes instead of global state. Provides type-safe dependency resolution with circular dependency detection.
Features¶
- Explicit scopes: Dependencies managed within context managers, no global state
- Async/await support: Full support for async/await with proper context isolation
- Type safety: Works with mypy for static type checking
- Circular dependency detection: Detects dependency cycles at registration time
- Thread safety: Each scope is isolated, safe for concurrent use
- Context isolation: Thread and async task isolation using contextvars
- Lazy evaluation: Dependencies resolved only when accessed
- Test isolation: Each test can use its own scope
Quick Example¶
from injectipy import inject, Inject, DependencyScope
# Create a dependency scope
scope = DependencyScope()
# Register dependencies
scope.register_value("config", {"database_url": "sqlite:///app.db"})
scope.register_resolver("database", lambda: Database())
# Use dependency injection
@inject
def create_user(name: str, config: dict = Inject["config"], db: Database = Inject["database"]):
return User.create(name, config["database_url"], db)
# Use within scope context for automatic injection
with scope:
user = create_user("Alice")
Key Characteristics¶
- No global state: Each scope manages its own dependencies
- Context managers: Use
with scope:
to activate dependency injection - Type checking: Works with mypy for compile-time validation
- Thread isolation: Multiple threads can use separate or shared scopes safely
Installation¶
Or with Poetry:
Documentation¶
- Installation - Install and verify setup
- Basic usage examples in this document
- GitHub Examples - Practical code examples
Basic Usage¶
Function Injection¶
from injectipy import inject, Inject, DependencyScope
scope = DependencyScope()
scope.register_value("config", {"debug": True})
@inject
def my_function(config: dict = Inject["config"]):
return config["debug"]
with scope:
result = my_function() # Returns True
Factory Functions¶
def create_database(host=Inject["db_host"], port=Inject["db_port"]):
return Database(host, port)
scope = DependencyScope()
scope.register_value("db_host", "localhost")
scope.register_value("db_port", 5432)
scope.register_resolver("database", create_database)
with scope:
db = scope["database"] # Factory called with injected dependencies
Async/Await Support¶
import asyncio
from injectipy import inject, Inject, DependencyScope
scope = DependencyScope()
scope.register_value("api_key", "secret-key")
@inject
async def fetch_data(endpoint: str, api_key: str = Inject["api_key"]) -> dict:
# Simulate async API call
await asyncio.sleep(0.1)
return {"endpoint": endpoint, "authenticated": bool(api_key)}
async def main():
async with scope: # Use async context manager
data = await fetch_data("/users")
print(data)
asyncio.run(main())
Use Cases¶
- Web Applications: Inject database connections, configuration, services
- CLI Tools: Manage application configuration and resources
- Testing: Easy mocking and test isolation
- Microservices: Clean dependency management across services
- Data Processing: Inject processors, validators, and transformers
Links¶
License¶
MIT License - see LICENSE for details.