Skip to content

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

Closed
@jonaslalin

Description

@jonaslalin

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())

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions