-
Notifications
You must be signed in to change notification settings - Fork 14
Description
Hey mates,
On the main page it's said that this lib is good to switch from dependency-injector so I'm hyped already.
But can this library help with wiring FastAPI routers which are defined in a library and should be used eventually in a customer application code?
To elaborate a bit more about my particular example (which fails with other DI libraries):
I want to make a library with some REST API routers for FastAPI application and with some DI bindings to pre-configured so my routers will receive my services:
Here is the LoggignContainer where I have logging-related dependencies:
class LoggingContainer(containers.DeclarativeContainer):
logger = providers.Singleton(MyLogger)
And here is a main BaseContainer where I aggregated all smaller containers from my library, it then can be used in the client code to register (for me) and access (for client) my services if needed:
class BaseContainer(containers.DeclarativeContainer):
app = providers.Container(AppContainer)
logging = providers.Container(LoggingContainer)
web_api = providers.Container(WebApiContainer, app=app, logging=logging)
Here is my library router which should automate some work, very simple one and which uses services registred in IoC Contaier from my lib, specifically my logger:
router = APIRouter()
tag = "Ping"
@router.get("/ping", tags=[tag], status_code=status.HTTP_200_OK)
@inject
async def ping_async(logger: Logger = Depends(Provide[LoggingContainer.logger])):
logger.trace("Ping")
return
In a client code some steps should be done, firstly a client Container to be defined, it has it's own application-related dependencies + inherits from my BaseContainer:
class AppContainer(BaseContainer):
hello_world_service = providers.Factory(HelloWorldService) <- some application related registration
Now client code need to register the library router (typical registration via FastAPI methods) + wire the router :
if __name__ == "__main__":
container = Container()
... here happens FastAPI code and registration of router there ....
container.wire(modules=[ping_router])
container.wire(modules=[__name__])
configure_services()
run_app()
My expectations are Logger from my library will be injected in my router but the results is:
"AttributeError: 'Provide' object has no attribute logger"
I tried many combinations and changed code many ways but unless I directly use AppContainer in my library code (what is impossible to expect beyond local examples and testing since I can not know what is App level container in advance) wiring doesn't work
So now I started to check you examples and in the FastAPI example I see such lines of code:
@ROUTER.get("/decks/")
async def list_decks(
decks_repo: DecksRepository = fastapi.Depends(ioc.IOCContainer.decks_repo),
) -> schemas.Decks:
objects = await decks_repo.all()
return typing.cast(schemas.Decks, {"items": objects})
Where ioc.IOCContainer.decks_repo is a reference to the container in the application code and I decided to ask in advance.
Is it possible in your lib to:
- Define a library Container that will be used or inherited by the Client specific container
- Wire client and library modules with Client Container
- And happily use dependencies from library container in library code not knowing about client-level Container in advance?
Thank you 🙂