From e6e5ee83d9cb1da85f0986826a29ffb116644733 Mon Sep 17 00:00:00 2001 From: Hilary James Oliver Date: Thu, 21 Mar 2024 20:11:04 +1300 Subject: [PATCH] Fix workflow-state alt run-dir. --- cylc/flow/id_cli.py | 9 ++++++--- cylc/flow/scripts/workflow_state.py | 17 ++++++++++------- cylc/flow/workflow_files.py | 16 ++++++++++++---- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/cylc/flow/id_cli.py b/cylc/flow/id_cli.py index b6d2a9c4150..4e205e610ab 100644 --- a/cylc/flow/id_cli.py +++ b/cylc/flow/id_cli.py @@ -198,6 +198,7 @@ async def parse_ids_async( constraint: str = 'tasks', max_workflows: Optional[int] = None, max_tasks: Optional[int] = None, + alt_run_dir: Optional[str] = None, ) -> Tuple[Dict[str, List[Tokens]], Any]: """Parse IDs from the command line. @@ -294,7 +295,8 @@ async def parse_ids_async( # infer the run number if not specified the ID (and if possible) if infer_latest_runs: - _infer_latest_runs(tokens_list, src_path=src_path) + _infer_latest_runs( + tokens_list, src_path=src_path, alt_run_dir=alt_run_dir) _validate_number( *tokens_list, @@ -409,13 +411,14 @@ def _validate_workflow_ids(*tokens_list, src_path): detect_both_flow_and_suite(src_path) -def _infer_latest_runs(tokens_list, src_path): +def _infer_latest_runs(tokens_list, src_path, alt_run_dir=None): for ind, tokens in enumerate(tokens_list): if ind == 0 and src_path: # source workflow passed in as a path continue tokens_list[ind] = tokens.duplicate( - workflow=infer_latest_run_from_id(tokens['workflow']) + workflow=infer_latest_run_from_id( + tokens['workflow'], alt_run_dir) ) pass diff --git a/cylc/flow/scripts/workflow_state.py b/cylc/flow/scripts/workflow_state.py index 170b63062d1..8a49eaa6a4c 100755 --- a/cylc/flow/scripts/workflow_state.py +++ b/cylc/flow/scripts/workflow_state.py @@ -162,7 +162,7 @@ def get_option_parser() -> COP: help="The top level cylc run directory if non-standard. The " "database should be DIR/WORKFLOW_ID/log/db. Use to interrogate " "workflows owned by others, etc.; see note above.", - metavar="DIR", action="store", dest="run_dir", default=None) + metavar="DIR", action="store", dest="alt_run_dir", default=None) parser.add_option( "-s", "--offset", @@ -196,10 +196,6 @@ def get_option_parser() -> COP: @cli_function(get_option_parser, remove_opts=["--db"]) def main(parser: COP, options: 'Values', workflow_id: str) -> None: - workflow_id, *_ = parse_id( - workflow_id, - constraint='workflows', - ) if options.use_task_point and options.cycle: raise InputError( @@ -232,10 +228,17 @@ def main(parser: COP, options: 'Values', workflow_id: str) -> None: raise InputError(f"invalid status '{options.status}'") # this only runs locally - if options.run_dir: - run_dir = expand_path(options.run_dir) + if options.alt_run_dir: + run_dir = alt_run_dir = expand_path(options.alt_run_dir) else: run_dir = get_cylc_run_dir() + alt_run_dir = None + + workflow_id, *_ = parse_id( + workflow_id, + constraint='workflows', + alt_run_dir=alt_run_dir + ) pollargs = { 'workflow_id': workflow_id, diff --git a/cylc/flow/workflow_files.py b/cylc/flow/workflow_files.py index 7d4a67756ad..9f56d2a8349 100644 --- a/cylc/flow/workflow_files.py +++ b/cylc/flow/workflow_files.py @@ -862,9 +862,14 @@ def check_reserved_dir_names(name: Union[Path, str]) -> None: raise WorkflowFilesError(err_msg.format('run')) -def infer_latest_run_from_id(workflow_id: str) -> str: - run_dir = Path(get_workflow_run_dir(workflow_id)) - _, id_ = infer_latest_run(run_dir) +def infer_latest_run_from_id( + workflow_id: str, alt_run_dir: Optional[str] = None +) -> str: + if alt_run_dir is not None: + run_dir = Path(alt_run_dir) / Path(workflow_id) + else: + run_dir = Path(get_workflow_run_dir(workflow_id)) + _, id_ = infer_latest_run(run_dir, alt_run_dir=alt_run_dir) return id_ @@ -872,6 +877,7 @@ def infer_latest_run( path: Path, implicit_runN: bool = True, warn_runN: bool = True, + alt_run_dir: Optional[str] = None, ) -> Tuple[Path, str]: """Infer the numbered run dir if the workflow has a runN symlink. @@ -890,15 +896,17 @@ def infer_latest_run( - WorkflowFilesError if the runN symlink is not valid. - InputError if the path does not exist. """ - cylc_run_dir = get_cylc_run_dir() + cylc_run_dir = alt_run_dir or get_cylc_run_dir() try: id_ = str(path.relative_to(cylc_run_dir)) except ValueError: raise ValueError(f"{path} is not in the cylc-run directory") + if not path.exists(): raise InputError( f'Workflow ID not found: {id_}\n(Directory not found: {path})' ) + if path.name == WorkflowFiles.RUN_N: runN_path = path if warn_runN: