Custom Container¶
-
Back to Scoped Dependencies Overview
Return to the Scoped Dependencies overview page with all topics.
-
Advanced
enter_scope,bind_scope, and FastAPI middleware.
You need this page only if you are not using di or dishka (or you must wrap a library python-cqrs does not ship). For a SQLAlchemy session that lasts for send(), copy the Tutorial instead.
Container.resolve is enough for unscoped DI. To enable CQRS scopes, add open_scope:
@typing.runtime_checkable
class SupportsScope(typing.Protocol[C]):
def open_scope(
self,
context: typing.Mapping[type, typing.Any] | None = None,
) -> typing.AsyncContextManager[Container[C]]: ...
Checklist¶
open_scopeyields a new object, neverself— otherwise concurrentsend()share one UoW.- Finalize on exit — commit/rollback/close generator providers in the context manager’s
__aexit__. - Propagate exceptions — do not swallow handler errors so rollback can run. Under
HANDLERfallback the framework re-raises through this exit so a generator UoW (yield session; commit()) rolls back the failed primary. - Optional — skipping
open_scopeis valid; the framework no-ops and behaviour stays as today. - Structural typing —
SupportsScopeisruntime_checkable; inheritance is not required. - Do not wrap the container yourself — mediators,
saga.transaction, andrecover_sagawrap a plain container internally. Resolving the root container directly insideenter_scopestill one-shots; that is the intended contract.
See examples/di/scoped_dependencies_custom_container.py for a ~80-line template.