ets-labs / python-dependency-injector

Dependency injection framework for Python
https://python-dependency-injector.ets-labs.org/
BSD 3-Clause "New" or "Revised" License
3.89k stars 304 forks source link

trouble with the Dependency Injector's `multiple containers` functionality #639

Open kmitjpaul opened 1 year ago

kmitjpaul commented 1 year ago

Hi having trouble with the Dependency Injector's multiple containers functionality please check this documentation segment: https://python-dependency-injector.ets-labs.org/examples/application-multiple-containers.html#main-module

@inject
def main(
        email: str,
        password: str,
        photo: str,
        user_service: UserService = Provide[Application.services.user],
        auth_service: AuthService = Provide[Application.services.auth],
        photo_service: PhotoService = Provide[Application.services.photo],
) -> None:
    user = user_service.get_user(email)
    auth_service.authenticate(user, password)
    photo_service.upload_photo(user, photo)

What it proposes to do is to use the whole chain of containers names Application.services.user not just Services. Using Application.services.user does not make any sense, why would function main() need to know about whole application structure? What if I want to test that function separately outside of "Application"?

This is not exactly an issue, more of me needing an explanation, because it looks like this defeats the whole purpose of Inversion of dependencies

The only solution that comes to mind is to create a list [UserService, AuthService, PhotoService] and wire them all in a loop.

philipbjorge commented 1 year ago

I'm running into something similar with the decoupled packages example.

I added the following to my main container and am manually wiring.

def _recursive_wire(container: containers.Container):
    for provider in container.traverse(types=[providers.Container]):
        _recursive_wire(provider.container)
        provider.wire()

class AppContainer:
  recursive_wire = providers.Callable(_recursive_wire, container=__self__)