Skip to content

Commit

Permalink
Fix issue pytest-dev#112: 'Dynamically calling a fixture causes a run…
Browse files Browse the repository at this point in the history
…time error' by failing over to a ThreadPoolExecutor in cases where the expected event loop is already running. Notably this happens when calling because it dynamically calls a fixture that needs to be setup on an event loop that's already running pytest async tests
  • Loading branch information
ykuzma1 committed Apr 20, 2019
1 parent 813423d commit 9094b19
Showing 1 changed file with 21 additions and 2 deletions.
23 changes: 21 additions & 2 deletions pytest_asyncio/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,25 @@ def pytest_pycollect_makeitem(collector, name, obj):
@pytest.hookimpl(hookwrapper=True)
def pytest_fixture_setup(fixturedef, request):
"""Adjust the event loop policy when an event loop is produced."""

def run_until_complete(loop, coro):
"""
Fail over to a ThreadPoolExecutor in case the event loop is already
running. Particularly, this occurs when calling a dynamic fixture
using `request.getfixturevalue(argname)`
"""

try:
return loop.run_until_complete(coro)
except RuntimeError:
with concurrent.futures.ThreadPoolExecutor(1) as pool:
loop = asyncio.new_event_loop()
try:
pool.submit(asyncio.set_event_loop, loop).result()
return pool.submit(loop.run_until_complete, coro).result()
finally:
loop.close()

if isasyncgenfunction(fixturedef.func):
# This is an async generator function. Wrap it accordingly.
f = fixturedef.func
Expand Down Expand Up @@ -94,7 +113,7 @@ async def async_finalizer():

request.addfinalizer(finalizer)

return loop.run_until_complete(setup())
return run_until_complete(loop, setup())

fixturedef.func = wrapper

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

return loop.run_until_complete(setup())
return run_until_complete(loop, setup())

fixturedef.func = wrapper

Expand Down

0 comments on commit 9094b19

Please sign in to comment.