Skip to content

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}")

See Also