From c57eef5a5f40954fa5155d6029caa7670ed45143 Mon Sep 17 00:00:00 2001 From: Tim Pillinger <26465611+wxtim@users.noreply.github.com> Date: Mon, 4 Apr 2022 11:54:05 +0100 Subject: [PATCH 1/5] Ensure that fileinstall doesn't fail given the status of asyncio loop --- cylc/rose/entry_points.py | 9 ++- .../functional/14_reinstall_fileinstall/data | 5 ++ .../dev-8.x/flow.cylc | 23 ++++++ .../14_reinstall_fileinstall/flow.cylc | 28 +++++++ .../14_reinstall_fileinstall/rose-suite.conf | 5 ++ .../functional/test_reinstall_fileinstall.py | 79 +++++++++++++++++++ 6 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 tests/functional/14_reinstall_fileinstall/data create mode 100644 tests/functional/14_reinstall_fileinstall/dev-8.x/flow.cylc create mode 100644 tests/functional/14_reinstall_fileinstall/flow.cylc create mode 100644 tests/functional/14_reinstall_fileinstall/rose-suite.conf create mode 100644 tests/functional/test_reinstall_fileinstall.py diff --git a/cylc/rose/entry_points.py b/cylc/rose/entry_points.py index 4297e0d6..5bb0bba1 100644 --- a/cylc/rose/entry_points.py +++ b/cylc/rose/entry_points.py @@ -258,6 +258,7 @@ def rose_fileinstall(srcdir=None, opts=None, rundir=None): raise exc else: # Carry out imports. + import asyncio from metomi.rose.config_processor import ConfigProcessorsManager from metomi.rose.popen import RosePopener from metomi.rose.reporter import Reporter @@ -274,7 +275,13 @@ def rose_fileinstall(srcdir=None, opts=None, rundir=None): fs_util = FileSystemUtil(event_handler) popen = RosePopener(event_handler) - # Process files + # Get an Asyncio loop if one doesn't exist: + try: + asyncio.get_event_loop() + except RuntimeError: + asyncio.set_event_loop(asyncio.new_event_loop()) + + # Process fileinstall. config_pm = ConfigProcessorsManager(event_handler, popen, fs_util) config_pm(config_tree, "file") finally: diff --git a/tests/functional/14_reinstall_fileinstall/data b/tests/functional/14_reinstall_fileinstall/data new file mode 100644 index 00000000..5e501c7b --- /dev/null +++ b/tests/functional/14_reinstall_fileinstall/data @@ -0,0 +1,5 @@ +Hello World +Bore Da +Myttin Da +Bon Jour +Guten Tag \ No newline at end of file diff --git a/tests/functional/14_reinstall_fileinstall/dev-8.x/flow.cylc b/tests/functional/14_reinstall_fileinstall/dev-8.x/flow.cylc new file mode 100644 index 00000000..1edec620 --- /dev/null +++ b/tests/functional/14_reinstall_fileinstall/dev-8.x/flow.cylc @@ -0,0 +1,23 @@ +[meta] +title = "Boilerplate" +description = """ +This workflow is designed to stop me having to +write a pile of boilerplate from scratch. +""" +written for cylc version = 8.x + +[scheduler] + allow implicit tasks = true + +[scheduling] + initial cycle point = 1066 + # final cycle point = 1067 + [[dependencies]] + P1Y = foo + +[runtime] + [[root]] + script = """ + echo $HOSTNAME + env + """ diff --git a/tests/functional/14_reinstall_fileinstall/flow.cylc b/tests/functional/14_reinstall_fileinstall/flow.cylc new file mode 100644 index 00000000..62becba0 --- /dev/null +++ b/tests/functional/14_reinstall_fileinstall/flow.cylc @@ -0,0 +1,28 @@ +#!jinja2 +[meta] +title = "%(workflow)" +description = """ +This workflow is designed to stop me having to +write a pile of boilerplate from scratch. +""" +written for cylc version = 8.x + + + +[scheduler] + allow implicit tasks = true + + +[scheduling] + cycling mode = integer + initial cycle point = 1066 + final cycle point = 1066 + [[dependencies]] + P1 = foo + +[runtime] + [[root]] + script = """ + echo $HOSTNAME + env + """ diff --git a/tests/functional/14_reinstall_fileinstall/rose-suite.conf b/tests/functional/14_reinstall_fileinstall/rose-suite.conf new file mode 100644 index 00000000..31285256 --- /dev/null +++ b/tests/functional/14_reinstall_fileinstall/rose-suite.conf @@ -0,0 +1,5 @@ +[template variables] +foo=42 + +[file:data] +source=data \ No newline at end of file diff --git a/tests/functional/test_reinstall_fileinstall.py b/tests/functional/test_reinstall_fileinstall.py new file mode 100644 index 00000000..5a6d4bcf --- /dev/null +++ b/tests/functional/test_reinstall_fileinstall.py @@ -0,0 +1,79 @@ +# THIS FILE IS PART OF THE ROSE-CYLC PLUGIN FOR THE CYLC WORKFLOW ENGINE. +# Copyright (C) NIWA & British Crown (Met Office) & Contributors. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""Cylc reinstall is able to use the async fileinstall from rose without +trouble. +""" + +import os +import pytest +import shutil +import subprocess + +from pathlib import Path +from uuid import uuid4 + +from cylc.flow.pathutil import get_workflow_run_dir + + +WORKFLOW_SRC = Path(__file__).parent / '14_reinstall_fileinstall' + + +@pytest.fixture(scope='module') +def fixture_provide_flow(tmp_path_factory): + """Provide a cylc workflow based on the contents of a folder which can + be either validated or installed. + """ + test_flow_name = f'cylc-rose-test-{str(uuid4())[:8]}' + srcpath = (tmp_path_factory.getbasetemp() / test_flow_name) + flowpath = Path(get_workflow_run_dir(test_flow_name)) + shutil.copytree(WORKFLOW_SRC, srcpath) + (srcpath / 'opt').mkdir(exist_ok=True) + yield { + 'test_flow_name': test_flow_name, + 'flowpath': flowpath, + 'srcpath': srcpath + } + shutil.rmtree(srcpath) + shutil.rmtree(flowpath) + + +def test_install_flow(fixture_provide_flow): + """Run ``cylc install``. + """ + result = subprocess.run( + [ + 'cylc', 'install', + '--flow-name', fixture_provide_flow['test_flow_name'], + '-C', str(fixture_provide_flow['srcpath']) + ], + capture_output=True, + env=os.environ + ) + assert result.returncode == 0 + + +def test_reinstall_flow(fixture_provide_flow): + """Run ``cylc reinstall``. + """ + result = subprocess.run( + [ + 'cylc', 'reinstall', + fixture_provide_flow['test_flow_name'], + ], + capture_output=True, + env=os.environ + ) + assert result.returncode == 0 From b3af13fabd6088f1701bf97c60217b9427adcc2d Mon Sep 17 00:00:00 2001 From: Tim Pillinger <26465611+wxtim@users.noreply.github.com> Date: Mon, 4 Apr 2022 12:26:33 +0100 Subject: [PATCH 2/5] update changelog --- CHANGES.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 65fdfe7f..04137f09 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,13 @@ # Selected Cylc-Rose Changes +## __cylc-rose-1.0.3 ()__ + +### Fixes + +[130](https://github.com/cylc/cylc-rose/pull/130) - Fix bug preventing +``cylc reinstall`` using Rose fileinstall. + + ## __cylc-rose-1.0.2 (Released 2022-03-24)__ ### Fixes From e0d97921b0f834f36b1bf05cab21169b9082f812 Mon Sep 17 00:00:00 2001 From: Tim Pillinger <26465611+wxtim@users.noreply.github.com> Date: Mon, 4 Apr 2022 14:04:47 +0100 Subject: [PATCH 3/5] Update cylc/rose/entry_points.py Co-authored-by: Oliver Sanders --- cylc/rose/entry_points.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cylc/rose/entry_points.py b/cylc/rose/entry_points.py index 5bb0bba1..66511215 100644 --- a/cylc/rose/entry_points.py +++ b/cylc/rose/entry_points.py @@ -276,6 +276,9 @@ def rose_fileinstall(srcdir=None, opts=None, rundir=None): popen = RosePopener(event_handler) # Get an Asyncio loop if one doesn't exist: + # Rose may need an event loop to invoke async interfaces, + # doing this here incase we want to go async in cylc-rose. + # See https://github.com/cylc/cylc-rose/pull/130/files try: asyncio.get_event_loop() except RuntimeError: From 9392b79a59fb2376378d1dfe466b1c6aba86b391 Mon Sep 17 00:00:00 2001 From: Tim Pillinger <26465611+wxtim@users.noreply.github.com> Date: Mon, 4 Apr 2022 15:50:04 +0100 Subject: [PATCH 4/5] flake8 --- tests/test_config_node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_config_node.py b/tests/test_config_node.py index e95a70cf..f7f4d342 100644 --- a/tests/test_config_node.py +++ b/tests/test_config_node.py @@ -151,7 +151,7 @@ def test_add_cylc_install_to_rose_conf_node_opts(rose_conf, cli_conf, expect): expect_opt = '' if 'opts' in cli_conf: - expect_opt = cli_conf['opts'] + expect_opt = cli_conf.get('opts') expect_opt += ' (cylc-install)' assert result.comments == [( From 4a0093e0773e8e2e19098f7bfe360dd9129e0110 Mon Sep 17 00:00:00 2001 From: Tim Pillinger <26465611+wxtim@users.noreply.github.com> Date: Tue, 5 Apr 2022 07:15:44 +0100 Subject: [PATCH 5/5] Response to review - Properly fixed a flake8 fail - Added new lines at end of files. --- tests/functional/14_reinstall_fileinstall/data | 2 +- tests/functional/14_reinstall_fileinstall/rose-suite.conf | 2 +- tests/test_config_node.py | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/functional/14_reinstall_fileinstall/data b/tests/functional/14_reinstall_fileinstall/data index 5e501c7b..6e17a24b 100644 --- a/tests/functional/14_reinstall_fileinstall/data +++ b/tests/functional/14_reinstall_fileinstall/data @@ -2,4 +2,4 @@ Hello World Bore Da Myttin Da Bon Jour -Guten Tag \ No newline at end of file +Guten Tag diff --git a/tests/functional/14_reinstall_fileinstall/rose-suite.conf b/tests/functional/14_reinstall_fileinstall/rose-suite.conf index 31285256..cb354f49 100644 --- a/tests/functional/14_reinstall_fileinstall/rose-suite.conf +++ b/tests/functional/14_reinstall_fileinstall/rose-suite.conf @@ -2,4 +2,4 @@ foo=42 [file:data] -source=data \ No newline at end of file +source=data diff --git a/tests/test_config_node.py b/tests/test_config_node.py index f7f4d342..a07d7ff8 100644 --- a/tests/test_config_node.py +++ b/tests/test_config_node.py @@ -149,9 +149,7 @@ def test_add_cylc_install_to_rose_conf_node_opts(rose_conf, cli_conf, expect): assert result.value == expect - expect_opt = '' - if 'opts' in cli_conf: - expect_opt = cli_conf.get('opts') + expect_opt = cli_conf.get('opts', '') expect_opt += ' (cylc-install)' assert result.comments == [(