
Product
Introducing Socket MCP for Claude Desktop
Add secure dependency scanning to Claude Desktop with Socket MCP, a one-click extension that keeps your coding conversations safe from malicious packages.
A code generator for dependency injection (DI) in Python which is based on the mediator and factory patterns
A code generator for dependency injection (DI) in Python based on the mediator and factory patterns.
@module
and @law_of_demeter
@cached_property
usagepip install reactor-di
from reactor_di import module, law_of_demeter, CachingStrategy
# Example: Database service with configuration forwarding
class DatabaseConfig:
host = "localhost"
port = 5432
timeout = 30
@law_of_demeter("_config")
class DatabaseService:
_config: DatabaseConfig
_host: str # Forwarded from config.host
_port: int # Forwarded from config.port
_timeout: int # Forwarded from config.timeout
def connect(self) -> str:
return f"Connected to {self._host}:{self._port} (timeout: {self._timeout}s)"
# Module: Automatic dependency injection with caching
@module(CachingStrategy.NOT_THREAD_SAFE)
class AppModule:
config: DatabaseConfig # Directly instantiated
database: DatabaseService # Synthesized with dependencies
# Usage
app = AppModule()
db_service = app.database
print(db_service.connect()) # → "Connected to localhost:5432 (timeout: 30s)"
# Properties are cleanly forwarded
print(db_service._host) # → "localhost" (from config.host)
print(db_service._timeout) # → 30 (from config.timeout)
Reactor DI uses a modular file structure for clean separation of concerns:
module.py
- The @module
decorator for dependency injection containerslaw_of_demeter.py
- The @law_of_demeter
decorator for property forwardingcaching.py
- Caching strategies (CachingStrategy.DISABLED
, CachingStrategy.NOT_THREAD_SAFE
)type_utils.py
- Shared type checking utilities used across decoratorsThe decorators work together seamlessly - @law_of_demeter
creates forwarding properties that @module
recognizes during dependency validation, enabling clean cooperation without special configuration.
from reactor_di import module, CachingStrategy
# No caching - components created fresh each time
@module(CachingStrategy.DISABLED)
class DevModule:
service: MyService
# Cached components - same instance returned (not thread-safe)
@module(CachingStrategy.NOT_THREAD_SAFE)
class ProdModule:
service: MyService
@law_of_demeter("_config") # Creates forwarding properties
@law_of_demeter("_module") # Auto-setup: self._config = self._module.config
class ResourceController:
def __init__(self, module):
self._module = module
# Decorator automatically sets up: self._config = module.config
# From _config
_timeout: int
_is_dry_run: bool
# From _module
_api: object
_namespace: str
# No prefix - direct forwarding
@law_of_demeter('config', prefix='')
class DirectController:
timeout: int # → config.timeout
is_dry_run: bool # → config.is_dry_run
# Custom prefix
@law_of_demeter('config', prefix='cfg_')
class PrefixController:
cfg_timeout: int # → config.timeout
cfg_is_dry_run: bool # → config.is_dry_run
Creates a dependency injection module that automatically instantiates and provides dependencies.
Parameters:
strategy
: Caching strategy for component instances
CachingStrategy.DISABLED
: Create new instances each time (default)CachingStrategy.NOT_THREAD_SAFE
: Cache instances (not thread-safe)Usage:
@module(CachingStrategy.NOT_THREAD_SAFE)
class AppModule:
config: Config
service: Service # Automatically injected with dependencies
Creates property forwarding from a base reference to avoid Law of Demeter violations.
Parameters:
base_ref
: Name of the base object attribute to forward fromprefix
: Prefix for forwarded property names (default: "_")Usage:
@law_of_demeter("_config")
class Service:
_timeout: int # Forwards to _config.timeout
_host: str # Forwards to _config.host
Checks if a provided type is compatible with a required type for dependency injection.
Logic:
provided_type == required_type
issubclass(provided_type, required_type)
Safely retrieves type hints with fallback to __annotations__
on error.
Collects type hints from entire inheritance hierarchy (MRO).
Determines if an attribute needs implementation by checking:
Component caching strategies for the @module
decorator.
DISABLED = "disabled"
: No caching, create new instances each timeNOT_THREAD_SAFE = "not_thread_safe"
: Cache instances (not thread-safe)This project uses modern Python tooling and best practices:
uv sync --all-groups
# Run all tests (126 tests, 100% coverage)
uv run pytest
# Run tests with coverage reporting
uv run pytest --cov=reactor_di
# Run specific test modules
uv run pytest tests/test_module.py # Module decorator tests
uv run pytest tests/test_law_of_demeter.py # Law of Demeter decorator tests
uv run pytest tests/test_type_utils.py # Type compatibility utilities tests
uv run pytest tests/test_integration.py # Integration tests between decorators
# Run linting
uv run ruff check src tests
uv run black --check src tests
# Run type checking
uv run mypy src
# Fix formatting
uv run black src tests
This project is licensed under the MIT License - see the LICENSE file for details.
FAQs
A code generator for dependency injection (DI) in Python which is based on the mediator and factory patterns
We found that reactor-di demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Add secure dependency scanning to Claude Desktop with Socket MCP, a one-click extension that keeps your coding conversations safe from malicious packages.
Product
Socket now supports Scala and Kotlin, bringing AI-powered threat detection to JVM projects with easy manifest generation and fast, accurate scans.
Application Security
/Security News
Socket CEO Feross Aboukhadijeh and a16z partner Joel de la Garza discuss vibe coding, AI-driven software development, and how the rise of LLMs, despite their risks, still points toward a more secure and innovative future.