3030)
3131
3232import pytest
33+ import pytest_asyncio
3334
3435from cylc .flow .config import WorkflowConfig
3536from cylc .flow .id import Tokens
@@ -112,15 +113,15 @@ def _pytest_passed(request: pytest.FixtureRequest) -> bool:
112113 ))
113114
114115
115- @pytest .fixture (scope = 'session' )
116+ @pytest_asyncio .fixture (scope = 'session' )
116117def run_dir ():
117118 """The cylc run directory for this host."""
118119 path = Path (get_cylc_run_dir ())
119120 path .mkdir (exist_ok = True )
120121 yield path
121122
122123
123- @pytest .fixture (scope = 'session' )
124+ @pytest_asyncio .fixture (scope = 'session' )
124125def ses_test_dir (request , run_dir ):
125126 """The root run dir for test flows in this test session."""
126127 timestamp = get_current_time_string (use_basic_format = True )
@@ -131,7 +132,7 @@ def ses_test_dir(request, run_dir):
131132 _rm_if_empty (path )
132133
133134
134- @pytest .fixture (scope = 'module' )
135+ @pytest_asyncio .fixture (scope = 'module' )
135136def mod_test_dir (request , ses_test_dir ):
136137 """The root run dir for test flows in this test module."""
137138 path = Path (
@@ -163,7 +164,7 @@ def test_dir(request, mod_test_dir):
163164 _rm_if_empty (path )
164165
165166
166- @pytest .fixture (scope = 'module' )
167+ @pytest_asyncio .fixture (scope = 'module' )
167168def mod_flow (run_dir , mod_test_dir ):
168169 """A function for creating module-level flows."""
169170 yield partial (_make_flow , run_dir , mod_test_dir )
@@ -175,7 +176,7 @@ def flow(run_dir, test_dir):
175176 yield partial (_make_flow , run_dir , test_dir )
176177
177178
178- @pytest .fixture (scope = 'module' )
179+ @pytest_asyncio .fixture (scope = 'module' )
179180def mod_scheduler ():
180181 """Return a Scheduler object for a flow.
181182
@@ -197,7 +198,7 @@ def scheduler():
197198 yield _scheduler
198199
199200
200- @pytest .fixture (scope = 'module' )
201+ @pytest_asyncio .fixture (scope = 'module' )
201202def mod_start ():
202203 """Start a scheduler but don't set it running (module scope)."""
203204 return partial (_start_flow , None )
@@ -209,7 +210,7 @@ def start(caplog: pytest.LogCaptureFixture):
209210 return partial (_start_flow , caplog )
210211
211212
212- @pytest .fixture (scope = 'module' )
213+ @pytest_asyncio .fixture (scope = 'module' )
213214def mod_run ():
214215 """Start a scheduler and set it running (module scope)."""
215216 return partial (_run_flow , None )
@@ -235,7 +236,7 @@ def one_conf():
235236 }
236237
237238
238- @pytest .fixture (scope = 'module' )
239+ @pytest_asyncio .fixture (scope = 'module' )
239240def mod_one_conf ():
240241 return {
241242 'scheduler' : {
@@ -257,36 +258,37 @@ def one(one_conf, flow, scheduler):
257258 return schd
258259
259260
260- @pytest .fixture (scope = 'module' )
261+ @pytest_asyncio .fixture (scope = 'module' )
261262def mod_one (mod_one_conf , mod_flow , mod_scheduler ):
262263 id_ = mod_flow (mod_one_conf )
263264 schd = mod_scheduler (id_ )
264265 return schd
265266
266267
267- @pytest .fixture (scope = 'module' )
268- def event_loop ():
269- """This fixture defines the event loop used for each test.
270-
271- The default scoping for this fixture is "function" which means that all
272- async fixtures must have "function" scoping.
273-
274- Defining `event_loop` as a module scoped fixture opens the door to
275- module scoped fixtures but means all tests in a module will run in the same
276- event loop. This is fine, it's actually an efficiency win but also
277- something to be aware of.
278-
279- See: https://github.com/pytest-dev/pytest-asyncio/issues/171
280-
281- """
282- loop = asyncio .get_event_loop_policy ().new_event_loop ()
283- yield loop
284- # gracefully exit async generators
285- loop .run_until_complete (loop .shutdown_asyncgens ())
286- # cancel any tasks still running in this event loop
287- for task in asyncio .all_tasks (loop ):
288- task .cancel ()
289- loop .close ()
268+ if pytest_asyncio .__version__ .startswith ('0.21' ):
269+ # BACK COMPAT: event_loop
270+ # FROM: python 3
271+ # TO: python 3.7
272+ # URL: https://github.com/cylc/cylc-flow/pull/6726
273+ @pytest_asyncio .fixture (scope = 'module' )
274+ def event_loop ():
275+ """This fixture defines the event loop used for each test.
276+ The default scoping for this fixture is "function" which means that all
277+ async fixtures must have "function" scoping.
278+ Defining `event_loop` as a module scoped fixture opens the door to
279+ module scoped fixtures but means all tests in a module will run in the
280+ same event loop. This is fine, it's actually an efficiency win but also
281+ something to be aware of.
282+ See: https://github.com/pytest-dev/pytest-asyncio/issues/171
283+ """
284+ loop = asyncio .get_event_loop_policy ().new_event_loop ()
285+ yield loop
286+ # gracefully exit async generators
287+ loop .run_until_complete (loop .shutdown_asyncgens ())
288+ # cancel any tasks still running in this event loop
289+ for task in asyncio .all_tasks (loop ):
290+ task .cancel ()
291+ loop .close ()
290292
291293
292294@pytest .fixture
@@ -382,7 +384,7 @@ def _validate(id_: Union[str, Path], **kwargs) -> WorkflowConfig:
382384 return _validate
383385
384386
385- @pytest .fixture (scope = 'module' )
387+ @pytest_asyncio .fixture (scope = 'module' )
386388def mod_validate (run_dir ):
387389 """Provides a function for validating workflow configurations.
388390
@@ -465,7 +467,7 @@ def run_job_cmd(
465467 return _disable_polling
466468
467469
468- @pytest .fixture (scope = 'module' )
470+ @pytest_asyncio .fixture (scope = 'module' )
469471def mod_workflow_source (mod_flow , tmp_path_factory ):
470472 """Create a workflow source directory.
471473
@@ -686,7 +688,7 @@ def complete():
686688 return _complete
687689
688690
689- @pytest .fixture (scope = 'module' )
691+ @pytest_asyncio .fixture (scope = 'module' )
690692def mod_complete ():
691693 return _complete
692694
0 commit comments