Skip to content

Commit

Permalink
Merge pull request #184 from cylc/1.1.x
Browse files Browse the repository at this point in the history
1.1.x
  • Loading branch information
MetRonnie authored Sep 14, 2022
2 parents db381f5 + 0a13dde commit 7121019
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 43 deletions.
2 changes: 1 addition & 1 deletion cylc/rose/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,4 @@
"""

__version__ = '1.1.1.dev'
__version__ = '1.1.1'
118 changes: 90 additions & 28 deletions cylc/rose/stem.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,54 @@
To run a rose-stem suite use "cylc play".
Looks for a suite to install either in $PWD/rose-stem, or in a specified
location - e.g:
# Install a rose-stem suite from PWD/rose-stem
$ rose stem
# Install a rose-stem suite from PWD/relative-path.
$ rose stem relative-path
# Install a rose-stem suite from specified abs path.
$ rose stem /absolute/path
Install a suitable suite with a specified set of source tree(s).
Default values of some of these settings are suite-dependent, specified
in the `rose-suite.conf` file.
Examples
rose stem --group=developer
rose stem --source=/path/to/source --source=/other/source --group=mygroup
rose stem --source=foo=/path/to/source --source=bar=fcm:bar_tr@head
Jinja2 Variables
Note that `<project>` refers to the FCM keyword name of the repository in
upper case.
HOST_SOURCE_<project>
The complete list of source trees for a given project. Working copies
in this list have their hostname prefixed, e.g. `host:/path/wc`.
HOST_SOURCE_<project>_BASE
The base of the project specified on the command line. This is
intended to specify the location of `fcm-make` config files. Working
copies in this list have their hostname prefixed.
RUN_NAMES
A list of groups to run in the rose-stem suite.
SOURCE_<project>
The complete list of source trees for a given project. Unlike the
`HOST_` variable of similar name, paths to working copies do NOT
include the host name.
SOURCE_<project>_BASE
The base of the project specified on the command line. This is
intended to specify the location of `fcm-make` config files. Unlike
the `HOST_` variable of similar name, paths to working copies do NOT
include the host name.
SOURCE_<project>_REV
The revision of the project specified on the command line. This
is intended to specify the revision of `fcm-make` config files.
"""

from ansimarkup import parse as cparse
from contextlib import suppress
from optparse import OptionGroup
import os
from pathlib import Path
import re
import sys

