Skip to content

Commit c42eb2a

Browse files
committed
[refactor] Extracted a context manager that sets a temporary event loop policy for the scope of the context.
Signed-off-by: Michael Seifert <[email protected]>
1 parent 77972a5 commit c42eb2a

File tree

1 file changed

+28
-30
lines changed

1 file changed

+28
-30
lines changed

pytest_asyncio/plugin.py

+28-30
Original file line numberDiff line numberDiff line change
@@ -590,21 +590,11 @@ def scoped_event_loop(
590590
event_loop_policy,
591591
) -> Iterator[asyncio.AbstractEventLoop]:
592592
new_loop_policy = event_loop_policy
593-
old_loop_policy = asyncio.get_event_loop_policy()
594-
old_loop = asyncio.get_event_loop()
595-
asyncio.set_event_loop_policy(new_loop_policy)
596-
loop = asyncio.new_event_loop()
597-
asyncio.set_event_loop(loop)
598-
yield loop
599-
loop.close()
600-
asyncio.set_event_loop_policy(old_loop_policy)
601-
# When a test uses both a scoped event loop and the event_loop fixture,
602-
# the "_provide_clean_event_loop" finalizer of the event_loop fixture
603-
# will already have installed a fresh event loop, in order to shield
604-
# subsequent tests from side-effects. We close this loop before restoring
605-
# the old loop to avoid ResourceWarnings.
606-
asyncio.get_event_loop().close()
607-
asyncio.set_event_loop(old_loop)
593+
with _temporary_event_loop_policy(new_loop_policy):
594+
loop = asyncio.new_event_loop()
595+
asyncio.set_event_loop(loop)
596+
yield loop
597+
loop.close()
608598

609599
# @pytest.fixture does not register the fixture anywhere, so pytest doesn't
610600
# know it exists. We work around this by attaching the fixture function to the
@@ -630,6 +620,24 @@ def _removesuffix(s: str, suffix: str) -> str:
630620
return s.removesuffix(suffix)
631621

632622

623+
@contextlib.contextmanager
624+
def _temporary_event_loop_policy(policy: AbstractEventLoopPolicy) -> Iterator[None]:
625+
old_loop_policy = asyncio.get_event_loop_policy()
626+
old_loop = asyncio.get_event_loop()
627+
asyncio.set_event_loop_policy(policy)
628+
try:
629+
yield
630+
finally:
631+
asyncio.set_event_loop_policy(old_loop_policy)
632+
# When a test uses both a scoped event loop and the event_loop fixture,
633+
# the "_provide_clean_event_loop" finalizer of the event_loop fixture
634+
# will already have installed a fresh event loop, in order to shield
635+
# subsequent tests from side-effects. We close this loop before restoring
636+
# the old loop to avoid ResourceWarnings.
637+
asyncio.get_event_loop().close()
638+
asyncio.set_event_loop(old_loop)
639+
640+
633641
def pytest_collection_modifyitems(
634642
session: Session, config: Config, items: List[Item]
635643
) -> None:
@@ -958,21 +966,11 @@ def _session_event_loop(
958966
request: FixtureRequest, event_loop_policy: AbstractEventLoopPolicy
959967
) -> Iterator[asyncio.AbstractEventLoop]:
960968
new_loop_policy = event_loop_policy
961-
old_loop_policy = asyncio.get_event_loop_policy()
962-
old_loop = asyncio.get_event_loop()
963-
asyncio.set_event_loop_policy(new_loop_policy)
964-
loop = asyncio.new_event_loop()
965-
asyncio.set_event_loop(loop)
966-
yield loop
967-
loop.close()
968-
asyncio.set_event_loop_policy(old_loop_policy)
969-
# When a test uses both a scoped event loop and the event_loop fixture,
970-
# the "_provide_clean_event_loop" finalizer of the event_loop fixture
971-
# will already have installed a fresh event loop, in order to shield
972-
# subsequent tests from side-effects. We close this loop before restoring
973-
# the old loop to avoid ResourceWarnings.
974-
asyncio.get_event_loop().close()
975-
asyncio.set_event_loop(old_loop)
969+
with _temporary_event_loop_policy(new_loop_policy):
970+
loop = asyncio.new_event_loop()
971+
asyncio.set_event_loop(loop)
972+
yield loop
973+
loop.close()
976974

977975

978976
@pytest.fixture(scope="session", autouse=True)

0 commit comments

Comments
 (0)