python-dependency-injector
python-dependency-injector copied to clipboard
Typing and code autocomplete with multi-containers setup
Hi, I decided to switch to set up with multiple Containers used in one main container. Copied code from example:
https://python-dependency-injector.ets-labs.org/examples/application-multiple-containers.html
So my code looks merely the same with one container that aggregates many other:
class Container(containers.DeclarativeContainer):
child = providers.Container(ChildContainer)
And having FastAPI as the main framework I inject dependencies in a router like this:
@router.get("")
@inject
async def test(logger: Logger = Depends(Provide[Container.child.logger])):
logger.info("Oh, hi Mark")
The issue is that Container.child is of Container[ChildContainer] type and even having logger on ChildContainer it is not visible anymore, therefore VS Code doesn't suggest autocomplete options (also not sure whether MyPy will be happy about it, but it is another story)
Is there a legal and safe way to inject dependencies from ChildContainer (when it is provided via another parent container) and have all beauty of a language server functionality?
Example:
from dependency_injector import containers, providers
from dependency_injector.wiring import Provide, inject
class Service:
def hello(self):
print("Hello World")
class ServiceFactory:
def create_service(self):
return Service()
class InnerContainer(containers.DeclarativeContainer):
service_factory = providers.Factory(ServiceFactory)
service = providers.Callable(service_factory().create_service)
class Container(containers.DeclarativeContainer):
inner = providers.Container(InnerContainer)
@inject
def main(service: Service = Provide[Container.inner.service]) -> None: # .service is Any here and auto-completion fails to suggest proper field name
service.hello()
container = Container()
container.wire(modules=[__name__])
main()
I also have this problem. VScode cannot provide typing hints for Container [T]. Use . container in Container [T] to solve this problem
from dependency_injector import containers, providers
from dependency_injector.wiring import Provide, inject
class UserRepo:
pass
class UserService:
def __init__(self, repo: UserRepo) -> None:
self._repo: UserRepo = repo
def test(self):
print("hello")
class Repositories(containers.DeclarativeContainer):
user_repo = providers.Singleton(UserRepo)
class Services(containers.DeclarativeContainer):
repositories = providers.Container(Repositories)
user_service = providers.Singleton(UserService, repo=repositories.container.user_repo) # .user_repo typing hints
class Application(containers.DeclarativeContainer):
repositories = providers.Container(Repositories)
services = providers.Container(Services, repositories=repositories)
@inject
def main( user_service: UserService = Provide[Application.services.container.user_service]): # .user_service typing hints
user_service.test()
if __name__ == "__main__":
container = Application()
container.wire(modules=[__name__])
main()