diff --git a/src/sirocco/core.py b/src/sirocco/core.py index 91d43eb4..83beafe3 100644 --- a/src/sirocco/core.py +++ b/src/sirocco/core.py @@ -59,7 +59,7 @@ class Task(BaseNode): # keywords and extend it as we support more command: str | None = None command_option: str | None = None - input_arg_options: dict[str, str] | None = None + input_arg_options: dict[str, str] = field(default_factory=dict) host: str | None = None account: str | None = None plugin: str | None = None @@ -94,6 +94,15 @@ def from_config( cls_config = dict(config) del cls_config["parameters"] + # We remove the None values in the config, as these are not setted parameters. + # This way the default values are not overwritten to None (e.g. for input_arg_options) + none_keys = [] + for key, value in cls_config.items(): + if value is None: + none_keys.append(key) + for key in none_keys: + del cls_config[key] + new = cls( parameters=parameters, inputs=inputs, diff --git a/tests/files/configs/test_config_parameters.yml b/tests/files/configs/test_config_parameters.yml index fa8e170c..7ae9a3d4 100644 --- a/tests/files/configs/test_config_parameters.yml +++ b/tests/files/configs/test_config_parameters.yml @@ -1,6 +1,6 @@ --- start_date: &root_start_date '2026-01-01T00:00' -end_date: &root_end_date '2028-01-01T00:00' +end_date: &root_end_date '2026-03-01T00:00' cycles: - bimonthly_tasks: @@ -39,7 +39,7 @@ cycles: - merge: inputs: - analysis_foo_bar: - lag: ['P0M', 'P2M', 'P4M', 'P6M', 'P8M', 'P10M'] + lag: ['P0M'] outputs: [yearly_analysis] tasks: @@ -47,7 +47,9 @@ tasks: plugin: shell command: $PWD/tests/files/scripts/icon.py input_arg_options: - icon_restart: '--restart' + icon_restart: "--restart" + initial_conditions: "--init" + forcing: '--forcing' parameters: [foo, bar] - statistics_foo: plugin: shell @@ -64,10 +66,10 @@ data: available: - initial_conditions: type: file - src: initial_conditions + src: $PWD/tests/files/data/initial_conditions - forcing: type: file - src: forcing + src: $PWD/tests/files/data/forcing generated: - icon_output: type: file @@ -89,5 +91,5 @@ data: src: yearly_analysis parameters: - foo: [0, 1, 2] - bar: {arange: [3, 4, 0.5]} + foo: [0, 1] + bar: {arange: [3, 4]} diff --git a/tests/files/data/test_config_parameters.txt b/tests/files/data/test_config_parameters.txt index 7220cdb2..81b4e718 100644 --- a/tests/files/data/test_config_parameters.txt +++ b/tests/files/data/test_config_parameters.txt @@ -3,42 +3,42 @@ cycles: tasks: - icon [date: 2026-01-01 00:00:00, foo: 0, bar: 3.0]: input: - - initial conditions + - initial_conditions - forcing output: - icon_output [date: 2026-01-01 00:00:00, foo: 0, bar: 3.0] - icon_restart [date: 2026-01-01 00:00:00, foo: 0, bar: 3.0] - icon [date: 2026-01-01 00:00:00, foo: 0, bar: 3.5]: input: - - initial conditions + - initial_conditions - forcing output: - icon_output [date: 2026-01-01 00:00:00, foo: 0, bar: 3.5] - icon_restart [date: 2026-01-01 00:00:00, foo: 0, bar: 3.5] - icon [date: 2026-01-01 00:00:00, foo: 1, bar: 3.0]: input: - - initial conditions + - initial_conditions - forcing output: - icon_output [date: 2026-01-01 00:00:00, foo: 1, bar: 3.0] - icon_restart [date: 2026-01-01 00:00:00, foo: 1, bar: 3.0] - icon [date: 2026-01-01 00:00:00, foo: 1, bar: 3.5]: input: - - initial conditions + - initial_conditions - forcing output: - icon_output [date: 2026-01-01 00:00:00, foo: 1, bar: 3.5] - icon_restart [date: 2026-01-01 00:00:00, foo: 1, bar: 3.5] - icon [date: 2026-01-01 00:00:00, foo: 2, bar: 3.0]: input: - - initial conditions + - initial_conditions - forcing output: - icon_output [date: 2026-01-01 00:00:00, foo: 2, bar: 3.0] - icon_restart [date: 2026-01-01 00:00:00, foo: 2, bar: 3.0] - icon [date: 2026-01-01 00:00:00, foo: 2, bar: 3.5]: input: - - initial conditions + - initial_conditions - forcing output: - icon_output [date: 2026-01-01 00:00:00, foo: 2, bar: 3.5] @@ -790,4 +790,4 @@ cycles: - analysis_foo_bar [date: 2027-09-01 00:00:00] - analysis_foo_bar [date: 2027-11-01 00:00:00] output: - - yearly_analysis [date: 2027-01-01 00:00:00] \ No newline at end of file + - yearly_analysis [date: 2027-01-01 00:00:00] diff --git a/tests/files/scripts/icon.py b/tests/files/scripts/icon.py index 4e7ad564..7ec029b9 100755 --- a/tests/files/scripts/icon.py +++ b/tests/files/scripts/icon.py @@ -1,42 +1,62 @@ #!/usr/bin/env python +"""usage: icon.py [-h] [--init [INIT]] [--restart [RESTART]] [--forcing [FORCING]] + +A script mocking parts of icon in a form of a shell script + +options: + -h, --help show this help message and exit + --init [INIT] The icon init file. + --restart [RESTART] The icon restart file. + --forcing [FORCING] The icon forcing file. +""" import argparse from pathlib import Path +LOG_FILE = Path("icon.log") + +def log(text: str): + print(text) + with LOG_FILE.open("a") as f: + f.write(text) def main(): - parser = argparse.ArgumentParser(description='A simple script with an optional restart argument.') - parser.add_argument('icon_input', type=str, help='The icon input.') + parser = argparse.ArgumentParser(description='A script mocking parts of icon in a form of a shell script.') + parser.add_argument('--init', nargs='?', type=str, help='The icon init file.') parser.add_argument('--restart', nargs='?', type=str, help='The icon restart file.') + parser.add_argument('--forcing', nargs='?', type=str, help='The icon forcing file.') #parser.add_argument('--restart', nargs='?', const='default', type=str, help='Initiate a restart operation with an optional string argument.') args = parser.parse_args() + output = Path('output') output.write_text("") - if args.restart: + if args.restart and args.init: + raise ValueError("Cannot use '--init' and '--restart' option at the same time.") + elif args.restart: + if not Path(args.restart).exists(): + raise FileNotFoundError(f"The icon restart file {args.restart!r} was not found.") restart = Path(args.restart) - restart.read_text() - text = "Restart operation initiated..." - print(text) - with output.open("a") as f: - f.write(text) - else: - text = "No restart option provided. Continuing without restart." - print(text) - with output.open("a") as f: - f.write(text) + + log(f"Restarting from file {args.restart!r}.") + elif args.init: + if not Path(args.init).exists(): + raise FileNotFoundError(f"The icon init file {args.init!r} was not found.") + + log(f"Starting from init file {args.init!r}.") + else: + raise ValueError("Please provide a restart or init file with the corresponding option.") # Main script execution continues here - text = "Script execution continues..." - print(text) - with output.open("a") as f: - f.write(text) + log("Script finished running calculations") restart = Path('restart') restart.write_text("") if __name__ == '__main__': main() + + diff --git a/tests/test_wc_workflow.py b/tests/test_wc_workflow.py index a876b4aa..55748482 100644 --- a/tests/test_wc_workflow.py +++ b/tests/test_wc_workflow.py @@ -21,8 +21,8 @@ def pprinter(): @pytest.mark.parametrize("config_path", [ - "tests/files/configs/test_config_small.yml", - #"tests/files/configs/test_config_parameters.yml", + #"tests/files/configs/test_config_small.yml", + "tests/files/configs/test_config_parameters.yml", ]) def test_run_workgraph(config_path): core_workflow = Workflow.from_yaml(config_path) @@ -46,9 +46,7 @@ def test_parse_config_file(config_case, pprinter): if test_str != reference_str: new_path = Path(reference_path).with_suffix(".new.txt") new_path.write_text(test_str) - msg = f"Workflow graph doesn't match serialized data. New graph string dumped to {new_path}." - assert reference_str == test_str - raise ValueError(msg) + assert reference_str == test_str, f"Workflow graph doesn't match serialized data. New graph string dumped to {new_path}." @pytest.mark.skip(reason="don't run it each time, uncomment to regenerate serilaized data")