Skip to content

Nested containers/dependencies containers working unexpected. #936

@Fakhriddin3040

Description

@Fakhriddin3040

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions