Migration from that-depends¶
1. Install modern-di using your favorite tool:¶
If you need only modern-di without integrations:
If you need to integrate with some framework, then install modern-di-*.
2. Migrate dependencies graph¶
- Use
modern-di.Groupinstead ofthat-depends.BaseContainer. - Add scopes to providers.
- Most of the providers will be
APPscope which is the default value. - SQLAlchemy orm session becomes Factory of
REQUEST-scope with cache_settings and finalizer to close connections. - Repositories depending on ORM-session becomes factories of
REQUEST-scope.
from that_depends import BaseContainer, providers
from app import repositories
from app.resources.db import create_sa_engine, create_session
class Dependencies(BaseContainer):
database_engine = providers.Resource(create_sa_engine, settings=settings.cast)
session = providers.ContextResource(create_session, engine=database_engine.cast)
decks_service = providers.Factory(repositories.DecksService, session=session)
cards_service = providers.Factory(repositories.CardsService, session=session)
from modern_di import Group, Scope, providers
from app.repositories import CardsRepository, DecksRepository
from app.resources.db import close_sa_engine, close_session, create_sa_engine, create_session
class Dependencies(Group):
database_engine = providers.Factory(
creator=create_sa_engine, cache_settings=providers.CacheSettings(finalizer=close_sa_engine)
)
session = providers.Factory(
scope=Scope.REQUEST, creator=create_session, cache_settings=providers.CacheSettings(finalizer=close_session)
)
decks_repository = providers.Factory(
scope=Scope.REQUEST,
creator=DecksRepository,
kwargs={"auto_commit": True, "session": session},
)
cards_repository = providers.Factory(
scope=Scope.REQUEST,
creator=CardsRepository,
kwargs={"auto_commit": True, "session": session},
)
3. Migrate integration with framework¶
Usage examples:
- with LiteStar - litestar-sqlalchemy-template
- with FastAPI - fastapi-sqlalchemy-template
4. Migrate routes¶
For fastapi replace fastapi.Depends with modern_di_fastapi.FromDI:
import fastapi
from modern_di_fastapi import FromDI
from app import ioc, schemas
from app.repositories import DecksService
ROUTER: typing.Final = fastapi.APIRouter()
@ROUTER.get("/decks/")
async def list_decks(
decks_service: DecksService = FromDI(DecksService),
) -> schemas.Decks:
objects = await decks_service.list()
return schemas.Decks(items=objects)
For litestar replace litestar.di.Provide with modern_di_litestar.FromDI
import litestar
from modern_di_litestar import FromDI
from app import ioc, schemas
from app.repositories import DecksService
@litestar.get("/decks/", dependencies={
"decks_service": FromDI(DecksService),
})
async def list_decks(decks_service: DecksService) -> schemas.Decks:
objects = await decks_service.list()
return schemas.Decks(items=objects)
5. More info about providers replacements:¶
-
SingletonbecomesFactoryofAPP-scope with cache_settings -
ResourcebecomesFactoryofAPP-scope with cache_settings and finalizer -
ListandDictbecomesFactorywhich accepts some dependencies and returns list or dict accordingly -
ContextResourceusually similar toResourcebecomesFactorywithcache_settingsandfinalizer. The difference is in scope which is usuallyREQUEST. -
FactorystaysFactorywithoutcache_settings