Description
Howdy, another somewhat similar issue like #379, this time with providers.Resource
.
Consider this example:
from dependency_injector import providers, containers
import asyncio
class TestObject():
def __init__(self, foo, bar):
self.foo = foo
self.bar = bar
def sync_foo(foo):
print('sync foo triggered!')
return foo
async def async_foo(foo):
print('async foo triggered!')
await asyncio.sleep(0)
return foo
class RootResourceContainer(containers.DeclarativeContainer):
sync_foo_resource=providers.Resource(
sync_foo,
foo='bar'
)
async_foo_resource=providers.Resource(
async_foo,
foo='bar'
)
obj_factory = providers.DelegatedFactory(
TestObject,
foo=async_foo_resource,
bar=sync_foo_resource,
)
class NonRootResourceContainer(containers.DeclarativeContainer):
obj_factory = providers.DelegatedFactory(
TestObject,
foo=providers.Resource(
async_foo,
foo='bar'
),
bar=providers.Resource(
sync_foo,
foo='bar'
)
)
async def main():
container = RootResourceContainer()
await container.init_resources()
print('after init')
print(container.obj_factory())
await container.shutdown_resources()
print('----')
container = NonRootResourceContainer()
await container.init_resources() # Crashing as async non-root async Resource is not detected
print('after init')
print(container.obj_factory())
await container.shutdown_resources()
asyncio.run(main())
First container with everything defined at class root level works, as both Resources are detected and initialized by container.init_resources()
.
Second container with nested Resources definition can't figure it out, and container.init_resources()
is not picking up all resources as stated in docs. In result, if no async resources are found, container.init_resources()
will not be awaitable, and awaiting it will crash.
Also in first container by calling container.obj_factory()
we are receiving awaitable, not actual factory result. As I'm expecting to receive awaitable when there was no previous async Resource initialization and handle this somewhere in my code (as stated in docs), that I'm expecting container.init_resources()
to do the job and resolve every declared resource and get rid of awaiting anything inside my code. Or in another words - I'd like to keep Resource-specific logic at the container layer, without bleeding it into my code, which will be sensitive for IoC layer changes.