python-dependency-injector icon indicating copy to clipboard operation
python-dependency-injector copied to clipboard

Nested dependencies container dependency injection working unexpected

Open Fakhriddin3040 opened this issue 1 month ago • 1 comments

Hello! I encountered with a problem, which can not solve about 3 days. This is due to the nested di containers provided by providers. Container or providers.DependenciesContainer. The main problem that I can not understand how to use it, or the lib does not work as expected. Here is a short example.

from __future__ import annotations
from datetime import tzinfo
from dependency_injector import containers, providers
from dependency_injector.wiring import Provide, inject
from pytz import timezone

class Clock:
    def __init__(self, tz: tzinfo): self.tz = tz
class Repository: ...
class CommandHandler:
    def __init__(self, clock: Clock, repo): self.clock, self.repo = clock, repo

# Core
class CoreServicesDIContainer(containers.DeclarativeContainer):
    clock = providers.Singleton(Clock, tz=timezone("Asia/Dushanbe"))

class CoreDIContainer(containers.DeclarativeContainer):
    services = providers.DependenciesContainer()
    handler = providers.Singleton(
        CommandHandler,
        clock=services.clock,
        repo=lambda: 1,
    )

# Application
class ApplicationRepositoryDIContainer(containers.DeclarativeContainer):
    some_repository = providers.Factory(Repository)

class ApplicationHandlersDIContainer(containers.DeclarativeContainer):
    core = providers.DependenciesContainer()
    repositories = providers.DependenciesContainer()
    command_handler = providers.Factory(
        CommandHandler,
        clock=core.provided.services.clock,
        repo=repositories.some_repository,
    )

class ApplicationDIContainer(containers.DeclarativeContainer):
    core = providers.DependenciesContainer()
    repositories = providers.Container(ApplicationRepositoryDIContainer)
    handlers = providers.Container(ApplicationHandlersDIContainer, core=core, repositories=repositories)

# Root
class RootDIContainer(containers.DeclarativeContainer):
    core = providers.Container(CoreDIContainer, services=providers.Container(CoreServicesDIContainer))
    application = providers.Container(ApplicationDIContainer, core=core)

@inject
def handle(handler: CommandHandler = Provide["application.handlers.command_handler"]): # If replace to "core.services.clock", 'Clock' instance will return.
    print("OK:", type(handler.clock), type(handler.repo))

def main():
    root = RootDIContainer()
    root.wire(modules=[__name__])
    handle()

if __name__ == "__main__":
    main()

The result: OK: <class 'dependency_injector.providers.Dependency'> <class '__main__.Repository'>

If execute script above, the clock type given to handler is 'provider.Singleton'. I noticed that when I address two nested containers at once, like I declared command_handler inside of ApplicationHandlersDIContainer, it will return a provider object instead of dependency object. But repository injection works correct as expected. So, I think the problem in nested containers dependency. Also, provided prop is not helping here. I tried each way.

If you encountered any problem like this, help please. Thank you in advance.

Fakhriddin3040 avatar Oct 27 '25 11:10 Fakhriddin3040