core.container.handler_factory¶
src.core.container.handler_factory
¶
Handler Factory Generator - Auto-wire handler dependencies from registry.
This module provides automatic dependency injection for CQRS handlers based on their init type hints. It introspects handler constructors and resolves dependencies from the container.
Architecture: - Uses Python's inspect module to analyze handler signatures - Maps protocol types to container factory functions - Creates request-scoped handler instances with injected dependencies
Usage
from src.core.container.handler_factory import create_handler
In router¶
async def get_handler(session: AsyncSession = Depends(get_db_session)): return await create_handler(RegisterUserHandler, session)
Reference
- docs/architecture/cqrs-registry.md
- docs/architecture/dependency-injection.md
Functions¶
get_type_name
¶
Extract type name from annotation.
Handles both class types and string forward references.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
annotation
|
Any
|
Type annotation (class or string). |
required |
Returns:
| Type | Description |
|---|---|
str
|
Type name as string. |
Source code in src/core/container/handler_factory.py
analyze_handler_dependencies
¶
Analyze handler init to discover dependencies.
Introspects the handler's __init__ method to discover required
dependencies and their types.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
handler_class
|
type
|
Handler class to analyze. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, dict[str, Any]]
|
Dict mapping parameter names to dependency info dicts. |
dict[str, dict[str, Any]]
|
Each info dict contains keys: type_name (str), annotation, is_optional (bool). |
Source code in src/core/container/handler_factory.py
create_handler
async
¶
Create handler instance with auto-wired dependencies.
Introspects handler init and resolves dependencies: - Repositories: Created with session - Singletons: Retrieved from container - Overrides: Provided explicitly
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
handler_class
|
type[T]
|
Handler class to instantiate. |
required |
session
|
AsyncSession
|
Database session for repositories. |
required |
**overrides
|
Any
|
Explicit dependency overrides. |
{}
|
Returns:
| Type | Description |
|---|---|
T
|
Handler instance with injected dependencies. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If dependency cannot be resolved. |
Example
handler = await create_handler(RegisterUserHandler, session) result = await handler.handle(command)
Source code in src/core/container/handler_factory.py
get_supported_dependencies
¶
Get list of supported dependency types.
Returns:
| Type | Description |
|---|---|
dict[str, list[str]]
|
Dict with 'repositories' and 'singletons' lists. |
Source code in src/core/container/handler_factory.py
handler_factory
¶
Generate FastAPI dependency for auto-wired handler creation.
Creates a dependency function compatible with FastAPI's Depends() that automatically injects all handler dependencies based on type hints.
The factory function is cached per handler class to enable testing: tests can override the dependency using the same key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
handler_class
|
type[T]
|
Handler class to generate dependency for. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
FastAPI-compatible dependency function (cached). |
Example
from src.core.container.handler_factory import handler_factory from src.application.commands.handlers.register_user_handler import ( RegisterUserHandler, )
In router:¶
async def create_user( handler: RegisterUserHandler = Depends(handler_factory(RegisterUserHandler)) ): result = await handler.handle(command)
In tests:¶
app.dependency_overrides[handler_factory(RegisterUserHandler)] = ( lambda: mock_handler )
Note
This replaces manual factory functions like get_register_user_handler.
The returned function uses create_handler internally for dependency
resolution.
Source code in src/core/container/handler_factory.py
clear_handler_factory_cache
¶
Clear the handler factory cache.
Useful for test isolation when testing handler_factory itself.
get_all_handler_factories
¶
Generate factory functions for all registered handlers.
Uses the CQRS registry to discover all handlers and creates auto-wired factory functions for each.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Dict mapping handler name to factory function. |
Example
factories = get_all_handler_factories() factories['RegisterUserHandler']