diff --git a/cylc/flow/scripts/cylc.py b/cylc/flow/scripts/cylc.py index 2dd56e9eacf..895af3aaf38 100644 --- a/cylc/flow/scripts/cylc.py +++ b/cylc/flow/scripts/cylc.py @@ -268,7 +268,7 @@ def get_version(long=False): 'start': 'cylc start & cylc restart have been replaced by cylc play', 'set-verbosity': - 'cylc set-verbosity has been replaced by cylc log-level', + 'cylc set-verbosity has been replaced by cylc verbosity', 'warranty': 'cylc warranty has been replaced by cylc help license', } diff --git a/cylc/flow/scripts/set.py b/cylc/flow/scripts/set.py index e8d4466199d..346f857c8af 100755 --- a/cylc/flow/scripts/set.py +++ b/cylc/flow/scripts/set.py @@ -59,12 +59,12 @@ FULL_ID_MULTI_ARG_DOC, CylcOptionParser as COP, ) +from cylc.flow.id import Tokens from cylc.flow.terminal import cli_function from cylc.flow.flow_mgr import ( add_flow_opts, validate_flow_opts ) -from cylc.flow.task_pool import REC_CLI_PREREQ MUTATION = ''' @@ -126,6 +126,29 @@ def get_option_parser() -> COP: return parser +def validate_prereq(prereq: str) -> bool: + """Return True prereq string is valid, else False. + + Examples: + Good prerequisite: + >>> validate_prereq('1/foo:succeeded') + True + + Bad prerequisite: + >>> validate_prereq('1/foo::succeeded') + False + + (That's sufficient, Tokens is fully tested elsewhere). + + """ + try: + Tokens(prereq) + except ValueError: + return False + else: + return True + + def get_prerequisite_opts(options): """Convert prerequisite inputs to a single list, and validate. @@ -149,9 +172,14 @@ def get_prerequisite_opts(options): raise InputError("--pre=all must be used alone") return result - for p in result: - if REC_CLI_PREREQ.match(p): - raise InputError(f"Bad prerequisite: {p}") + msg = '\n'.join( + [ + p for p in result + if not validate_prereq(p) + ] + ) + if msg: + raise InputError(f"Invalid prerequisite(s):\n{msg}") return result diff --git a/cylc/flow/scripts/log_level.py b/cylc/flow/scripts/verbosity.py similarity index 96% rename from cylc/flow/scripts/log_level.py rename to cylc/flow/scripts/verbosity.py index 4d8f181d080..9cebaf63cc9 100755 --- a/cylc/flow/scripts/log_level.py +++ b/cylc/flow/scripts/verbosity.py @@ -16,9 +16,9 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -"""cylc log-level [OPTIONS] ARGS +"""cylc verbosity [OPTIONS] ARGS -Set the Python logging level of a running scheduler. +Set the logging severity level of a running scheduler. Messages at or above the chosen level are logged. If you choose WARNING (say) only WARNING and CRITICAL messages will be logged. diff --git a/cylc/flow/task_pool.py b/cylc/flow/task_pool.py index ca326b14cf1..793b91c676e 100644 --- a/cylc/flow/task_pool.py +++ b/cylc/flow/task_pool.py @@ -16,7 +16,6 @@ """Wrangle task proxies to manage the workflow.""" -import re from contextlib import suppress from collections import Counter import json @@ -73,6 +72,7 @@ from cylc.flow.flow_mgr import FLOW_ALL, FLOW_NONE, FLOW_NEW + if TYPE_CHECKING: from queue import Queue from cylc.flow.config import WorkflowConfig @@ -83,16 +83,8 @@ from cylc.flow.workflow_db_mgr import WorkflowDatabaseManager from cylc.flow.flow_mgr import FlowMgr, FlowNums -Pool = Dict['PointBase', Dict[str, TaskProxy]] - -# CLI prerequisite pattern: point/name:label -REC_CLI_PREREQ = re.compile( - rf"({TaskID.POINT_RE})" + - rf"{TaskID.DELIM2}" + - rf"({TaskID.NAME_RE})" + - r':' + r'(\w+)' # TODO: formally define qualifier RE? -) +Pool = Dict['PointBase', Dict[str, TaskProxy]] class TaskPool: @@ -1676,11 +1668,16 @@ def set_prereqs(self, point, taskdef, prereqs, flow_nums): if prereqs == ["all"]: itask.state.set_all_satisfied() else: - for pre in prereqs: - m = REC_CLI_PREREQ.match(pre) - if m is not None: - itask.satisfy_me({m.groups()}) - # (regex already checked in the CLI) + # Pass individual prerequisites to itask. + itask.satisfy_me( + { + (t['cycle'], t['task'], t['task_sel']) + for t in [ + Tokens(p, relative=True) + for p in prereqs + ] + } + ) self.data_store_mgr.delta_task_prerequisite(itask) self.add_to_pool(itask) diff --git a/setup.cfg b/setup.cfg index 70fb8776e3c..1cfe55da7b6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -189,11 +189,11 @@ cylc.command = remove = cylc.flow.scripts.remove:main report-timings = cylc.flow.scripts.report_timings:main [report-timings] scan = cylc.flow.scripts.scan:cli - log-level = cylc.flow.scripts.log_level:main show = cylc.flow.scripts.show:main set = cylc.flow.scripts.set:main stop = cylc.flow.scripts.stop:main subscribe = cylc.flow.scripts.subscribe:main + verbosity = cylc.flow.scripts.verbosity:main workflow-state = cylc.flow.scripts.workflow_state:main tui = cylc.flow.scripts.tui:main trigger = cylc.flow.scripts.trigger:main diff --git a/tests/functional/cli/03-log-level.t b/tests/functional/cli/03-verbosity.t similarity index 89% rename from tests/functional/cli/03-log-level.t rename to tests/functional/cli/03-verbosity.t index 6274e333816..eb66a4a8cfa 100755 --- a/tests/functional/cli/03-log-level.t +++ b/tests/functional/cli/03-verbosity.t @@ -15,13 +15,13 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . #------------------------------------------------------------------------------- -# Test "cylc log-level" +# Test "cylc verbosity" . "$(dirname "$0")/test_header" set_test_number 6 # Test illegal log level TEST_NAME="${TEST_NAME_BASE}-bad" -run_fail "$TEST_NAME" cylc log-level duck quack +run_fail "$TEST_NAME" cylc verbosity duck quack grep_ok 'InputError: Illegal logging level, duck' "${TEST_NAME}.stderr" # Test good log level @@ -37,10 +37,10 @@ __FLOW__ run_ok "${TEST_NAME}-validate" cylc validate "$WORKFLOW_NAME" workflow_run_ok "${TEST_NAME}-run" cylc play --pause "$WORKFLOW_NAME" -run_ok "$TEST_NAME" cylc log-level DEBUG "$WORKFLOW_NAME" +run_ok "$TEST_NAME" cylc verbosity DEBUG "$WORKFLOW_NAME" LOG_SCAN_GREP_OPTS="-E" \ log_scan "${TEST_NAME}-grep" "${WORKFLOW_RUN_DIR}/log/scheduler/log" 5 1 \ - '\[command] actioned.*set_log_level' + '\[command] actioned.*verbosity' cylc stop "$WORKFLOW_NAME" purge