{"action":"closed","issue":{"url":"https://api.github.com/repos/python-trio/pytest-trio/issues/55","repository_url":"https://api.github.com/repos/python-trio/pytest-trio","labels_url":"https://api.github.com/repos/python-trio/pytest-trio/issues/55/labels{/name}","comments_url":"https://api.github.com/repos/python-trio/pytest-trio/issues/55/comments","events_url":"https://api.github.com/repos/python-trio/pytest-trio/issues/55/events","html_url":"https://github.com/python-trio/pytest-trio/issues/55","id":344276156,"node_id":"MDU6SXNzdWUzNDQyNzYxNTY=","number":55,"title":"It's very annoying that fixtures can't yield inside a nursery/cancel scope","user":{"login":"njsmith","id":609896,"node_id":"MDQ6VXNlcjYwOTg5Ng==","avatar_url":"https://avatars0.githubusercontent.com/u/609896?v=4","gravatar_id":"","url":"https://api.github.com/users/njsmith","html_url":"https://github.com/njsmith","followers_url":"https://api.github.com/users/njsmith/followers","following_url":"https://api.github.com/users/njsmith/following{/other_user}","gists_url":"https://api.github.com/users/njsmith/gists{/gist_id}","starred_url":"https://api.github.com/users/njsmith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/njsmith/subscriptions","organizations_url":"https://api.github.com/users/njsmith/orgs","repos_url":"https://api.github.com/users/njsmith/repos","events_url":"https://api.github.com/users/njsmith/events{/privacy}","received_events_url":"https://api.github.com/users/njsmith/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":3,"created_at":"2018-07-25T03:11:54Z","updated_at":"2018-08-24T11:44:16Z","closed_at":"2018-08-24T11:44:16Z","author_association":"MEMBER","body":"Right now, writing code like this is broken:\r\n\r\n```python\r\n@pytest.fixture\r\nasync def background_task_fixture():\r\n    async with trio.open_nursery() as nursery:\r\n        await nursery.start(...)\r\n        yield\r\n        nursery.cancel_scope.cancel()\r\n```\r\n\r\nThe 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: https://github.com/python-trio/pytest-trio/issues/25#issuecomment-352990630)\r\n\r\nFor this particular case, that's not a big deal – you can write it as \r\n\r\n```python\r\n@pytest.fixture\r\nasync def background_task_fixture(test_nursery):\r\n    await test_nursery.start(...)\r\n```\r\n\r\nand that's actually better than the original.\r\n\r\nBut, as @touilleMan [points out](https://github.com/python-trio/pytest-trio/pull/47#discussion_r204700827), 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:\r\n\r\n```python\r\n@pytest.fixture\r\nasync def tcp_client():\r\n    async with await open_tcp_stream(...) as stream:\r\n        yield stream\r\n\r\n@pytest.fixture\r\nasync def websocket_client():\r\n    async with open_websocket(...) as websocket:\r\n        yield websocket\r\n```\r\n\r\nThe 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?"}}
{"actor":{"display_login":"njsmith"}}