from cylc.flow.exceptions import CylcError
from cylc.flow.scripts.install import (
get_option_parser,
install as cylc_install
Expand All @@ -55,6 +84,7 @@
from metomi.rose.resource import ResourceLocator


EXC_EXIT = cparse('<red><bold>{name}: </bold>{exc}</red>')
DEFAULT_TEST_DIR = 'rose-stem'
ROSE_STEM_VERSION = 1
SUITE_RC_PREFIX = '[jinja2:suite.rc]'
Expand Down Expand Up @@ -96,7 +126,7 @@ def __repr__(self):
__str__ = __repr__


class ProjectNotFoundException(Exception):
class ProjectNotFoundException(CylcError):

"""Exception class when unable to determine project a source belongs to."""

Expand Down Expand Up @@ -482,6 +512,7 @@ def get_source_opt_from_args(opts, args):
"""
if len(args) == 0:
# sourcedir not given:
opts.source = None
return opts
elif os.path.isabs(args[-1]):
# sourcedir given, and is abspath:
Expand All @@ -501,38 +532,69 @@ def main():
# TODO: add any rose stem specific CLI args that might exist
# On inspection of rose/lib/python/rose/opt_parse.py it turns out that
# opts.group is stored by the --task option.
parser.add_option(
"--task", "--group",
help="Specifies a source tree to include in a suite.",
rose_stem_options = OptionGroup(parser, 'Rose Stem Specific Options')
rose_stem_options.add_option(
"--task", "--group", "-t", "-g",
help=(
"Specify a group name to run. Additional groups can be specified"
"with further `--group` arguments. The suite will then convert the"
"groups into a series of tasks to run."
),
action="append",
metavar="PATH/TO/FLOW",
default=[],
dest="stem_groups")
parser.add_option(
"--source",
help="Specifies a source tree to include in a suite.",
rose_stem_options.add_option(
"--source", '-s',
help=(
"Specify a source tree to include in a rose-stem suite. The first"
"source tree must be a working copy as the location of the suite"
"and fcm-make config files are taken from it. Further source"
"trees can be added with additional `--source` arguments. "
"The project which is associated with a given source is normally "
"automatically determined using FCM, however the project can "
"be specified by putting the project name as the first part of "
"this argument separated by an equals sign as in the third "
"example above. Defaults to `.` if not specified."
),
action="append",
metavar="PATH/TO/FLOW",
default=[],
dest="stem_sources")

# Hard-set for now, but could be set based upon cylc verbosity levels?
parser.add_option('--verbosity', default=1)
parser.add_option('--quietness', default=0)
parser.add_option_group(rose_stem_options)

parser.usage = __doc__

opts, args = parser.parse_args(sys.argv[1:])
# sliced sys.argv to drop 'rose-stem'
opts = get_source_opt_from_args(opts, args)

# modify the CLI options to add whatever rose stem would like to add
opts = StemRunner(opts).process()
# Verbosity is set using the Cylc options which decrement and increment
# verbosity as part of the parser, but rose needs opts.quietness too, so
# hard set it.
opts.quietness = 0

# call cylc install
if hasattr(opts, 'source'):
cylc_install(parser, opts, opts.source)
else:
cylc_install(parser, opts)
try:
# modify the CLI options to add whatever rose stem would like to add
opts = StemRunner(opts).process()

# call cylc install
if hasattr(opts, 'source'):
cylc_install(parser, opts, opts.source)
else:
cylc_install(parser, opts)

except CylcError as exc:
if opts.verbosity > 1:
raise exc
print(
EXC_EXIT.format(
name=exc.__class__.__name__,
exc=exc
),
file=sys.stderr
)


if __name__ == "__main__":
Expand Down
14 changes: 9 additions & 5 deletions tests/functional/test_rose_stem.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
Tests for cylc.rose.stem
========================
These tests are based on the Rose 2019 tests for Rose Stem.
Structure
---------
Expand Down Expand Up @@ -173,7 +175,10 @@ def setup_stem_repo(tmp_path_factory, monkeymodule, request):
'suite_install_dir': suite_install_dir
}
# Only clean up if all went well.
if not request.session.testsfailed:
if (
not request.session.testsfailed
and Path(suite_install_dir).exists()
):
shutil.rmtree(suite_install_dir)


Expand Down Expand Up @@ -613,7 +618,6 @@ class TestProjectNotInKeywords:
def test_project_not_in_keywords(self, project_not_in_keywords):
"""test for successful execution with site/user configuration
"""
assert project_not_in_keywords.returncode == 1
assert (b'Cannot ascertain project for source tree' in
project_not_in_keywords.stderr
)
assert project_not_in_keywords.returncode == 0
stderr = project_not_in_keywords.stderr.decode()
assert 'Cannot ascertain project for source tree' in stderr
15 changes: 6 additions & 9 deletions tests/unit/test_rose_stem_units.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
[
pytest.param(
[],
'',
None,
id='no-path'
),
pytest.param(
Expand All @@ -43,17 +43,14 @@
]
)
def test_get_source_opt_from_args(tmp_path, monkeypatch, args, expect):
# Basic setup
"""It converts Rose 2 CLI features to options usable by Rose Stem
"""
monkeypatch.chdir(tmp_path)
opts = SimpleNamespace()

# Run function
result = get_source_opt_from_args(opts, args)
result = get_source_opt_from_args(opts, args).source

# If an arg is given we are expecting source to be added to the options.
# Otherwise options should be returned unchanged.
if expect:
expect = SimpleNamespace(source=expect.format(tmp_path=tmp_path))
if expect is None:
assert result == expect
else:
assert result == opts
assert result == expect.format(tmp_path=str(tmp_path))

0 comments on commit 7121019

Please sign in to comment.