ets-labs / python-dependency-injector

Dependency injection framework for Python
https://python-dependency-injector.ets-labs.org/
BSD 3-Clause "New" or "Revised" License
3.97k stars 306 forks source link

Async providers with async dependencies #368

Closed kolypto closed 3 years ago

kolypto commented 3 years ago

It turns out that async providers currently cannot have async dependencies.

Example: in this container, both are async functions:

class Container(containers.DeclarativeContainer):
    db = providers.Factory(async_db_provider)
    service = providers.Singleton(async_service, db=db)

Now, when in my code I request an instance of service:

service = await container.service()

the expected result would be an instance of service. The actual result is its unawaited coroutine:

<coroutine object async_service at 0x7faea530fc40>

This behavior persists with Resource, Couroutine, and other providers.


Full source code to reproduce:


# Create two async providers

async def async_db_provider():
    return {'db': 'ok'}  # just some sample object

async def async_service(db = None):
    return {'service': 'ok', 'db': db}

class Container(containers.DeclarativeContainer):
    # Second provider, a singleton, depends on the first one
    db = providers.Factory(async_db_provider)
    service = providers.Singleton(async_service, db=db)

if __name__ == '__main__':
    # Create the container
    container = Container()

    async def main():
        try:
            # Request the service
            service = await container.service()
            print(service)  # <--- expected: instance of service
        finally:
            # Shutdown resources
            shutdown_resources_awaitable = container.shutdown_resources()
            if isawaitable(shutdown_resources_awaitable):
                await shutdown_resources_awaitable

    asyncio.run(main())
rmk135 commented 3 years ago

Thanks @kolypto. I'll take a look.

rmk135 commented 3 years ago

I have fixed it, but can not publish to PyPI cause of CI issues.

Travis CI has changed the policy of OSS projects support recently. I asked them to support Dependency Injector. They provided some credits one-time. Seems like this amount is used, so I'm requesting them to replenish the credits again. I expect this to get resolved in a day or two. Otherwise I will publish source code tar ball from my laptop.

rmk135 commented 3 years ago

@kolypto

Fixed in 4.11.0. It's already on PyPI.

My apologies it was there and it took so long to fix it. I had to make unplanned migrating to Github Actions. I also added extra tests and refactored async injections code. It will go smoothly now. Thanks for reporting the bug. If you find anything else or just need any other help - open an issue.

Best, Roman

kolypto commented 3 years ago

@rmk135 thanks for fixing, it was actually quite responsive of you :)