Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Singleton provider throws RuntimeError: Task got bad yield for generators #795

Open
jonaslalin opened this issue Apr 22, 2024 · 1 comment

Comments

@jonaslalin
Copy link

jonaslalin commented Apr 22, 2024

When a generator is provided by Factory, I can inject my dependency synchronously, and example_1 below works as expected. When a generator is provided by Singleton, I experience forced asynchronous behavior (why do I get that?) and encounter a bad yield exception (see example_2 below).

Does anyone know why this happens and how I can fix it?

System:

Python 3.9.16
dependency-injector 4.41.0

Exception:

Traceback (most recent call last):
  File "issue.py", line 37, in <module>
    asyncio.run(example_2())
  File "/usr/lib64/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib64/python3.9/asyncio/base_events.py", line 647, in run_until_complete
    return future.result()
  File ".venv/lib64/python3.9/site-packages/dependency_injector/wiring.py", line 994, in _patched
    return await _async_inject(
  File "src/dependency_injector/_cwiring.pyx", line 62, in _async_inject
  File "src/dependency_injector/providers.pyx", line 2986, in dependency_injector.providers.BaseSingleton._async_init_instance
  File "issue.py", line 8, in generator_factory
    yield 1
RuntimeError: Task got bad yield: 1

Program (issue.py):

import asyncio
from typing import AsyncIterator, Iterator

from dependency_injector import containers, providers, wiring


def generator_factory() -> Iterator[int]:
    yield 1
    yield 2
    yield 3
    yield 4
    yield 5


class Container(containers.DeclarativeContainer):
    generator_1 = providers.Factory(generator_factory)
    generator_2 = providers.Singleton(generator_factory)


@wiring.inject
def example_1(generator_1: Iterator[int] = wiring.Provide[Container.generator_1]) -> None:
    for i in generator_1:
        print(i)


@wiring.inject
async def example_2(generator_2: AsyncIterator[int] = wiring.Provide[Container.generator_2]) -> None:
    async for i in generator_2:
        print(i)


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

    example_1()
    asyncio.run(example_2())
@nightblure
Copy link

nightblure commented Nov 13, 2024

@jonaslalin hi!

it works if you declare generator_factory with async :

async def generator_factory() -> Iterator[int]:
    ...

but example_1 will break because it is synchronous

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants