Skip to content

It's very annoying that fixtures can't yield inside a nursery/cancel scope #55

@njsmith

Description

@njsmith

Right now, writing code like this is broken:

@pytest.fixture
async def background_task_fixture():
    async with trio.open_nursery() as nursery:
        await nursery.start(...)
        yield
        nursery.cancel_scope.cancel()

The problem is that the cancel scope semantics assume that they're strictly nested and can "see" all exceptions that happen inside them, but the convention for pytest fixtures is that we never throw in any exceptions. Also, right now we setup and teardown fixtures in a strict sequential order, but it might be nice to someday do that concurrently, and if we do then this example would really explode (you'll get assertion errors inside trio/_core/_run.py). (Previous discussion: #25 (comment))

For this particular case, that's not a big deal – you can write it as

@pytest.fixture
async def background_task_fixture(test_nursery):
    await test_nursery.start(...)

and that's actually better than the original.

But, as @touilleMan points out, there are other cases where this is really quite a problem. Specifically, cases where the use of a nursery is abstracted away inside some other context manager. For example, consider these two fixtures:

@pytest.fixture
async def tcp_client():
    async with await open_tcp_stream(...) as stream:
        yield stream

@pytest.fixture
async def websocket_client():
    async with open_websocket(...) as websocket:
        yield websocket

The first one is fine; the second one uses a nursery internally, so it's broken. But to realize that, we have to know what's going on internally in some random third-party library, and that's pretty terrible. So... what can we do to make this better?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions