diff --git a/docs/Maestro/cli.md b/docs/Maestro/cli.md index af8f1992..2d46612b 100644 --- a/docs/Maestro/cli.md +++ b/docs/Maestro/cli.md @@ -55,7 +55,7 @@ maestro cancel [OPTIONS] DIRECTORY [DIRECTORY ...] | Name | Type | Description | Default | | ---- | ---- | ----------- | ------- | | `-h`, `--help` | boolean | Show this help message and exit. | `False` | - +| `-y`, `--autoyes` | boolean | Automatically answer yes to input prompts. | `False` | ### **run** diff --git a/maestrowf/maestro.py b/maestrowf/maestro.py index 23f5dd46..d6258c7d 100644 --- a/maestrowf/maestro.py +++ b/maestrowf/maestro.py @@ -136,7 +136,13 @@ def cancel_study(args): to_cancel.append(abs_path) if to_cancel: - ok_cancel = input("Are you sure? [y|[n]]: ") + # If we are automatically launching, just set the input as yes. + if args.autoyes: + ok_cancel = "y" + else: + ok_cancel = six.moves.input("Are you sure? [y|[n]]: ") + # ok_cancel = input("Are you sure? [y|[n]]: ") + try: if ok_cancel in ACCEPTED_INPUT: for directory in to_cancel: @@ -545,6 +551,9 @@ def setup_argparser(): cancel = subparsers.add_parser( 'cancel', help="Cancel all running jobs.") + cancel.add_argument("-y", "--autoyes", action="store_true", default=False, + help="Automatically answer yes to input prompts") + cancel.add_argument( "directory", type=str, nargs="+", help="Directory or list of directories containing running studies.") diff --git a/pyproject.toml b/pyproject.toml index 013c1d14..6f79e3b6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [tool] [tool.poetry] name = "maestrowf" -version = "1.1.12dev1" +version = "1.1.12dev2" description = "A tool to easily orchestrate general computational workflows both locally and on supercomputers." license = "MIT License" classifiers = [ diff --git a/tests/test_cli.py b/tests/test_cli.py index b3f2c8a4..448d0a70 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -2,6 +2,7 @@ from maestrowf.conductor import Conductor import pytest +from unittest.mock import patch, MagicMock from rich.pretty import pprint @@ -114,3 +115,52 @@ def test_write_update_args(cli_args, expected_lock_dict, tmp_path): update_dict = Conductor.load_updated_study_exec(tmp_path) assert update_dict == expected_lock_dict + + +@pytest.mark.parametrize( + "cli_args, user_input, expect_parse_ok, expected_ret_code, cancel_processed", + [ + ([], "", True, 0, False), + ([], "y", True, 0, True), + ([], "n", True, 0, False), + (["--autoyes", ], "", True, 0, True), + (["--ay", ], "", False, 2, False) # How to test the ret_code=1 -> study dir doesn't exist + ] +) +def test_cancel_cli(cli_args, user_input, expect_parse_ok, expected_ret_code, cancel_processed, tmp_path, capsys): + """ + Test validation of arguments passed to the 'maestro update' cli command + """ + + with patch("six.moves.input", return_value=user_input): + + parser = maestro.setup_argparser() + maestro_cli = ["cancel"] + + maestro_cli.extend(cli_args) + maestro_cli.append(str(tmp_path)) # attach fake study workspace + print(f"{maestro_cli=}") + + if expect_parse_ok: + args = parser.parse_args(maestro_cli) + cret = maestro.cancel_study(args) + assert cret == expected_ret_code + + # assert args is None + assert (tmp_path / ".cancel.lock").exists() == cancel_processed + + else: + with pytest.raises(SystemExit) as se: + args = parser.parse_args(maestro_cli) + + assert se.value.code == expected_ret_code + + # Check the output form argparse + captured = capsys.readouterr() + + combined = captured.out + captured.err + print(f"{combined=}") + assert "unrecognized arguments" in combined or "usage:" in combined + + # Ensure a cancel file not created somehow + assert not (tmp_path / ".cancel.lock").exists()