Skip to content

Commit 3ddb7f5

Browse files
committed
Fix issue pytest-dev#112: 'Dynamically calling a fixture causes a runtime error' by failing over to a ThreadPoolExecutor in cases where the expected event loop is already running. Notably this happens when calling 'request.getfixturevalue(argname)' because it dynamically calls a fixture that needs to be setup on an event loop that's already running pytest async tests
1 parent 813423d commit 3ddb7f5

File tree

1 file changed

+21
-2
lines changed

1 file changed

+21
-2
lines changed

Diff for: pytest_asyncio/plugin.py

+21-2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,25 @@ def pytest_pycollect_makeitem(collector, name, obj):
5151
@pytest.hookimpl(hookwrapper=True)
5252
def pytest_fixture_setup(fixturedef, request):
5353
"""Adjust the event loop policy when an event loop is produced."""
54+
55+
def run_until_complete(loop, coro):
56+
"""
57+
Fail over to a ThreadPoolExecutor in case the event loop is already
58+
running. Particularly, this occurs when calling a dynamic fixture
59+
using `request.getfixturevalue(argname)`
60+
"""
61+
62+
try:
63+
return loop.run_until_complete(coro)
64+
except RuntimeError:
65+
with concurrent.futures.ThreadPoolExecutor(1) as pool:
66+
loop = asyncio.new_event_loop()
67+
try:
68+
pool.submit(asyncio.set_event_loop, loop).result()
69+
return pool.submit(loop.run_until_complete, coro).result()
70+
finally:
71+
loop.close()
72+
5473
if isasyncgenfunction(fixturedef.func):
5574
# This is an async generator function. Wrap it accordingly.
5675
f = fixturedef.func
@@ -94,7 +113,7 @@ async def async_finalizer():
94113

95114
request.addfinalizer(finalizer)
96115

97-
return loop.run_until_complete(setup())
116+
return run_until_complete(loop, setup())
98117

99118
fixturedef.func = wrapper
100119

@@ -116,7 +135,7 @@ async def setup():
116135
res = await f(*args, **kwargs)
117136
return res
118137

119-
return loop.run_until_complete(setup())
138+
return run_until_complete(loop, setup())
120139

121140
fixturedef.func = wrapper
122141

0 commit comments

Comments
 (0)