Description
In #50, we started using a gross hack to make it so within each test invocation, all fixtures + the test itself all shared a single contextvars.Context
. This simulates them all running in a single task (except that some can happen concurrently, see #57).
Is this the optimal behavior? I guess the options are:
- Use a single
Context
for all fixtures - Use separate
Context
s for different fixtures, but when a fixture starts up copy in the values from the previous fixture. (Doing this with concurrent setup/teardown is pretty complicated; doing it with sequential setup/teardown would be easy.)
The difference is in code like:
mycv = contextvars.ContextVar("mycv")
@trio_fixture
def fix():
mycv.set("a")
yield
assert mycv.get() == "a"
@pytest.mark.trio
async def test(fix):
mycv.set("b")
Right now, the assert
fails, because the fixture can "see" the set
call in test
, because they share a Context
. If we used separate contexts with copy-on-startup, then fix
would not be able to see changes made by downstream fixtures. You can think of it as arranging for ContextVar
changes to be automatically rolled back during the teardown process. This is conceptually attractive, but I don't know if it matters, or is even beneficial, in practice.
Also, even if we keep the current semantics, we should find a way to stop doing the gross hack that we're doing right now. This might mean enhancing trio, e.g. by adding a context=
argument to nursery.start_soon
.