Description
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.