Skip to content

Closing does not resolve nested dependecies #702

Closed
@jazzthief

Description

@jazzthief

Closing doesn't seem to resolve nested dependecies: e.g. when a Factory depends on another Factory dependent on a Resource. I have followed issue #633, and linked PR #636 that dealt with the detection of dependent resources, however in my example it doesn't look like it is working when the dependencies are nested.

The following example replicates the code from dependecy-injector test suite
used to test the dependent resources resolution in PR #636. Apart from different naming, the only things I added are NestedService and test_nested_dependency():

from dependency_injector import containers, providers
from dependency_injector.wiring import inject, Provide, Closing


class MyResource:
    init_counter: int = 0
    shutdown_counter: int = 0

    @classmethod
    def reset_counter(cls):
        cls.init_counter = 0
        cls.shutdown_counter = 0

    @classmethod
    def init(cls):
        cls.init_counter += 1

    @classmethod
    def shutdown(cls):
        cls.shutdown_counter += 1


class FactoryService:
    def __init__(self, resource: MyResource):
        self.resource = resource


class NestedService:
    def __init__(self, factory: FactoryService):
        self.factory = factory


def init_resource():
    resource = MyResource()
    resource.init()
    yield resource
    resource.shutdown()


class Container(containers.DeclarativeContainer):

    resource = providers.Resource(init_resource)
    factory_service = providers.Factory(FactoryService, resource)
    nested_service = providers.Factory(NestedService, factory_service)


@inject
def test_function(resource: MyResource = Closing[Provide["resource"]]):
    return resource


@inject
def test_function_dependency(
    factory: FactoryService = Closing[Provide["factory_service"]]
):
    return factory


@inject
def test_nested_dependency(
    nested: NestedService = Closing[Provide["nested_service"]]
):
    return nested.factory


if __name__ == "__main__":
    container = Container()
    container.wire(modules=[__name__])

    MyResource.reset_counter()
    for _ in range(3):
        result = test_nested_dependency()
        print(f"Initialized {result.resource.init_counter} times")
        print(f"Shut down {result.resource.shutdown_counter} times")

Running this with python 3.11.1 and dependency-injector 4.41.0 fails for me with the following traceback:

  File "/home/jazzthief/prg/api-test/api_test/test_closing.py", line 68, in <module>
    container.wire(modules=[__name__])
  File "src/dependency_injector/containers.pyx", line 317, in dependency_injector.containers.DynamicContainer.wire
  File "/home/jazzthief/prg/api-test/.venv/lib/python3.11/site-packages/dependency_injector/wiring.py", line 426, in wire
    _bind_injections(patched, providers_map)
  File "/home/jazzthief/prg/api-test/.venv/lib/python3.11/site-packages/dependency_injector/wiring.py", line 633, in _bind_injections
    deps = _locate_dependent_closing_args(provider)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jazzthief/prg/api-test/.venv/lib/python3.11/site-packages/dependency_injector/wiring.py", line 608, in _locate_dependent_closing_args
    closing_deps += _locate_dependent_closing_args(arg)
TypeError: unsupported operand type(s) for +=: 'dict' and 'dict'

Could anyone please provide any guidance as to whether this is expected behaviour or any existing workarounds? I am trying to use dependency-injector in a large FastAPI project which would greatly benefit from nested Resource closing - and would be glad to try and fix this if possible.

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