You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

reactor-di

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

reactor-di

A code generator for dependency injection (DI) in Python which is based on the mediator and factory patterns

0.1.0
pipPyPI
Maintainers
1

Reactor DI

CI PyPI version Coverage Status Python versions License: MIT

A code generator for dependency injection (DI) in Python based on the mediator and factory patterns.

Features

  • Two powerful decorators: @module and @law_of_demeter
  • Code generation approach: Generates DI code rather than runtime injection
  • Mediator pattern: Central coordination of dependencies
  • Factory pattern: Object creation abstraction
  • Type-safe: Full type hint support
  • Python 3.8+ support: Requires Python 3.8+ due to @cached_property usage

Installation

pip install reactor-di

Quick Start

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)

Architecture

Reactor DI uses a modular file structure for clean separation of concerns:

  • module.py - The @module decorator for dependency injection containers
  • law_of_demeter.py - The @law_of_demeter decorator for property forwarding
  • caching.py - Caching strategies (CachingStrategy.DISABLED, CachingStrategy.NOT_THREAD_SAFE)
  • type_utils.py - Shared type checking utilities used across decorators

The decorators work together seamlessly - @law_of_demeter creates forwarding properties that @module recognizes during dependency validation, enabling clean cooperation without special configuration.

Advanced Usage

Caching Strategies

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

Multiple Decorator Integration

@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

Custom Prefixes

# 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

API Reference

Core Decorators

@module(strategy: CachingStrategy = CachingStrategy.DISABLED)

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

@law_of_demeter(base_ref: str, prefix: str = "_")

Creates property forwarding from a base reference to avoid Law of Demeter violations.

Parameters:

  • base_ref: Name of the base object attribute to forward from
  • prefix: 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

Type Utilities

is_type_compatible(provided_type: Any, required_type: Any) -> bool

Checks if a provided type is compatible with a required type for dependency injection.

Logic:

  • Exact type match: provided_type == required_type
  • String annotations: Name-based comparison
  • None types: Must both be None
  • Class inheritance: issubclass(provided_type, required_type)
  • Complex types: Conservative fallback to True

safe_get_type_hints(cls: Type[Any]) -> Dict[str, Any]

Safely retrieves type hints with fallback to __annotations__ on error.

get_all_type_hints(cls: Type[Any]) -> Dict[str, Any]

Collects type hints from entire inheritance hierarchy (MRO).

needs_implementation(cls: Type[Any], attr_name: str) -> bool

Determines if an attribute needs implementation by checking:

  • Has annotation but no implementation
  • Is an abstract method/property in inheritance hierarchy

Enums

CachingStrategy

Component caching strategies for the @module decorator.

  • DISABLED = "disabled": No caching, create new instances each time
  • NOT_THREAD_SAFE = "not_thread_safe": Cache instances (not thread-safe)

Development

This project uses modern Python tooling and best practices:

Setup

  • Clone the repository
  • Install dependencies:
    uv sync --all-groups
    

Running Tests

# 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

Code Quality

# 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

Contributing

  • Fork the repository
  • Create a feature branch
  • Make your changes
  • Add tests for new functionality with meaningful assertions
  • Ensure all tests pass and 100% coverage is maintained
  • Verify realistic code scenarios rather than mocking impossible edge cases
  • Submit a pull request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Keywords

code-generation

FAQs

Did you know?

Socket

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.

Install

Related posts