DI Bootstrap API Reference¶
Overview¶
The TD-020 external bootstrap runtime provides a modern, type-safe approach to dependency injection container initialization. This API reference covers the core components introduced in TD-020.
BootstrapRuntime¶
Module: loryth.common.di.bootstrap
External orchestrator that coordinates container bootstrap operations including registration, dependency validation, and singleton preparation.
Constructor¶
BootstrapRuntime(
*,
dependency_analyzer: DependencyAnalyzer | None = None
) -> None
Parameters: - dependency_analyzer - Optional custom dependency analyzer for cycle detection
Methods¶
bootstrap(container, plan)¶
Execute a bootstrap plan on a container.
def bootstrap(
self,
container: Container,
plan: BootstrapPlan
) -> None
Parameters: - container - Target DI container to bootstrap - plan - Bootstrap plan specifying registration steps and validation flags
Raises: - BootstrapError - If dependency validation fails - DiResolutionError - If singleton preparation fails
Properties¶
metrics¶
Returns cumulative bootstrap metrics across all executions.
@property
def metrics(self) -> BootstrapMetrics
Example¶
from loryth.common.di.bootstrap import BootstrapRuntime, BootstrapPlan
from loryth.common.di.container import Container
# Create runtime and container
runtime = BootstrapRuntime()
container = Container()
# Execute bootstrap
plan = BootstrapPlan(
registrations=(
SingletonRegistrationStep(IService, Service),
),
validate_dependencies=True,
eager_prepare=True,
)
runtime.bootstrap(container, plan)
# Check metrics
print(runtime.metrics.snapshot)
BootstrapPlan¶
Module: loryth.common.di.bootstrap
Immutable specification of registration steps and validation/preparation flags.
Constructor¶
BootstrapPlan(
registrations: tuple[RegistrationStep, ...] = (),
validate_dependencies: bool = True,
eager_prepare: bool = True
) -> None
Parameters: - registrations - Sequence of registration steps to execute - validate_dependencies - Enable dependency cycle detection - eager_prepare - Enable eager singleton resolution
Properties¶
registrations¶
Registration steps to execute during bootstrap.
@property
def registrations(self) -> tuple[RegistrationStep, ...]
validate_dependencies¶
Whether to validate dependency cycles.
@property
def validate_dependencies(self) -> bool
eager_prepare¶
Whether to eagerly resolve singletons.
@property
def eager_prepare(self) -> bool
Example¶
from loryth.common.di.bootstrap import BootstrapPlan
# Create plan with validation disabled (for testing)
plan = BootstrapPlan(
registrations=(
SingletonRegistrationStep(IService, Service),
),
validate_dependencies=False,
eager_prepare=False,
)
RegistrationStep Implementations¶
SingletonRegistrationStep¶
Register a singleton service.
SingletonRegistrationStep(
service_type: type,
implementation_type: type
) -> None
Parameters: - service_type - Service interface/abstract type - implementation_type - Concrete implementation type
TransientRegistrationStep¶
Register a transient service.
TransientRegistrationStep(
service_type: type,
implementation_type: type
) -> None
Parameters: - service_type - Service interface/abstract type - implementation_type - Concrete implementation type
FactoryRegistrationStep¶
Register a factory function.
FactoryRegistrationStep(
service_type: type,
factory: Callable[[Container], Any]
) -> None
Parameters: - service_type - Service interface/abstract type - factory - Factory function that creates service instances
InstanceRegistrationStep¶
Register a pre-created instance.
InstanceRegistrationStep(
service_type: type,
instance: Any
) -> None
Parameters: - service_type - Service interface/abstract type - instance - Pre-created service instance
Example¶
from loryth.common.di.bootstrap import (
SingletonRegistrationStep,
TransientRegistrationStep,
FactoryRegistrationStep,
InstanceRegistrationStep
)
# Mixed registration types
plan = BootstrapPlan(
registrations=(
SingletonRegistrationStep(IDatabase, PostgresDatabase),
TransientRegistrationStep(ILogger, ConsoleLogger),
FactoryRegistrationStep(ICache, lambda c: RedisCache()),
InstanceRegistrationStep(IConfig, AppConfig()),
)
)
DependencyAnalyzer¶
Module: loryth.common.di.bootstrap
Validates dependency graphs for cycles using topological sort.
Methods¶
validate(dependency_graph)¶
Validate dependency graph for cycles.
def validate(
self,
dependency_graph: DependencyGraph
) -> None
Parameters: - dependency_graph - Dependency graph to validate
Raises: - BootstrapError - If circular dependency detected
Example¶
from loryth.common.di.bootstrap import DependencyAnalyzer
# Create analyzer
analyzer = DependencyAnalyzer()
# Validate dependency graph
analyzer.validate(container._dependency_graph)
Usage Patterns¶
Basic Application Bootstrap¶
from loryth.common.di.bootstrap import BootstrapRuntime, BootstrapPlan
from loryth.common.di.container import Container
# Standard bootstrap pattern
container = Container()
plan = BootstrapPlan(
registrations=(
SingletonRegistrationStep(IService, Service),
TransientRegistrationStep(ILogger, ConsoleLogger),
),
validate_dependencies=True,
eager_prepare=True,
)
runtime = BootstrapRuntime()
runtime.bootstrap(container, plan)
# Container ready for use
service = container.resolve(IService)
Testing with Partial Validation¶
# Test pattern with validation disabled
plan = BootstrapPlan(
registrations=(
SingletonRegistrationStep(IService, Service),
),
validate_dependencies=False, # Skip cycle detection
eager_prepare=False, # Don't resolve eagerly
)
runtime.bootstrap(container, plan)
# Container registered but not validated - useful for unit tests
Plugin Discovery with Re-Bootstrap¶
# Initial bootstrap
plan1 = BootstrapPlan(
registrations=(
SingletonRegistrationStep(ICoreService, CoreService),
)
)
runtime.bootstrap(container, plan1)
# Later: plugin discovery
plan2 = BootstrapPlan(
registrations=(
SingletonRegistrationStep(ICoreService, CoreService), # No-op
SingletonRegistrationStep(IPluginService, PluginService), # New
)
)
runtime.bootstrap(container, plan2) # Safe re-bootstrap
Error Handling¶
BootstrapError¶
Raised when dependency validation fails (circular dependencies).
try:
runtime.bootstrap(container, plan)
except BootstrapError as e:
print(f"Bootstrap failed: {e}")
DiResolutionError¶
Raised when singleton preparation fails.
try:
runtime.bootstrap(container, plan)
except DiResolutionError as e:
print(f"Preparation failed: {e}")