Skip to content

add_kwargs fails to override async Resource dependencies #974

Description

@beaudrychase

I am using dependency-injector version 4.49.1. Running on Python 3.12.13.

The following snippet reproduces the error I'm seeing. case_2_use_kwarg_does_nothing reproduces the error, while the other cases outline minimal differences that cause it to behave as expected. Happy to provide more details if it helps. Thanks for looking into this.

import asyncio

from dependency_injector.containers import DeclarativeContainer
from dependency_injector.providers import Resource, Singleton


class ExampleResource:
    _val: int

    def __init__(self, val) -> None:
        self._val = val


class ExampleResourceWithAsyncContext(ExampleResource):

    async def __aenter__(self) -> "ExampleResourceWithAsyncContext":
        return self

    async def __aexit__(
        self,
    ) -> None:
        return None


class ExampleSingleton:
    _resource: ExampleResource

    def __init__(self, resource: ExampleResource) -> None:
        self._resource = resource


class Container(DeclarativeContainer):
    example_async_resource = Resource(ExampleResourceWithAsyncContext, val=1)
    example_singleton_with_async_resource = Singleton(
        ExampleSingleton, resource=example_async_resource
    )

    async_resource_as_singleton = Singleton(ExampleResourceWithAsyncContext, val=2)
    example_singleton_with_singleton = Singleton(
        ExampleSingleton, resource=async_resource_as_singleton
    )

    sync_resource = Resource(ExampleResource, val=3)
    example_singleton_with_sync_resource = Singleton(
        ExampleSingleton, resource=sync_resource
    )


async def case_1_no_overriding():
    container = Container()
    singleton = await container.example_singleton_with_async_resource.async_()

    assert singleton._resource._val == 1  # works as expected


async def case_2_use_kwarg_does_nothing():
    container = Container()
    manual_resource = ExampleResourceWithAsyncContext(val=20)
    container.example_singleton_with_async_resource.add_kwargs(resource=manual_resource)

    singleton = await container.example_singleton_with_async_resource.async_()

    assert singleton._resource._val != 20  # This is not what I expect
    assert singleton._resource._val == 1  # add_kwargs did nothing


async def case_3_use_singleton_instead_of_resource_works():
    container = Container()
    manual_resource = ExampleResourceWithAsyncContext(val=20)
    container.example_singleton_with_singleton.add_kwargs(resource=manual_resource)

    singleton = (
        container.example_singleton_with_singleton()
    )  # not allowed to call async_ because it isn't async

    assert singleton._resource._val == 20  # When the dep is a Singleton it works!


async def case_4_no_async_resource_add_kwargs_works():
    container = Container()
    manual_resource = ExampleResource(val=20)
    container.example_singleton_with_sync_resource.add_kwargs(resource=manual_resource)

    singleton = container.example_singleton_with_sync_resource()

    assert (
        singleton._resource._val == 20
    )  # When the dep is a Resource without async context handler it works!


async def main():
    await case_1_no_overriding()
    await case_2_use_kwarg_does_nothing()
    await case_3_use_singleton_instead_of_resource_works()
    await case_4_no_async_resource_add_kwargs_works()


if __name__ == "__main__":
    asyncio.run(main())

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions