@@ -590,21 +590,11 @@ def scoped_event_loop(
590
590
event_loop_policy ,
591
591
) -> Iterator [asyncio .AbstractEventLoop ]:
592
592
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 ()
608
598
609
599
# @pytest.fixture does not register the fixture anywhere, so pytest doesn't
610
600
# 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:
630
620
return s .removesuffix (suffix )
631
621
632
622
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
+
633
641
def pytest_collection_modifyitems (
634
642
session : Session , config : Config , items : List [Item ]
635
643
) -> None :
@@ -958,21 +966,11 @@ def _session_event_loop(
958
966
request : FixtureRequest , event_loop_policy : AbstractEventLoopPolicy
959
967
) -> Iterator [asyncio .AbstractEventLoop ]:
960
968
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 ()
976
974
977
975
978
976
@pytest .fixture (scope = "session" , autouse = True )
0 commit comments