diff --git a/pyproject.toml b/pyproject.toml index d5863fc6..3877f9aa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,7 +33,10 @@ dependencies = [ "aiida-core>=2.5", "termcolor", "pygraphviz", - "lxml" + "lxml", + "aiida-core~=2.5", + "aiida-workgraph==0.3.14", + "node_graph==0.0.11", ] license = {file = "LICENSE"} diff --git a/src/sirocco/core/graph_items.py b/src/sirocco/core/graph_items.py index 0bed3d87..807018d2 100644 --- a/src/sirocco/core/graph_items.py +++ b/src/sirocco/core/graph_items.py @@ -2,6 +2,7 @@ from dataclasses import dataclass, field from itertools import chain, product +from pathlib import Path from typing import TYPE_CHECKING, Any, ClassVar, Self from sirocco.parsing._yaml_data_models import ( diff --git a/src/sirocco/parsing/_yaml_data_models.py b/src/sirocco/parsing/_yaml_data_models.py index 976f7fa7..1f10c6c9 100644 --- a/src/sirocco/parsing/_yaml_data_models.py +++ b/src/sirocco/parsing/_yaml_data_models.py @@ -1,7 +1,7 @@ from __future__ import annotations import time -from dataclasses import dataclass +from dataclasses import dataclass, field from datetime import datetime from pathlib import Path from typing import Annotated, Any, ClassVar, Literal @@ -82,43 +82,6 @@ def convert_datetime(cls, value) -> datetime: return datetime.fromisoformat(value) -class _CliArgsBaseModel(BaseModel): - """Base class for cli_arguments specifications""" - - # TODO: Even allow for `str`, or always require list? - positional: str | list[str] | None = None - # Field needed for child class doing pydantic parsing - keyword: dict[str, str] | None = Field(default_factory=dict) - flags: str | list[str] | None = None - source_file: str | list[str] | None = None - - # TODO: Should we allow users to pass it without the hyphen(s), and prepend them automatically? - # TODO: While convenient, it could be a bad idea, if users put in wrong things. Better to be explicit. - @field_validator("keyword", mode="before") - @classmethod - def validate_keyword_args(cls, value): - """Ensure keyword arguments start with '-' or '--'.""" - if value is not None: - invalid_keys = [key for key in value if not key.startswith(("-", "--"))] - if invalid_keys: - invalid_kwarg_exc = f"Invalid keyword arguments: {', '.join(invalid_keys)}" - raise ValueError(invalid_kwarg_exc) - return value - - @field_validator("flags", mode="before") - @classmethod - def validate_flag_args(cls, value): - """Ensure positional arguments start with '-' or '--'.""" - if value is not None: - if isinstance(value, str): - value = [value] - invalid_flags = [arg for arg in value if not arg.startswith(("-", "--"))] - if invalid_flags: - invalid_flags_exc = f"Invalid positional arguments: {', '.join(invalid_flags)}" - raise ValueError(invalid_flags_exc) - return value - - class TargetNodesBaseModel(_NamedBaseModel): """class for targeting other task or data nodes in the graph @@ -310,12 +273,14 @@ class ConfigRootTask(ConfigBaseTask): class ConfigShellTaskSpecs: plugin: ClassVar[Literal["shell"]] = "shell" command: str = "" - cli_arguments: _CliArgsBaseModel | None = None + cli_arguments: str = "" + env_source_files: str | list[str] = field(default_factory=list) src: str | None = None class ConfigShellTask(ConfigBaseTask, ConfigShellTaskSpecs): - pass + command: str = "" + env_source_files: str | list[str] = Field(default_factory=list) @dataclass @@ -341,6 +306,9 @@ class ConfigBaseData(_NamedBaseModel, ConfigBaseDataSpecs): """ parameters: list[str] = [] + type: str | None = None + src: str | None = None + format: str | None = None @field_validator("type") @classmethod diff --git a/src/sirocco/workgraph.py b/src/sirocco/workgraph.py new file mode 100644 index 00000000..8d1e52fe --- /dev/null +++ b/src/sirocco/workgraph.py @@ -0,0 +1,356 @@ +from __future__ import annotations + +from pathlib import Path +from typing import TYPE_CHECKING, Any + +import aiida.common +import aiida.orm +import aiida_workgraph.engine.utils # type: ignore[import-untyped] +from aiida_workgraph import WorkGraph + +from sirocco.core._tasks.icon_task import IconTask +from sirocco.core._tasks.shell_task import ShellTask + +if TYPE_CHECKING: + from aiida_workgraph.socket import TaskSocket # type: ignore[import-untyped] + + from sirocco import core + from sirocco.core import graph_items + + +# This is hack to aiida-workgraph, merging this into aiida-workgraph properly would require +# some major refactor see issue https://github.com/aiidateam/aiida-workgraph/issues/168 +# It might be better to give up on the graph like construction and just create the task +# directly with inputs, arguments and outputs +def _prepare_for_shell_task(task: dict, kwargs: dict) -> dict: + """Prepare the inputs for ShellTask""" + from aiida.common import lang + from aiida.orm import AbstractCode + from aiida_shell.launch import convert_nodes_single_file_data, prepare_code + + command = kwargs.pop("command", None) + resolve_command = kwargs.pop("resolve_command", False) + metadata = kwargs.pop("metadata", {}) + # setup code + if isinstance(command, str): + computer = (metadata or {}).get("options", {}).pop("computer", None) + code = prepare_code(command, computer, resolve_command) + else: + lang.type_check(command, AbstractCode) + code = command + # update the tasks with links + nodes = convert_nodes_single_file_data(kwargs.pop("nodes", {})) + # find all keys in kwargs start with "nodes." + for key in list(kwargs.keys()): + if key.startswith("nodes."): + nodes[key[6:]] = kwargs.pop(key) + metadata.update({"call_link_label": task["name"]}) + + default_outputs = {"remote_folder", "remote_stash", "retrieved", "_outputs", "_wait", "stdout", "stderr"} + task_outputs = {task["outputs"][i]["name"] for i in range(len(task["outputs"]))} + task_outputs = task_outputs.union(set(kwargs.pop("outputs", []))) + missing_outputs = task_outputs.difference(default_outputs) + return { + "code": code, + "nodes": nodes, + "filenames": kwargs.pop("filenames", {}), + "arguments": kwargs.pop("arguments", []), + "outputs": list(missing_outputs), + "parser": kwargs.pop("parser", None), + "metadata": metadata or {}, + } + + +aiida_workgraph.engine.utils.prepare_for_shell_task = _prepare_for_shell_task + + +class AiidaWorkGraph: + def __init__(self, core_workflow: core.Workflow): + # the core workflow that unrolled the time constraints for the whole graph + self._core_workflow = core_workflow + + self._validate_workflow() + + self._workgraph = WorkGraph(core_workflow.name) + + # stores the input data available on initialization + self._aiida_data_nodes: dict[str, aiida_workgraph.orm.Data] = {} + # stores the outputs sockets of tasks + self._aiida_socket_nodes: dict[str, TaskSocket] = {} + self._aiida_task_nodes: dict[str, aiida_workgraph.Task] = {} + + self._add_available_data() + self._add_tasks() + + def _validate_workflow(self): + """Checks if the core workflow uses for its cycles, tasks and data valid names for AiiDA.""" + for cycle in self._core_workflow.cycles: + try: + aiida.common.validate_link_label(cycle.name) + except ValueError as exception: + msg = f"Raised error when validating cycle name '{cycle.name}': {exception.args[0]}" + raise ValueError(msg) from exception + for task in cycle.tasks: + try: + aiida.common.validate_link_label(task.name) + except ValueError as exception: + msg = f"Raised error when validating task name '{cycle.name}': {exception.args[0]}" + raise ValueError(msg) from exception + for input_ in task.inputs: + try: + aiida.common.validate_link_label(input_.name) + except ValueError as exception: + msg = f"Raised error when validating input name '{input_.name}': {exception.args[0]}" + raise ValueError(msg) from exception + for output in task.outputs: + try: + aiida.common.validate_link_label(output.name) + except ValueError as exception: + msg = f"Raised error when validating output name '{output.name}': {exception.args[0]}" + raise ValueError(msg) from exception + + def _add_available_data(self): + """Adds the available data on initialization to the workgraph""" + for cycle in self._core_workflow.cycles: + for task in cycle.tasks: + for input_ in task.inputs: + if input_.available: + self._add_aiida_input_data_node(task, input_) + + @staticmethod + def replace_invalid_chars_in_label(label: str) -> str: + """Replaces chars in the label that are invalid for AiiDA. + + The invalid chars ["-", " ", ":", "."] are replaced with underscores. + """ + invalid_chars = ["-", " ", ":", "."] + for invalid_char in invalid_chars: + label = label.replace(invalid_char, "_") + return label + + @staticmethod + def get_aiida_label_from_graph_item(obj: graph_items.GraphItem) -> str: + """Returns a unique AiiDA label for the given graph item. + + The graph item object is uniquely determined by its name and its coordinates. There is the possibility that + through the replacement of invalid chars in the coordinates duplication can happen but it is unlikely. + """ + return AiidaWorkGraph.replace_invalid_chars_in_label( + f"{obj.name}" + "__".join(f"_{key}_{value}" for key, value in obj.coordinates.items()) + ) + + def _add_aiida_input_data_node(self, task: graph_items.Task, input_: graph_items.Data): + """ + Create an `aiida.orm.Data` instance from the provided graph item. + """ + label = AiidaWorkGraph.get_aiida_label_from_graph_item(input_) + input_path = Path(input_.src) + input_full_path = input_.src if input_path.is_absolute() else task.config_rootdir / input_path + + if input_.type == "file": + self._aiida_data_nodes[label] = aiida.orm.SinglefileData(label=label, file=input_full_path) + elif input_.type == "dir": + self._aiida_data_nodes[label] = aiida.orm.FolderData(label=label, tree=input_full_path) + else: + msg = f"Data type {input_.type!r} not supported. Please use 'file' or 'dir'." + raise ValueError(msg) + + def _add_tasks(self): + """Creates the AiiDA task nodes from the `GraphItem.Task`s in the cycles. + + This includes the linking of all input and output nodes, the arguments and wait_on tasks + """ + for cycle in self._core_workflow.cycles: + for task in cycle.tasks: + self._create_task_node(task) + + # NOTE: The wait on tasks has to be added after the creation of the tasks because it might reference tasks from + # the future + for cycle in self._core_workflow.cycles: + for task in cycle.tasks: + self._link_wait_on_to_task(task) + + for cycle in self._core_workflow.cycles: + for task in cycle.tasks: + for input_ in task.inputs: + self._link_input_nodes_to_task(task, input_) + self._link_arguments_to_task(task) + for output in task.outputs: + self._link_output_nodes_to_task(task, output) + + def _create_task_node(self, task: graph_items.Task): + label = AiidaWorkGraph.get_aiida_label_from_graph_item(task) + if isinstance(task, ShellTask): + command_path = Path(task.command) + command_full_path = task.command if command_path.is_absolute() else task.config_rootdir / command_path + command = str(command_full_path) + + # Source file + env_source_files = task.env_source_files + env_source_files = [env_source_files] if isinstance(env_source_files, str) else env_source_files + prepend_text = "\n".join([f"source {env_source_file}" for env_source_file in env_source_files]) + + # NOTE: We don't pass the `nodes` dictionary here, as then we would need to have the sockets available when + # we create the task. Instead, they are being updated via the WG internals when linking inputs/outputs to + # tasks + workgraph_task = self._workgraph.tasks.new( + "ShellJob", + name=label, + command=command, + arguments=[], + metadata={"options": {"prepend_text": prepend_text}}, + ) + + self._aiida_task_nodes[label] = workgraph_task + + elif isinstance(task, IconTask): + exc = "IconTask not implemented yet." + raise NotImplementedError(exc) + else: + exc = f"Task: {task.name} not implemented yet." + raise NotImplementedError(exc) + + def _link_wait_on_to_task(self, task: graph_items.Task): + label = AiidaWorkGraph.get_aiida_label_from_graph_item(task) + workgraph_task = self._aiida_task_nodes[label] + wait_on_tasks = [] + for wait_on in task.wait_on: + wait_on_task_label = AiidaWorkGraph.get_aiida_label_from_graph_item(wait_on) + wait_on_tasks.append(self._aiida_task_nodes[wait_on_task_label]) + workgraph_task.wait = wait_on_tasks + + def _link_input_nodes_to_task(self, task: graph_items.Task, input_: graph_items.Data): + """Links the input to the workgraph task.""" + task_label = AiidaWorkGraph.get_aiida_label_from_graph_item(task) + input_label = AiidaWorkGraph.get_aiida_label_from_graph_item(input_) + workgraph_task = self._aiida_task_nodes[task_label] + workgraph_task.inputs.new("Any", f"nodes.{input_label}") + workgraph_task.kwargs.append(f"nodes.{input_label}") + + # resolve data + if (data_node := self._aiida_data_nodes.get(input_label)) is not None: + if (nodes := workgraph_task.inputs.get("nodes")) is None: + msg = ( + f"Workgraph task {workgraph_task.name!r} did not initialize input nodes in the workgraph " + f"before linking. This is a bug in the code, please contact the developers by making an issue." + ) + raise ValueError(msg) + nodes.value.update({f"{input_label}": data_node}) + elif (output_socket := self._aiida_socket_nodes.get(input_label)) is not None: + self._workgraph.links.new(output_socket, workgraph_task.inputs[f"nodes.{input_label}"]) + else: + msg = ( + f"Input data node {input_label!r} was neither found in socket nodes nor in data nodes. The task " + f"{task_label!r} must have dependencies on inputs before they are created." + ) + raise ValueError(msg) + + def _link_arguments_to_task(self, task: graph_items.Task): + """Links the arguments to the workgraph task. + + Parses `cli_arguments` of the graph item task and links all arguments to the task node. It only adds arguments + corresponding to inputs if they are contained in the task. + """ + task_label = AiidaWorkGraph.get_aiida_label_from_graph_item(task) + workgraph_task = self._aiida_task_nodes[task_label] + if (workgraph_task_arguments := workgraph_task.inputs.get("arguments")) is None: + msg = ( + f"Workgraph task {workgraph_task.name!r} did not initialize arguments nodes in the workgraph " + f"before linking. This is a bug in the code, please contact developers." + ) + raise ValueError(msg) + + name_to_input_map = {input_.name: input_ for input_ in task.inputs} + # we track the linked input arguments, to ensure that all linked input nodes got linked arguments + linked_input_args = [] + + len_arg_with_option = 2 + len_arg_no_option = 1 + for arg in self._split_cli_arguments(task.cli_arguments): + if arg.startswith("{") and arg.endswith("}"): + # remove curly brackets + # "{--init file}" -> "--init file" + arg_wrapped = arg[1:-1] + # "--init file" -> ["--init", "file"] + input_arg = arg_wrapped.split() + if len(input_arg) != len_arg_with_option and len(input_arg) != len_arg_no_option: + msg = f"Expected argument of format {{data}} or {{option data}} but found {arg}" + raise ValueError(msg) + arg_name = input_arg[0] if len(input_arg) == len_arg_no_option else input_arg[1] + # We only add an input argument to the args if it has been added to the nodes + # This ensures that inputs and their arguments are only added + # when the time conditions are fulfilled + if (input_ := name_to_input_map.get(arg_name)) is not None: + input_label = AiidaWorkGraph.get_aiida_label_from_graph_item(input_) + + arg_option = input_arg[0] if len(input_arg) == len_arg_with_option else None + if arg_option is not None: + workgraph_task_arguments.value.append(f"{arg_option}") + workgraph_task_arguments.value.append(f"{{{input_label}}}") + linked_input_args.append(input_.name) + else: + workgraph_task_arguments.value.append(f"{arg}") + # Adding remaining input nodes as positional arguments + for input_name in name_to_input_map: + if input_name not in linked_input_args: + input_ = name_to_input_map[input_name] + input_label = AiidaWorkGraph.get_aiida_label_from_graph_item(input_) + workgraph_task_arguments.value.append(f"{{{input_label}}}") + + def _split_cli_arguments(self, cli_arguments: str) -> list[str]: + """Splits the CLI arguments into a list of separate entities. + + Splits the CLI arguments by whitespaces except if the whitespace is contained within curly brackets. For example + the string + "-D --CMAKE_CXX_COMPILER=${CXX_COMPILER} {--init file}" + will be splitted into by this function + ["-D", "--CMAKE_CXX_COMPILER=${CXX_COMPILER}", "{--init file}"] + """ + + nb_open_curly_brackets = 0 + last_split_idx = 0 + splits = [] + for i, char in enumerate(cli_arguments): + if char == " " and not nb_open_curly_brackets: + # we ommit the space in the splitting + splits.append(cli_arguments[last_split_idx:i]) + last_split_idx = i + 1 + elif char == "{": + nb_open_curly_brackets += 1 + elif char == "}": + if nb_open_curly_brackets == 0: + msg = "Invalid input for cli_arguments. Found a closing curly bracket before an opening in {cli_argumentss!r}" + raise ValueError(msg) + nb_open_curly_brackets -= 1 + + if last_split_idx != len(cli_arguments): + splits.append(cli_arguments[last_split_idx : len(cli_arguments)]) + + return splits + + def _link_output_nodes_to_task(self, task: graph_items.Task, output: graph_items.Data): + """ + task: the task corresponding to the output + output: ... + """ + workgraph_task = self._aiida_task_nodes[AiidaWorkGraph.get_aiida_label_from_graph_item(task)] + output_label = AiidaWorkGraph.get_aiida_label_from_graph_item(output) + output_socket = workgraph_task.outputs.new("Any", output.src) + self._aiida_socket_nodes[output_label] = output_socket + + def run( + self, + inputs: None | dict[str, Any] = None, + metadata: None | dict[str, Any] = None, + ) -> dict[str, Any]: + return self._workgraph.run(inputs=inputs, metadata=metadata) + + def submit( + self, + *, + inputs: None | dict[str, Any] = None, + wait: bool = False, + timeout: int = 60, + metadata: None | dict[str, Any] = None, + ) -> dict[str, Any]: + return self._workgraph.submit(inputs=inputs, wait=wait, timeout=timeout, metadata=metadata) diff --git a/tests/cases/large/config/data/dummy_source_file.sh b/tests/cases/large/config/data/dummy_source_file.sh new file mode 100644 index 00000000..e69de29b diff --git a/tests/cases/large/config/data/era5 b/tests/cases/large/config/data/era5 new file mode 100644 index 00000000..e69de29b diff --git a/tests/cases/large/config/data/grid b/tests/cases/large/config/data/grid new file mode 100644 index 00000000..e69de29b diff --git a/tests/cases/large/config/data/obs_data b/tests/cases/large/config/data/obs_data new file mode 100644 index 00000000..e69de29b diff --git a/tests/cases/large/config/scripts/cleanup.sh b/tests/cases/large/config/scripts/cleanup.sh new file mode 100755 index 00000000..bc5435d9 --- /dev/null +++ b/tests/cases/large/config/scripts/cleanup.sh @@ -0,0 +1 @@ +echo "cleanup" > output diff --git a/tests/cases/large/config/scripts/extpar b/tests/cases/large/config/scripts/extpar new file mode 100755 index 00000000..66dc5ac0 --- /dev/null +++ b/tests/cases/large/config/scripts/extpar @@ -0,0 +1 @@ +echo "extpar" > output diff --git a/tests/cases/large/config/scripts/icon b/tests/cases/large/config/scripts/icon new file mode 100755 index 00000000..ec409b0e --- /dev/null +++ b/tests/cases/large/config/scripts/icon @@ -0,0 +1,4 @@ +echo "icon" > restart +echo "icon" > output +echo "icon" > output_1 +echo "icon" > output_2 diff --git a/tests/cases/large/config/scripts/main_script_atm.sh b/tests/cases/large/config/scripts/main_script_atm.sh new file mode 100755 index 00000000..2a361f83 --- /dev/null +++ b/tests/cases/large/config/scripts/main_script_atm.sh @@ -0,0 +1 @@ +echo "main_script_atm.sh" > postout diff --git a/tests/cases/large/config/scripts/main_script_ocn.sh b/tests/cases/large/config/scripts/main_script_ocn.sh new file mode 100755 index 00000000..1d01b24c --- /dev/null +++ b/tests/cases/large/config/scripts/main_script_ocn.sh @@ -0,0 +1 @@ +echo "python main_script_ocn.sh" > postout diff --git a/tests/cases/large/config/scripts/post_clean.sh b/tests/cases/large/config/scripts/post_clean.sh new file mode 100755 index 00000000..b91319f8 --- /dev/null +++ b/tests/cases/large/config/scripts/post_clean.sh @@ -0,0 +1 @@ +echo "store_and_clean" > stored_data diff --git a/tests/cases/large/config/test_config_large.yml b/tests/cases/large/config/test_config_large.yml index 05c261b8..ea295f4e 100644 --- a/tests/cases/large/config/test_config_large.yml +++ b/tests/cases/large/config/test_config_large.yml @@ -61,12 +61,8 @@ tasks: account: g110 - extpar: plugin: shell # no extpar plugin available yet - command: $PWD/examples/files/scripts/extpar - cli_arguments: - keyword: - --input: obs_data - flags: - - --verbose + command: scripts/extpar + cli_arguments: "--verbose {--input obs_data}" uenv: squashfs: path/to/squashfs mount_point: runtime/mount/point @@ -74,26 +70,18 @@ tasks: walltime: 00:02:00 - preproc: plugin: shell - command: $PWD/examples/files/scripts/cleanup.sh - cli_arguments: - positional: - - grid_file - keyword: - -p: extpar_file - -e: ERA5 - source_file: dummy_source_file + command: scripts/cleanup.sh + cli_arguments: "{-p extpar_file} {-e ERA5} {grid_file}" + source_file: dummy_source_file nodes: 4 walltime: 00:02:00 uenv: squashfs: path/to/squashfs mount_point: runtime/mount/point - icon: - plugin: icon - command: $PWD/examples/files/scripts/icon - cli_arguments: - keyword: - -g: grid_file - --input: icon_input + plugin: shell + command: scripts/icon + cli_arguments: "{-g grid_file} {--input icon_input}" nodes: 40 walltime: 23:59:59 namelists: @@ -104,10 +92,8 @@ tasks: mount_point: runtime/mount/point - postproc_1: plugin: shell - command: $PWD/examples/files/scripts/main_script_ocn.sh - cli_arguments: - keyword: - --input: stream_1 + command: scripts/main_script_ocn.sh + cli_arguments: "{--input stream_1}" nodes: 2 walltime: 00:05:00 uenv: @@ -115,13 +101,8 @@ tasks: mount_point: runtime/mount/point - postproc_2: plugin: shell - command: $PWD/examples/files/scripts/main_script_atm.sh - cli_arguments: - keyword: - --input: stream_2 - # `arg_option` should be in `tasks` section instead - # How to implement this? Even needed with keyword-arguments? - # arg_option: --input + command: scripts/main_script_atm.sh + cli_arguments: "{--input stream_2}" nodes: 2 walltime: 00:05:00 src: path/to/src/dir @@ -130,36 +111,30 @@ tasks: mount_point: runtime/mount/point - store_and_clean_1: plugin: shell - command: $PWD/examples/files/scripts/post_clean.sh - cli_arguments: - keyword: - --input: postout_1 - --stream: stream_1 - --icon_input: icon_input + command: scripts/post_clean.sh + cli_arguments: "{--input postout_1} {--stream stream_1} {--icon_input icon_input}" nodes: 1 walltime: 00:01:00 - store_and_clean_2: plugin: shell - command: $PWD/examples/files/scripts/post_clean.sh - cli_arguments: - keyword: - --input: postout_2 + command: scripts/post_clean.sh + cli_arguments: "{--input postout_2}" nodes: 1 walltime: 00:01:00 data: available: - grid_file: type: file - src: $PWD/examples/files/data/grid + src: data/grid - obs_data: type: file - src: $PWD/examples/files/data/obs_data + src: data/obs_data - ERA5: type: file - src: $PWD/examples/files/data/era5 + src: data/era5 - dummy_source_file: type: file - src: $PWD/examples/files/data/dummy_source_file.sh + src: data/dummy_source_file.sh generated: - extpar_file: type: file diff --git a/tests/cases/large/data/test_config_large.txt b/tests/cases/large/data/test_config_large.txt index 24445df1..59e7bdc0 100644 --- a/tests/cases/large/data/test_config_large.txt +++ b/tests/cases/large/data/test_config_large.txt @@ -12,8 +12,9 @@ cycles: nodes: 1 walltime: time.struct_time(tm_year=1900, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=2, tm_sec=0, tm_wday=0, tm_yday=1, tm_isdst=-1) plugin: 'shell' - command: '$PWD/examples/files/scripts/extpar' - cli arguments: positional=None keyword={'--input': 'obs_data'} flags=['--verbose'] source_file=None + command: 'scripts/extpar' + cli arguments: '--verbose {--input obs_data}' + env source files: [] - icon_bimonthly [date: 2025-01-01 00:00:00]: tasks: - preproc [date: 2025-01-01 00:00:00]: @@ -31,8 +32,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/cleanup.sh' - cli arguments: positional=['grid_file'] keyword={'-p': 'extpar_file', '-e': 'ERA5'} flags=None source_file='dummy_source_file' + command: 'scripts/cleanup.sh' + cli arguments: '{-p extpar_file} {-e ERA5} {grid_file}' + env source files: [] - icon [date: 2025-01-01 00:00:00]: input: - grid_file @@ -48,8 +50,10 @@ cycles: walltime: time.struct_time(tm_year=1900, tm_mon=1, tm_mday=1, tm_hour=23, tm_min=59, tm_sec=59, tm_wday=0, tm_yday=1, tm_isdst=-1) start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 - plugin: 'icon' - namelists: {'master': 'path/to/mater_nml', 'model': 'path/to/model_nml'} + plugin: 'shell' + command: 'scripts/icon' + cli arguments: '{-g grid_file} {--input icon_input}' + env source files: [] - postproc_1 [date: 2025-01-01 00:00:00]: input: - stream_1 [date: 2025-01-01 00:00:00] @@ -63,8 +67,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/main_script_ocn.sh' - cli arguments: positional=None keyword={'--input': 'stream_1'} flags=None source_file=None + command: 'scripts/main_script_ocn.sh' + cli arguments: '{--input stream_1}' + env source files: [] - store_and_clean_1 [date: 2025-01-01 00:00:00]: input: - postout_1 [date: 2025-01-01 00:00:00] @@ -79,8 +84,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/post_clean.sh' - cli arguments: positional=None keyword={'--input': 'postout_1', '--stream': 'stream_1', '--icon_input': 'icon_input'} flags=None source_file=None + command: 'scripts/post_clean.sh' + cli arguments: '{--input postout_1} {--stream stream_1} {--icon_input icon_input}' + env source files: [] - icon_bimonthly [date: 2025-03-01 00:00:00]: tasks: - preproc [date: 2025-03-01 00:00:00]: @@ -98,8 +104,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/cleanup.sh' - cli arguments: positional=['grid_file'] keyword={'-p': 'extpar_file', '-e': 'ERA5'} flags=None source_file='dummy_source_file' + command: 'scripts/cleanup.sh' + cli arguments: '{-p extpar_file} {-e ERA5} {grid_file}' + env source files: [] - icon [date: 2025-03-01 00:00:00]: input: - grid_file @@ -116,8 +123,10 @@ cycles: walltime: time.struct_time(tm_year=1900, tm_mon=1, tm_mday=1, tm_hour=23, tm_min=59, tm_sec=59, tm_wday=0, tm_yday=1, tm_isdst=-1) start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 - plugin: 'icon' - namelists: {'master': 'path/to/mater_nml', 'model': 'path/to/model_nml'} + plugin: 'shell' + command: 'scripts/icon' + cli arguments: '{-g grid_file} {--input icon_input}' + env source files: [] - postproc_1 [date: 2025-03-01 00:00:00]: input: - stream_1 [date: 2025-03-01 00:00:00] @@ -131,8 +140,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/main_script_ocn.sh' - cli arguments: positional=None keyword={'--input': 'stream_1'} flags=None source_file=None + command: 'scripts/main_script_ocn.sh' + cli arguments: '{--input stream_1}' + env source files: [] - store_and_clean_1 [date: 2025-03-01 00:00:00]: input: - postout_1 [date: 2025-03-01 00:00:00] @@ -147,8 +157,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/post_clean.sh' - cli arguments: positional=None keyword={'--input': 'postout_1', '--stream': 'stream_1', '--icon_input': 'icon_input'} flags=None source_file=None + command: 'scripts/post_clean.sh' + cli arguments: '{--input postout_1} {--stream stream_1} {--icon_input icon_input}' + env source files: [] - icon_bimonthly [date: 2025-05-01 00:00:00]: tasks: - preproc [date: 2025-05-01 00:00:00]: @@ -168,8 +179,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/cleanup.sh' - cli arguments: positional=['grid_file'] keyword={'-p': 'extpar_file', '-e': 'ERA5'} flags=None source_file='dummy_source_file' + command: 'scripts/cleanup.sh' + cli arguments: '{-p extpar_file} {-e ERA5} {grid_file}' + env source files: [] - icon [date: 2025-05-01 00:00:00]: input: - grid_file @@ -186,8 +198,10 @@ cycles: walltime: time.struct_time(tm_year=1900, tm_mon=1, tm_mday=1, tm_hour=23, tm_min=59, tm_sec=59, tm_wday=0, tm_yday=1, tm_isdst=-1) start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 - plugin: 'icon' - namelists: {'master': 'path/to/mater_nml', 'model': 'path/to/model_nml'} + plugin: 'shell' + command: 'scripts/icon' + cli arguments: '{-g grid_file} {--input icon_input}' + env source files: [] - postproc_1 [date: 2025-05-01 00:00:00]: input: - stream_1 [date: 2025-05-01 00:00:00] @@ -201,8 +215,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/main_script_ocn.sh' - cli arguments: positional=None keyword={'--input': 'stream_1'} flags=None source_file=None + command: 'scripts/main_script_ocn.sh' + cli arguments: '{--input stream_1}' + env source files: [] - store_and_clean_1 [date: 2025-05-01 00:00:00]: input: - postout_1 [date: 2025-05-01 00:00:00] @@ -217,8 +232,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/post_clean.sh' - cli arguments: positional=None keyword={'--input': 'postout_1', '--stream': 'stream_1', '--icon_input': 'icon_input'} flags=None source_file=None + command: 'scripts/post_clean.sh' + cli arguments: '{--input postout_1} {--stream stream_1} {--icon_input icon_input}' + env source files: [] - icon_bimonthly [date: 2025-07-01 00:00:00]: tasks: - preproc [date: 2025-07-01 00:00:00]: @@ -238,8 +254,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/cleanup.sh' - cli arguments: positional=['grid_file'] keyword={'-p': 'extpar_file', '-e': 'ERA5'} flags=None source_file='dummy_source_file' + command: 'scripts/cleanup.sh' + cli arguments: '{-p extpar_file} {-e ERA5} {grid_file}' + env source files: [] - icon [date: 2025-07-01 00:00:00]: input: - grid_file @@ -256,8 +273,10 @@ cycles: walltime: time.struct_time(tm_year=1900, tm_mon=1, tm_mday=1, tm_hour=23, tm_min=59, tm_sec=59, tm_wday=0, tm_yday=1, tm_isdst=-1) start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 - plugin: 'icon' - namelists: {'master': 'path/to/mater_nml', 'model': 'path/to/model_nml'} + plugin: 'shell' + command: 'scripts/icon' + cli arguments: '{-g grid_file} {--input icon_input}' + env source files: [] - postproc_1 [date: 2025-07-01 00:00:00]: input: - stream_1 [date: 2025-07-01 00:00:00] @@ -271,8 +290,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/main_script_ocn.sh' - cli arguments: positional=None keyword={'--input': 'stream_1'} flags=None source_file=None + command: 'scripts/main_script_ocn.sh' + cli arguments: '{--input stream_1}' + env source files: [] - store_and_clean_1 [date: 2025-07-01 00:00:00]: input: - postout_1 [date: 2025-07-01 00:00:00] @@ -287,8 +307,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/post_clean.sh' - cli arguments: positional=None keyword={'--input': 'postout_1', '--stream': 'stream_1', '--icon_input': 'icon_input'} flags=None source_file=None + command: 'scripts/post_clean.sh' + cli arguments: '{--input postout_1} {--stream stream_1} {--icon_input icon_input}' + env source files: [] - icon_bimonthly [date: 2025-09-01 00:00:00]: tasks: - preproc [date: 2025-09-01 00:00:00]: @@ -308,8 +329,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/cleanup.sh' - cli arguments: positional=['grid_file'] keyword={'-p': 'extpar_file', '-e': 'ERA5'} flags=None source_file='dummy_source_file' + command: 'scripts/cleanup.sh' + cli arguments: '{-p extpar_file} {-e ERA5} {grid_file}' + env source files: [] - icon [date: 2025-09-01 00:00:00]: input: - grid_file @@ -326,8 +348,10 @@ cycles: walltime: time.struct_time(tm_year=1900, tm_mon=1, tm_mday=1, tm_hour=23, tm_min=59, tm_sec=59, tm_wday=0, tm_yday=1, tm_isdst=-1) start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 - plugin: 'icon' - namelists: {'master': 'path/to/mater_nml', 'model': 'path/to/model_nml'} + plugin: 'shell' + command: 'scripts/icon' + cli arguments: '{-g grid_file} {--input icon_input}' + env source files: [] - postproc_1 [date: 2025-09-01 00:00:00]: input: - stream_1 [date: 2025-09-01 00:00:00] @@ -341,8 +365,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/main_script_ocn.sh' - cli arguments: positional=None keyword={'--input': 'stream_1'} flags=None source_file=None + command: 'scripts/main_script_ocn.sh' + cli arguments: '{--input stream_1}' + env source files: [] - store_and_clean_1 [date: 2025-09-01 00:00:00]: input: - postout_1 [date: 2025-09-01 00:00:00] @@ -357,8 +382,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/post_clean.sh' - cli arguments: positional=None keyword={'--input': 'postout_1', '--stream': 'stream_1', '--icon_input': 'icon_input'} flags=None source_file=None + command: 'scripts/post_clean.sh' + cli arguments: '{--input postout_1} {--stream stream_1} {--icon_input icon_input}' + env source files: [] - icon_bimonthly [date: 2025-11-01 00:00:00]: tasks: - preproc [date: 2025-11-01 00:00:00]: @@ -378,8 +404,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/cleanup.sh' - cli arguments: positional=['grid_file'] keyword={'-p': 'extpar_file', '-e': 'ERA5'} flags=None source_file='dummy_source_file' + command: 'scripts/cleanup.sh' + cli arguments: '{-p extpar_file} {-e ERA5} {grid_file}' + env source files: [] - icon [date: 2025-11-01 00:00:00]: input: - grid_file @@ -396,8 +423,10 @@ cycles: walltime: time.struct_time(tm_year=1900, tm_mon=1, tm_mday=1, tm_hour=23, tm_min=59, tm_sec=59, tm_wday=0, tm_yday=1, tm_isdst=-1) start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 - plugin: 'icon' - namelists: {'master': 'path/to/mater_nml', 'model': 'path/to/model_nml'} + plugin: 'shell' + command: 'scripts/icon' + cli arguments: '{-g grid_file} {--input icon_input}' + env source files: [] - postproc_1 [date: 2025-11-01 00:00:00]: input: - stream_1 [date: 2025-11-01 00:00:00] @@ -411,8 +440,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/main_script_ocn.sh' - cli arguments: positional=None keyword={'--input': 'stream_1'} flags=None source_file=None + command: 'scripts/main_script_ocn.sh' + cli arguments: '{--input stream_1}' + env source files: [] - store_and_clean_1 [date: 2025-11-01 00:00:00]: input: - postout_1 [date: 2025-11-01 00:00:00] @@ -427,8 +457,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/post_clean.sh' - cli arguments: positional=None keyword={'--input': 'postout_1', '--stream': 'stream_1', '--icon_input': 'icon_input'} flags=None source_file=None + command: 'scripts/post_clean.sh' + cli arguments: '{--input postout_1} {--stream stream_1} {--icon_input icon_input}' + env source files: [] - icon_bimonthly [date: 2026-01-01 00:00:00]: tasks: - preproc [date: 2026-01-01 00:00:00]: @@ -448,8 +479,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/cleanup.sh' - cli arguments: positional=['grid_file'] keyword={'-p': 'extpar_file', '-e': 'ERA5'} flags=None source_file='dummy_source_file' + command: 'scripts/cleanup.sh' + cli arguments: '{-p extpar_file} {-e ERA5} {grid_file}' + env source files: [] - icon [date: 2026-01-01 00:00:00]: input: - grid_file @@ -466,8 +498,10 @@ cycles: walltime: time.struct_time(tm_year=1900, tm_mon=1, tm_mday=1, tm_hour=23, tm_min=59, tm_sec=59, tm_wday=0, tm_yday=1, tm_isdst=-1) start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 - plugin: 'icon' - namelists: {'master': 'path/to/mater_nml', 'model': 'path/to/model_nml'} + plugin: 'shell' + command: 'scripts/icon' + cli arguments: '{-g grid_file} {--input icon_input}' + env source files: [] - postproc_1 [date: 2026-01-01 00:00:00]: input: - stream_1 [date: 2026-01-01 00:00:00] @@ -481,8 +515,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/main_script_ocn.sh' - cli arguments: positional=None keyword={'--input': 'stream_1'} flags=None source_file=None + command: 'scripts/main_script_ocn.sh' + cli arguments: '{--input stream_1}' + env source files: [] - store_and_clean_1 [date: 2026-01-01 00:00:00]: input: - postout_1 [date: 2026-01-01 00:00:00] @@ -497,8 +532,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/post_clean.sh' - cli arguments: positional=None keyword={'--input': 'postout_1', '--stream': 'stream_1', '--icon_input': 'icon_input'} flags=None source_file=None + command: 'scripts/post_clean.sh' + cli arguments: '{--input postout_1} {--stream stream_1} {--icon_input icon_input}' + env source files: [] - icon_bimonthly [date: 2026-03-01 00:00:00]: tasks: - preproc [date: 2026-03-01 00:00:00]: @@ -518,8 +554,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/cleanup.sh' - cli arguments: positional=['grid_file'] keyword={'-p': 'extpar_file', '-e': 'ERA5'} flags=None source_file='dummy_source_file' + command: 'scripts/cleanup.sh' + cli arguments: '{-p extpar_file} {-e ERA5} {grid_file}' + env source files: [] - icon [date: 2026-03-01 00:00:00]: input: - grid_file @@ -536,8 +573,10 @@ cycles: walltime: time.struct_time(tm_year=1900, tm_mon=1, tm_mday=1, tm_hour=23, tm_min=59, tm_sec=59, tm_wday=0, tm_yday=1, tm_isdst=-1) start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 - plugin: 'icon' - namelists: {'master': 'path/to/mater_nml', 'model': 'path/to/model_nml'} + plugin: 'shell' + command: 'scripts/icon' + cli arguments: '{-g grid_file} {--input icon_input}' + env source files: [] - postproc_1 [date: 2026-03-01 00:00:00]: input: - stream_1 [date: 2026-03-01 00:00:00] @@ -551,8 +590,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/main_script_ocn.sh' - cli arguments: positional=None keyword={'--input': 'stream_1'} flags=None source_file=None + command: 'scripts/main_script_ocn.sh' + cli arguments: '{--input stream_1}' + env source files: [] - store_and_clean_1 [date: 2026-03-01 00:00:00]: input: - postout_1 [date: 2026-03-01 00:00:00] @@ -567,8 +607,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/post_clean.sh' - cli arguments: positional=None keyword={'--input': 'postout_1', '--stream': 'stream_1', '--icon_input': 'icon_input'} flags=None source_file=None + command: 'scripts/post_clean.sh' + cli arguments: '{--input postout_1} {--stream stream_1} {--icon_input icon_input}' + env source files: [] - icon_bimonthly [date: 2026-05-01 00:00:00]: tasks: - preproc [date: 2026-05-01 00:00:00]: @@ -588,8 +629,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/cleanup.sh' - cli arguments: positional=['grid_file'] keyword={'-p': 'extpar_file', '-e': 'ERA5'} flags=None source_file='dummy_source_file' + command: 'scripts/cleanup.sh' + cli arguments: '{-p extpar_file} {-e ERA5} {grid_file}' + env source files: [] - icon [date: 2026-05-01 00:00:00]: input: - grid_file @@ -606,8 +648,10 @@ cycles: walltime: time.struct_time(tm_year=1900, tm_mon=1, tm_mday=1, tm_hour=23, tm_min=59, tm_sec=59, tm_wday=0, tm_yday=1, tm_isdst=-1) start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 - plugin: 'icon' - namelists: {'master': 'path/to/mater_nml', 'model': 'path/to/model_nml'} + plugin: 'shell' + command: 'scripts/icon' + cli arguments: '{-g grid_file} {--input icon_input}' + env source files: [] - postproc_1 [date: 2026-05-01 00:00:00]: input: - stream_1 [date: 2026-05-01 00:00:00] @@ -621,8 +665,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/main_script_ocn.sh' - cli arguments: positional=None keyword={'--input': 'stream_1'} flags=None source_file=None + command: 'scripts/main_script_ocn.sh' + cli arguments: '{--input stream_1}' + env source files: [] - store_and_clean_1 [date: 2026-05-01 00:00:00]: input: - postout_1 [date: 2026-05-01 00:00:00] @@ -637,8 +682,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/post_clean.sh' - cli arguments: positional=None keyword={'--input': 'postout_1', '--stream': 'stream_1', '--icon_input': 'icon_input'} flags=None source_file=None + command: 'scripts/post_clean.sh' + cli arguments: '{--input postout_1} {--stream stream_1} {--icon_input icon_input}' + env source files: [] - icon_bimonthly [date: 2026-07-01 00:00:00]: tasks: - preproc [date: 2026-07-01 00:00:00]: @@ -658,8 +704,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/cleanup.sh' - cli arguments: positional=['grid_file'] keyword={'-p': 'extpar_file', '-e': 'ERA5'} flags=None source_file='dummy_source_file' + command: 'scripts/cleanup.sh' + cli arguments: '{-p extpar_file} {-e ERA5} {grid_file}' + env source files: [] - icon [date: 2026-07-01 00:00:00]: input: - grid_file @@ -676,8 +723,10 @@ cycles: walltime: time.struct_time(tm_year=1900, tm_mon=1, tm_mday=1, tm_hour=23, tm_min=59, tm_sec=59, tm_wday=0, tm_yday=1, tm_isdst=-1) start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 - plugin: 'icon' - namelists: {'master': 'path/to/mater_nml', 'model': 'path/to/model_nml'} + plugin: 'shell' + command: 'scripts/icon' + cli arguments: '{-g grid_file} {--input icon_input}' + env source files: [] - postproc_1 [date: 2026-07-01 00:00:00]: input: - stream_1 [date: 2026-07-01 00:00:00] @@ -691,8 +740,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/main_script_ocn.sh' - cli arguments: positional=None keyword={'--input': 'stream_1'} flags=None source_file=None + command: 'scripts/main_script_ocn.sh' + cli arguments: '{--input stream_1}' + env source files: [] - store_and_clean_1 [date: 2026-07-01 00:00:00]: input: - postout_1 [date: 2026-07-01 00:00:00] @@ -707,8 +757,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/post_clean.sh' - cli arguments: positional=None keyword={'--input': 'postout_1', '--stream': 'stream_1', '--icon_input': 'icon_input'} flags=None source_file=None + command: 'scripts/post_clean.sh' + cli arguments: '{--input postout_1} {--stream stream_1} {--icon_input icon_input}' + env source files: [] - icon_bimonthly [date: 2026-09-01 00:00:00]: tasks: - preproc [date: 2026-09-01 00:00:00]: @@ -728,8 +779,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/cleanup.sh' - cli arguments: positional=['grid_file'] keyword={'-p': 'extpar_file', '-e': 'ERA5'} flags=None source_file='dummy_source_file' + command: 'scripts/cleanup.sh' + cli arguments: '{-p extpar_file} {-e ERA5} {grid_file}' + env source files: [] - icon [date: 2026-09-01 00:00:00]: input: - grid_file @@ -746,8 +798,10 @@ cycles: walltime: time.struct_time(tm_year=1900, tm_mon=1, tm_mday=1, tm_hour=23, tm_min=59, tm_sec=59, tm_wday=0, tm_yday=1, tm_isdst=-1) start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 - plugin: 'icon' - namelists: {'master': 'path/to/mater_nml', 'model': 'path/to/model_nml'} + plugin: 'shell' + command: 'scripts/icon' + cli arguments: '{-g grid_file} {--input icon_input}' + env source files: [] - postproc_1 [date: 2026-09-01 00:00:00]: input: - stream_1 [date: 2026-09-01 00:00:00] @@ -761,8 +815,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/main_script_ocn.sh' - cli arguments: positional=None keyword={'--input': 'stream_1'} flags=None source_file=None + command: 'scripts/main_script_ocn.sh' + cli arguments: '{--input stream_1}' + env source files: [] - store_and_clean_1 [date: 2026-09-01 00:00:00]: input: - postout_1 [date: 2026-09-01 00:00:00] @@ -777,8 +832,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/post_clean.sh' - cli arguments: positional=None keyword={'--input': 'postout_1', '--stream': 'stream_1', '--icon_input': 'icon_input'} flags=None source_file=None + command: 'scripts/post_clean.sh' + cli arguments: '{--input postout_1} {--stream stream_1} {--icon_input icon_input}' + env source files: [] - icon_bimonthly [date: 2026-11-01 00:00:00]: tasks: - preproc [date: 2026-11-01 00:00:00]: @@ -798,8 +854,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/cleanup.sh' - cli arguments: positional=['grid_file'] keyword={'-p': 'extpar_file', '-e': 'ERA5'} flags=None source_file='dummy_source_file' + command: 'scripts/cleanup.sh' + cli arguments: '{-p extpar_file} {-e ERA5} {grid_file}' + env source files: [] - icon [date: 2026-11-01 00:00:00]: input: - grid_file @@ -816,8 +873,10 @@ cycles: walltime: time.struct_time(tm_year=1900, tm_mon=1, tm_mday=1, tm_hour=23, tm_min=59, tm_sec=59, tm_wday=0, tm_yday=1, tm_isdst=-1) start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 - plugin: 'icon' - namelists: {'master': 'path/to/mater_nml', 'model': 'path/to/model_nml'} + plugin: 'shell' + command: 'scripts/icon' + cli arguments: '{-g grid_file} {--input icon_input}' + env source files: [] - postproc_1 [date: 2026-11-01 00:00:00]: input: - stream_1 [date: 2026-11-01 00:00:00] @@ -831,8 +890,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/main_script_ocn.sh' - cli arguments: positional=None keyword={'--input': 'stream_1'} flags=None source_file=None + command: 'scripts/main_script_ocn.sh' + cli arguments: '{--input stream_1}' + env source files: [] - store_and_clean_1 [date: 2026-11-01 00:00:00]: input: - postout_1 [date: 2026-11-01 00:00:00] @@ -847,8 +907,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/post_clean.sh' - cli arguments: positional=None keyword={'--input': 'postout_1', '--stream': 'stream_1', '--icon_input': 'icon_input'} flags=None source_file=None + command: 'scripts/post_clean.sh' + cli arguments: '{--input postout_1} {--stream stream_1} {--icon_input icon_input}' + env source files: [] - yearly [date: 2025-01-01 00:00:00]: tasks: - postproc_2 [date: 2025-01-01 00:00:00]: @@ -869,8 +930,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/main_script_atm.sh' - cli arguments: positional=None keyword={'--input': 'stream_2'} flags=None source_file=None + command: 'scripts/main_script_atm.sh' + cli arguments: '{--input stream_2}' + env source files: [] src: 'path/to/src/dir' - store_and_clean_2 [date: 2025-01-01 00:00:00]: input: @@ -890,8 +952,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/post_clean.sh' - cli arguments: positional=None keyword={'--input': 'postout_2'} flags=None source_file=None + command: 'scripts/post_clean.sh' + cli arguments: '{--input postout_2}' + env source files: [] - yearly [date: 2026-01-01 00:00:00]: tasks: - postproc_2 [date: 2026-01-01 00:00:00]: @@ -912,8 +975,9 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/main_script_atm.sh' - cli arguments: positional=None keyword={'--input': 'stream_2'} flags=None source_file=None + command: 'scripts/main_script_atm.sh' + cli arguments: '{--input stream_2}' + env source files: [] src: 'path/to/src/dir' - store_and_clean_2 [date: 2026-01-01 00:00:00]: input: @@ -933,5 +997,6 @@ cycles: start date: 2025-01-01 00:00:00 end date: 2027-01-01 00:00:00 plugin: 'shell' - command: '$PWD/examples/files/scripts/post_clean.sh' - cli arguments: positional=None keyword={'--input': 'postout_2'} flags=None source_file=None \ No newline at end of file + command: 'scripts/post_clean.sh' + cli arguments: '{--input postout_2}' + env source files: [] \ No newline at end of file diff --git a/tests/cases/parameters/config/data/forcing b/tests/cases/parameters/config/data/forcing new file mode 100644 index 00000000..e69de29b diff --git a/tests/cases/parameters/config/data/initial_conditions b/tests/cases/parameters/config/data/initial_conditions new file mode 100644 index 00000000..e69de29b diff --git a/tests/cases/parameters/config/scripts/icon.py b/tests/cases/parameters/config/scripts/icon.py new file mode 100755 index 00000000..32f71ed6 --- /dev/null +++ b/tests/cases/parameters/config/scripts/icon.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +"""usage: icon.py [-h] [--init [INIT]] [--restart [RESTART]] [--forcing [FORCING]] [namelist] + +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 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("namelist", nargs="?", default=None) + parser.add_argument("--restart", nargs="?", type=str, help="The icon restart file.") + parser.add_argument("--forcing", nargs="?", type=str, help="The icon forcing file.") + + args = parser.parse_args() + + output = Path("icon_output") + output.write_text("") + + if args.restart: + if args.init: + msg = "Cannot use '--init' and '--restart' option at the same time." + raise ValueError(msg) + if not Path(args.restart).exists(): + msg = f"The icon restart file {args.restart!r} was not found." + raise FileNotFoundError(msg) + restart = Path(args.restart) + + log(f"Restarting from file {args.restart!r}.") + elif args.init: + if not Path(args.init).exists(): + msg = f"The icon init file {args.init!r} was not found." + raise FileNotFoundError(msg) + + log(f"Starting from init file {args.init!r}.") + else: + msg = "Please provide a restart or init file with the corresponding option." + raise ValueError(msg) + + if args.namelist: + log(f"Namelist {args.namelist} provided. Continue with it.") + else: + log("No namelist provided. Continue with default one.") + + # Main script execution continues here + log("Script finished running calculations") + + restart = Path("restart") + restart.write_text("") + + +if __name__ == "__main__": + main() diff --git a/tests/cases/parameters/config/scripts/merge.py b/tests/cases/parameters/config/scripts/merge.py new file mode 100755 index 00000000..2fa94152 --- /dev/null +++ b/tests/cases/parameters/config/scripts/merge.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import argparse +from pathlib import Path + + +def main(): + parser = argparse.ArgumentParser(description="A script mocking parts of icon in a form of a shell script.") + parser.add_argument("file", nargs="+", type=str, help="The files to analyse.") + args = parser.parse_args() + Path("analysis").write_text(f"analysis for file {args.file}") + + +if __name__ == "__main__": + main() diff --git a/tests/cases/parameters/config/scripts/statistics.py b/tests/cases/parameters/config/scripts/statistics.py new file mode 100755 index 00000000..2fa94152 --- /dev/null +++ b/tests/cases/parameters/config/scripts/statistics.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import argparse +from pathlib import Path + + +def main(): + parser = argparse.ArgumentParser(description="A script mocking parts of icon in a form of a shell script.") + parser.add_argument("file", nargs="+", type=str, help="The files to analyse.") + args = parser.parse_args() + Path("analysis").write_text(f"analysis for file {args.file}") + + +if __name__ == "__main__": + main() diff --git a/tests/cases/parameters/config/test_config_parameters.yml b/tests/cases/parameters/config/test_config_parameters.yml index ec993af9..9cc8a3e6 100644 --- a/tests/cases/parameters/config/test_config_parameters.yml +++ b/tests/cases/parameters/config/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: @@ -10,7 +10,7 @@ cycles: tasks: - icon: inputs: - - initial conditions: + - initial_conditions: when: at: *root_start_date - icon_restart: @@ -39,40 +39,38 @@ cycles: - merge: inputs: - analysis_foo_bar: - lag: ['P0M', 'P2M', 'P4M', 'P6M', 'P8M', 'P10M'] + lag: ['P0M'] outputs: [yearly_analysis] tasks: - icon: plugin: shell - command: $PWD/tests/files/scripts/icon.py - cli_arguments: - keyword: - --restart: icon_restart + command: scripts/icon.py + cli_arguments: "{--restart icon_restart} {--init initial_conditions} {--forcing forcing}" parameters: [foo, bar] - statistics_foo: plugin: shell - command: $PWD/tests/files/scripts/statistics.py + command: scripts/statistics.py parameters: [bar] - statistics_foo_bar: plugin: shell - command: $PWD/tests/files/scripts/statistics.py + command: scripts/statistics.py - merge: plugin: shell - command: $PWD/tests/files/scripts/merge.py + command: scripts/merge.py data: available: - - initial conditions: + - initial_conditions: type: file - src: . + src: data/initial_conditions - forcing: type: file - src: . + src: data/forcing generated: - icon_output: type: file - src: output + src: icon_output parameters: [foo, bar] - icon_restart: type: file @@ -80,15 +78,15 @@ data: parameters: [foo, bar] - analysis_foo: type: file - src: analysis_foo + src: analysis parameters: [bar] - analysis_foo_bar: type: file - src: foo_analysis_bar + src: analysis - yearly_analysis: type: file - src: yearly_analysis + src: analysis parameters: - foo: [0, 1, 2] + foo: [0, 1] bar: [3.0, 3.5] diff --git a/tests/cases/parameters/data/test_config_parameters.txt b/tests/cases/parameters/data/test_config_parameters.txt index fc0a8282..d41c87ba 100644 --- a/tests/cases/parameters/data/test_config_parameters.txt +++ b/tests/cases/parameters/data/test_config_parameters.txt @@ -3,7 +3,7 @@ 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] @@ -11,13 +11,14 @@ cycles: name: 'icon' coordinates: {'date': datetime.datetime(2026, 1, 1, 0, 0), 'foo': 0, 'bar': 3.0} start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 + end date: 2026-03-01 00:00:00 plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None + command: 'scripts/icon.py' + cli arguments: '{--restart icon_restart} {--init initial_conditions} {--forcing forcing}' + env source files: [] - 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] @@ -25,13 +26,14 @@ cycles: name: 'icon' coordinates: {'date': datetime.datetime(2026, 1, 1, 0, 0), 'foo': 0, 'bar': 3.5} start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 + end date: 2026-03-01 00:00:00 plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None + command: 'scripts/icon.py' + cli arguments: '{--restart icon_restart} {--init initial_conditions} {--forcing forcing}' + env source files: [] - 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] @@ -39,13 +41,14 @@ cycles: name: 'icon' coordinates: {'date': datetime.datetime(2026, 1, 1, 0, 0), 'foo': 1, 'bar': 3.0} start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 + end date: 2026-03-01 00:00:00 plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None + command: 'scripts/icon.py' + cli arguments: '{--restart icon_restart} {--init initial_conditions} {--forcing forcing}' + env source files: [] - 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] @@ -53,64 +56,39 @@ cycles: name: 'icon' coordinates: {'date': datetime.datetime(2026, 1, 1, 0, 0), 'foo': 1, 'bar': 3.5} start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 + end date: 2026-03-01 00:00:00 plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-01-01 00:00:00, foo: 2, bar: 3.0]: - input: - - 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] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 1, 1, 0, 0), 'foo': 2, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-01-01 00:00:00, foo: 2, bar: 3.5]: - input: - - initial conditions - - forcing - output: - - icon_output [date: 2026-01-01 00:00:00, foo: 2, bar: 3.5] - - icon_restart [date: 2026-01-01 00:00:00, foo: 2, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 1, 1, 0, 0), 'foo': 2, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None + command: 'scripts/icon.py' + cli arguments: '{--restart icon_restart} {--init initial_conditions} {--forcing forcing}' + env source files: [] - statistics_foo [date: 2026-01-01 00:00:00, bar: 3.0]: input: - icon_output [date: 2026-01-01 00:00:00, foo: 0, bar: 3.0] - icon_output [date: 2026-01-01 00:00:00, foo: 1, bar: 3.0] - - icon_output [date: 2026-01-01 00:00:00, foo: 2, bar: 3.0] output: - analysis_foo [date: 2026-01-01 00:00:00, bar: 3.0] name: 'statistics_foo' coordinates: {'date': datetime.datetime(2026, 1, 1, 0, 0), 'bar': 3.0} start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 + end date: 2026-03-01 00:00:00 plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' + command: 'scripts/statistics.py' + cli arguments: '' + env source files: [] - statistics_foo [date: 2026-01-01 00:00:00, bar: 3.5]: input: - icon_output [date: 2026-01-01 00:00:00, foo: 0, bar: 3.5] - icon_output [date: 2026-01-01 00:00:00, foo: 1, bar: 3.5] - - icon_output [date: 2026-01-01 00:00:00, foo: 2, bar: 3.5] output: - analysis_foo [date: 2026-01-01 00:00:00, bar: 3.5] name: 'statistics_foo' coordinates: {'date': datetime.datetime(2026, 1, 1, 0, 0), 'bar': 3.5} start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 + end date: 2026-03-01 00:00:00 plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' + command: 'scripts/statistics.py' + cli arguments: '' + env source files: [] - statistics_foo_bar [date: 2026-01-01 00:00:00]: input: - analysis_foo [date: 2026-01-01 00:00:00, bar: 3.5] @@ -120,1406 +98,23 @@ cycles: name: 'statistics_foo_bar' coordinates: {'date': datetime.datetime(2026, 1, 1, 0, 0)} start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - bimonthly_tasks [date: 2026-03-01 00:00:00]: - tasks: - - icon [date: 2026-03-01 00:00:00, foo: 0, bar: 3.0]: - input: - - icon_restart [date: 2026-01-01 00:00:00, foo: 0, bar: 3.0] - - forcing - output: - - icon_output [date: 2026-03-01 00:00:00, foo: 0, bar: 3.0] - - icon_restart [date: 2026-03-01 00:00:00, foo: 0, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 3, 1, 0, 0), 'foo': 0, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-03-01 00:00:00, foo: 0, bar: 3.5]: - input: - - icon_restart [date: 2026-01-01 00:00:00, foo: 0, bar: 3.5] - - forcing - output: - - icon_output [date: 2026-03-01 00:00:00, foo: 0, bar: 3.5] - - icon_restart [date: 2026-03-01 00:00:00, foo: 0, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 3, 1, 0, 0), 'foo': 0, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-03-01 00:00:00, foo: 1, bar: 3.0]: - input: - - icon_restart [date: 2026-01-01 00:00:00, foo: 1, bar: 3.0] - - forcing - output: - - icon_output [date: 2026-03-01 00:00:00, foo: 1, bar: 3.0] - - icon_restart [date: 2026-03-01 00:00:00, foo: 1, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 3, 1, 0, 0), 'foo': 1, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-03-01 00:00:00, foo: 1, bar: 3.5]: - input: - - icon_restart [date: 2026-01-01 00:00:00, foo: 1, bar: 3.5] - - forcing - output: - - icon_output [date: 2026-03-01 00:00:00, foo: 1, bar: 3.5] - - icon_restart [date: 2026-03-01 00:00:00, foo: 1, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 3, 1, 0, 0), 'foo': 1, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-03-01 00:00:00, foo: 2, bar: 3.0]: - input: - - icon_restart [date: 2026-01-01 00:00:00, foo: 2, bar: 3.0] - - forcing - output: - - icon_output [date: 2026-03-01 00:00:00, foo: 2, bar: 3.0] - - icon_restart [date: 2026-03-01 00:00:00, foo: 2, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 3, 1, 0, 0), 'foo': 2, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-03-01 00:00:00, foo: 2, bar: 3.5]: - input: - - icon_restart [date: 2026-01-01 00:00:00, foo: 2, bar: 3.5] - - forcing - output: - - icon_output [date: 2026-03-01 00:00:00, foo: 2, bar: 3.5] - - icon_restart [date: 2026-03-01 00:00:00, foo: 2, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 3, 1, 0, 0), 'foo': 2, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - statistics_foo [date: 2026-03-01 00:00:00, bar: 3.0]: - input: - - icon_output [date: 2026-03-01 00:00:00, foo: 0, bar: 3.0] - - icon_output [date: 2026-03-01 00:00:00, foo: 1, bar: 3.0] - - icon_output [date: 2026-03-01 00:00:00, foo: 2, bar: 3.0] - output: - - analysis_foo [date: 2026-03-01 00:00:00, bar: 3.0] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2026, 3, 1, 0, 0), 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo [date: 2026-03-01 00:00:00, bar: 3.5]: - input: - - icon_output [date: 2026-03-01 00:00:00, foo: 0, bar: 3.5] - - icon_output [date: 2026-03-01 00:00:00, foo: 1, bar: 3.5] - - icon_output [date: 2026-03-01 00:00:00, foo: 2, bar: 3.5] - output: - - analysis_foo [date: 2026-03-01 00:00:00, bar: 3.5] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2026, 3, 1, 0, 0), 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo_bar [date: 2026-03-01 00:00:00]: - input: - - analysis_foo [date: 2026-03-01 00:00:00, bar: 3.5] - - analysis_foo [date: 2026-03-01 00:00:00, bar: 3.0] - output: - - analysis_foo_bar [date: 2026-03-01 00:00:00] - name: 'statistics_foo_bar' - coordinates: {'date': datetime.datetime(2026, 3, 1, 0, 0)} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - bimonthly_tasks [date: 2026-05-01 00:00:00]: - tasks: - - icon [date: 2026-05-01 00:00:00, foo: 0, bar: 3.0]: - input: - - icon_restart [date: 2026-03-01 00:00:00, foo: 0, bar: 3.0] - - forcing - output: - - icon_output [date: 2026-05-01 00:00:00, foo: 0, bar: 3.0] - - icon_restart [date: 2026-05-01 00:00:00, foo: 0, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 5, 1, 0, 0), 'foo': 0, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-05-01 00:00:00, foo: 0, bar: 3.5]: - input: - - icon_restart [date: 2026-03-01 00:00:00, foo: 0, bar: 3.5] - - forcing - output: - - icon_output [date: 2026-05-01 00:00:00, foo: 0, bar: 3.5] - - icon_restart [date: 2026-05-01 00:00:00, foo: 0, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 5, 1, 0, 0), 'foo': 0, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-05-01 00:00:00, foo: 1, bar: 3.0]: - input: - - icon_restart [date: 2026-03-01 00:00:00, foo: 1, bar: 3.0] - - forcing - output: - - icon_output [date: 2026-05-01 00:00:00, foo: 1, bar: 3.0] - - icon_restart [date: 2026-05-01 00:00:00, foo: 1, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 5, 1, 0, 0), 'foo': 1, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-05-01 00:00:00, foo: 1, bar: 3.5]: - input: - - icon_restart [date: 2026-03-01 00:00:00, foo: 1, bar: 3.5] - - forcing - output: - - icon_output [date: 2026-05-01 00:00:00, foo: 1, bar: 3.5] - - icon_restart [date: 2026-05-01 00:00:00, foo: 1, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 5, 1, 0, 0), 'foo': 1, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-05-01 00:00:00, foo: 2, bar: 3.0]: - input: - - icon_restart [date: 2026-03-01 00:00:00, foo: 2, bar: 3.0] - - forcing - output: - - icon_output [date: 2026-05-01 00:00:00, foo: 2, bar: 3.0] - - icon_restart [date: 2026-05-01 00:00:00, foo: 2, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 5, 1, 0, 0), 'foo': 2, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-05-01 00:00:00, foo: 2, bar: 3.5]: - input: - - icon_restart [date: 2026-03-01 00:00:00, foo: 2, bar: 3.5] - - forcing - output: - - icon_output [date: 2026-05-01 00:00:00, foo: 2, bar: 3.5] - - icon_restart [date: 2026-05-01 00:00:00, foo: 2, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 5, 1, 0, 0), 'foo': 2, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - statistics_foo [date: 2026-05-01 00:00:00, bar: 3.0]: - input: - - icon_output [date: 2026-05-01 00:00:00, foo: 0, bar: 3.0] - - icon_output [date: 2026-05-01 00:00:00, foo: 1, bar: 3.0] - - icon_output [date: 2026-05-01 00:00:00, foo: 2, bar: 3.0] - output: - - analysis_foo [date: 2026-05-01 00:00:00, bar: 3.0] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2026, 5, 1, 0, 0), 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo [date: 2026-05-01 00:00:00, bar: 3.5]: - input: - - icon_output [date: 2026-05-01 00:00:00, foo: 0, bar: 3.5] - - icon_output [date: 2026-05-01 00:00:00, foo: 1, bar: 3.5] - - icon_output [date: 2026-05-01 00:00:00, foo: 2, bar: 3.5] - output: - - analysis_foo [date: 2026-05-01 00:00:00, bar: 3.5] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2026, 5, 1, 0, 0), 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo_bar [date: 2026-05-01 00:00:00]: - input: - - analysis_foo [date: 2026-05-01 00:00:00, bar: 3.5] - - analysis_foo [date: 2026-05-01 00:00:00, bar: 3.0] - output: - - analysis_foo_bar [date: 2026-05-01 00:00:00] - name: 'statistics_foo_bar' - coordinates: {'date': datetime.datetime(2026, 5, 1, 0, 0)} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - bimonthly_tasks [date: 2026-07-01 00:00:00]: - tasks: - - icon [date: 2026-07-01 00:00:00, foo: 0, bar: 3.0]: - input: - - icon_restart [date: 2026-05-01 00:00:00, foo: 0, bar: 3.0] - - forcing - output: - - icon_output [date: 2026-07-01 00:00:00, foo: 0, bar: 3.0] - - icon_restart [date: 2026-07-01 00:00:00, foo: 0, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 7, 1, 0, 0), 'foo': 0, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-07-01 00:00:00, foo: 0, bar: 3.5]: - input: - - icon_restart [date: 2026-05-01 00:00:00, foo: 0, bar: 3.5] - - forcing - output: - - icon_output [date: 2026-07-01 00:00:00, foo: 0, bar: 3.5] - - icon_restart [date: 2026-07-01 00:00:00, foo: 0, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 7, 1, 0, 0), 'foo': 0, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-07-01 00:00:00, foo: 1, bar: 3.0]: - input: - - icon_restart [date: 2026-05-01 00:00:00, foo: 1, bar: 3.0] - - forcing - output: - - icon_output [date: 2026-07-01 00:00:00, foo: 1, bar: 3.0] - - icon_restart [date: 2026-07-01 00:00:00, foo: 1, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 7, 1, 0, 0), 'foo': 1, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-07-01 00:00:00, foo: 1, bar: 3.5]: - input: - - icon_restart [date: 2026-05-01 00:00:00, foo: 1, bar: 3.5] - - forcing - output: - - icon_output [date: 2026-07-01 00:00:00, foo: 1, bar: 3.5] - - icon_restart [date: 2026-07-01 00:00:00, foo: 1, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 7, 1, 0, 0), 'foo': 1, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-07-01 00:00:00, foo: 2, bar: 3.0]: - input: - - icon_restart [date: 2026-05-01 00:00:00, foo: 2, bar: 3.0] - - forcing - output: - - icon_output [date: 2026-07-01 00:00:00, foo: 2, bar: 3.0] - - icon_restart [date: 2026-07-01 00:00:00, foo: 2, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 7, 1, 0, 0), 'foo': 2, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-07-01 00:00:00, foo: 2, bar: 3.5]: - input: - - icon_restart [date: 2026-05-01 00:00:00, foo: 2, bar: 3.5] - - forcing - output: - - icon_output [date: 2026-07-01 00:00:00, foo: 2, bar: 3.5] - - icon_restart [date: 2026-07-01 00:00:00, foo: 2, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 7, 1, 0, 0), 'foo': 2, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - statistics_foo [date: 2026-07-01 00:00:00, bar: 3.0]: - input: - - icon_output [date: 2026-07-01 00:00:00, foo: 0, bar: 3.0] - - icon_output [date: 2026-07-01 00:00:00, foo: 1, bar: 3.0] - - icon_output [date: 2026-07-01 00:00:00, foo: 2, bar: 3.0] - output: - - analysis_foo [date: 2026-07-01 00:00:00, bar: 3.0] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2026, 7, 1, 0, 0), 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo [date: 2026-07-01 00:00:00, bar: 3.5]: - input: - - icon_output [date: 2026-07-01 00:00:00, foo: 0, bar: 3.5] - - icon_output [date: 2026-07-01 00:00:00, foo: 1, bar: 3.5] - - icon_output [date: 2026-07-01 00:00:00, foo: 2, bar: 3.5] - output: - - analysis_foo [date: 2026-07-01 00:00:00, bar: 3.5] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2026, 7, 1, 0, 0), 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo_bar [date: 2026-07-01 00:00:00]: - input: - - analysis_foo [date: 2026-07-01 00:00:00, bar: 3.5] - - analysis_foo [date: 2026-07-01 00:00:00, bar: 3.0] - output: - - analysis_foo_bar [date: 2026-07-01 00:00:00] - name: 'statistics_foo_bar' - coordinates: {'date': datetime.datetime(2026, 7, 1, 0, 0)} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - bimonthly_tasks [date: 2026-09-01 00:00:00]: - tasks: - - icon [date: 2026-09-01 00:00:00, foo: 0, bar: 3.0]: - input: - - icon_restart [date: 2026-07-01 00:00:00, foo: 0, bar: 3.0] - - forcing - output: - - icon_output [date: 2026-09-01 00:00:00, foo: 0, bar: 3.0] - - icon_restart [date: 2026-09-01 00:00:00, foo: 0, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 9, 1, 0, 0), 'foo': 0, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-09-01 00:00:00, foo: 0, bar: 3.5]: - input: - - icon_restart [date: 2026-07-01 00:00:00, foo: 0, bar: 3.5] - - forcing - output: - - icon_output [date: 2026-09-01 00:00:00, foo: 0, bar: 3.5] - - icon_restart [date: 2026-09-01 00:00:00, foo: 0, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 9, 1, 0, 0), 'foo': 0, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-09-01 00:00:00, foo: 1, bar: 3.0]: - input: - - icon_restart [date: 2026-07-01 00:00:00, foo: 1, bar: 3.0] - - forcing - output: - - icon_output [date: 2026-09-01 00:00:00, foo: 1, bar: 3.0] - - icon_restart [date: 2026-09-01 00:00:00, foo: 1, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 9, 1, 0, 0), 'foo': 1, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-09-01 00:00:00, foo: 1, bar: 3.5]: - input: - - icon_restart [date: 2026-07-01 00:00:00, foo: 1, bar: 3.5] - - forcing - output: - - icon_output [date: 2026-09-01 00:00:00, foo: 1, bar: 3.5] - - icon_restart [date: 2026-09-01 00:00:00, foo: 1, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 9, 1, 0, 0), 'foo': 1, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-09-01 00:00:00, foo: 2, bar: 3.0]: - input: - - icon_restart [date: 2026-07-01 00:00:00, foo: 2, bar: 3.0] - - forcing - output: - - icon_output [date: 2026-09-01 00:00:00, foo: 2, bar: 3.0] - - icon_restart [date: 2026-09-01 00:00:00, foo: 2, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 9, 1, 0, 0), 'foo': 2, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-09-01 00:00:00, foo: 2, bar: 3.5]: - input: - - icon_restart [date: 2026-07-01 00:00:00, foo: 2, bar: 3.5] - - forcing - output: - - icon_output [date: 2026-09-01 00:00:00, foo: 2, bar: 3.5] - - icon_restart [date: 2026-09-01 00:00:00, foo: 2, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 9, 1, 0, 0), 'foo': 2, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - statistics_foo [date: 2026-09-01 00:00:00, bar: 3.0]: - input: - - icon_output [date: 2026-09-01 00:00:00, foo: 0, bar: 3.0] - - icon_output [date: 2026-09-01 00:00:00, foo: 1, bar: 3.0] - - icon_output [date: 2026-09-01 00:00:00, foo: 2, bar: 3.0] - output: - - analysis_foo [date: 2026-09-01 00:00:00, bar: 3.0] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2026, 9, 1, 0, 0), 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo [date: 2026-09-01 00:00:00, bar: 3.5]: - input: - - icon_output [date: 2026-09-01 00:00:00, foo: 0, bar: 3.5] - - icon_output [date: 2026-09-01 00:00:00, foo: 1, bar: 3.5] - - icon_output [date: 2026-09-01 00:00:00, foo: 2, bar: 3.5] - output: - - analysis_foo [date: 2026-09-01 00:00:00, bar: 3.5] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2026, 9, 1, 0, 0), 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo_bar [date: 2026-09-01 00:00:00]: - input: - - analysis_foo [date: 2026-09-01 00:00:00, bar: 3.5] - - analysis_foo [date: 2026-09-01 00:00:00, bar: 3.0] - output: - - analysis_foo_bar [date: 2026-09-01 00:00:00] - name: 'statistics_foo_bar' - coordinates: {'date': datetime.datetime(2026, 9, 1, 0, 0)} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 + end date: 2026-03-01 00:00:00 plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - bimonthly_tasks [date: 2026-11-01 00:00:00]: + command: 'scripts/statistics.py' + cli arguments: '' + env source files: [] + - yearly [date: 2026-01-01 00:00:00]: tasks: - - icon [date: 2026-11-01 00:00:00, foo: 0, bar: 3.0]: - input: - - icon_restart [date: 2026-09-01 00:00:00, foo: 0, bar: 3.0] - - forcing - output: - - icon_output [date: 2026-11-01 00:00:00, foo: 0, bar: 3.0] - - icon_restart [date: 2026-11-01 00:00:00, foo: 0, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 11, 1, 0, 0), 'foo': 0, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-11-01 00:00:00, foo: 0, bar: 3.5]: - input: - - icon_restart [date: 2026-09-01 00:00:00, foo: 0, bar: 3.5] - - forcing - output: - - icon_output [date: 2026-11-01 00:00:00, foo: 0, bar: 3.5] - - icon_restart [date: 2026-11-01 00:00:00, foo: 0, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 11, 1, 0, 0), 'foo': 0, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-11-01 00:00:00, foo: 1, bar: 3.0]: - input: - - icon_restart [date: 2026-09-01 00:00:00, foo: 1, bar: 3.0] - - forcing - output: - - icon_output [date: 2026-11-01 00:00:00, foo: 1, bar: 3.0] - - icon_restart [date: 2026-11-01 00:00:00, foo: 1, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 11, 1, 0, 0), 'foo': 1, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-11-01 00:00:00, foo: 1, bar: 3.5]: - input: - - icon_restart [date: 2026-09-01 00:00:00, foo: 1, bar: 3.5] - - forcing - output: - - icon_output [date: 2026-11-01 00:00:00, foo: 1, bar: 3.5] - - icon_restart [date: 2026-11-01 00:00:00, foo: 1, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 11, 1, 0, 0), 'foo': 1, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-11-01 00:00:00, foo: 2, bar: 3.0]: + - merge [date: 2026-01-01 00:00:00]: input: - - icon_restart [date: 2026-09-01 00:00:00, foo: 2, bar: 3.0] - - forcing - output: - - icon_output [date: 2026-11-01 00:00:00, foo: 2, bar: 3.0] - - icon_restart [date: 2026-11-01 00:00:00, foo: 2, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 11, 1, 0, 0), 'foo': 2, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2026-11-01 00:00:00, foo: 2, bar: 3.5]: - input: - - icon_restart [date: 2026-09-01 00:00:00, foo: 2, bar: 3.5] - - forcing - output: - - icon_output [date: 2026-11-01 00:00:00, foo: 2, bar: 3.5] - - icon_restart [date: 2026-11-01 00:00:00, foo: 2, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2026, 11, 1, 0, 0), 'foo': 2, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - statistics_foo [date: 2026-11-01 00:00:00, bar: 3.0]: - input: - - icon_output [date: 2026-11-01 00:00:00, foo: 0, bar: 3.0] - - icon_output [date: 2026-11-01 00:00:00, foo: 1, bar: 3.0] - - icon_output [date: 2026-11-01 00:00:00, foo: 2, bar: 3.0] - output: - - analysis_foo [date: 2026-11-01 00:00:00, bar: 3.0] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2026, 11, 1, 0, 0), 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo [date: 2026-11-01 00:00:00, bar: 3.5]: - input: - - icon_output [date: 2026-11-01 00:00:00, foo: 0, bar: 3.5] - - icon_output [date: 2026-11-01 00:00:00, foo: 1, bar: 3.5] - - icon_output [date: 2026-11-01 00:00:00, foo: 2, bar: 3.5] - output: - - analysis_foo [date: 2026-11-01 00:00:00, bar: 3.5] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2026, 11, 1, 0, 0), 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo_bar [date: 2026-11-01 00:00:00]: - input: - - analysis_foo [date: 2026-11-01 00:00:00, bar: 3.5] - - analysis_foo [date: 2026-11-01 00:00:00, bar: 3.0] - output: - - analysis_foo_bar [date: 2026-11-01 00:00:00] - name: 'statistics_foo_bar' - coordinates: {'date': datetime.datetime(2026, 11, 1, 0, 0)} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - bimonthly_tasks [date: 2027-01-01 00:00:00]: - tasks: - - icon [date: 2027-01-01 00:00:00, foo: 0, bar: 3.0]: - input: - - icon_restart [date: 2026-11-01 00:00:00, foo: 0, bar: 3.0] - - forcing - output: - - icon_output [date: 2027-01-01 00:00:00, foo: 0, bar: 3.0] - - icon_restart [date: 2027-01-01 00:00:00, foo: 0, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 1, 1, 0, 0), 'foo': 0, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-01-01 00:00:00, foo: 0, bar: 3.5]: - input: - - icon_restart [date: 2026-11-01 00:00:00, foo: 0, bar: 3.5] - - forcing - output: - - icon_output [date: 2027-01-01 00:00:00, foo: 0, bar: 3.5] - - icon_restart [date: 2027-01-01 00:00:00, foo: 0, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 1, 1, 0, 0), 'foo': 0, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-01-01 00:00:00, foo: 1, bar: 3.0]: - input: - - icon_restart [date: 2026-11-01 00:00:00, foo: 1, bar: 3.0] - - forcing - output: - - icon_output [date: 2027-01-01 00:00:00, foo: 1, bar: 3.0] - - icon_restart [date: 2027-01-01 00:00:00, foo: 1, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 1, 1, 0, 0), 'foo': 1, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-01-01 00:00:00, foo: 1, bar: 3.5]: - input: - - icon_restart [date: 2026-11-01 00:00:00, foo: 1, bar: 3.5] - - forcing - output: - - icon_output [date: 2027-01-01 00:00:00, foo: 1, bar: 3.5] - - icon_restart [date: 2027-01-01 00:00:00, foo: 1, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 1, 1, 0, 0), 'foo': 1, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-01-01 00:00:00, foo: 2, bar: 3.0]: - input: - - icon_restart [date: 2026-11-01 00:00:00, foo: 2, bar: 3.0] - - forcing - output: - - icon_output [date: 2027-01-01 00:00:00, foo: 2, bar: 3.0] - - icon_restart [date: 2027-01-01 00:00:00, foo: 2, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 1, 1, 0, 0), 'foo': 2, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-01-01 00:00:00, foo: 2, bar: 3.5]: - input: - - icon_restart [date: 2026-11-01 00:00:00, foo: 2, bar: 3.5] - - forcing - output: - - icon_output [date: 2027-01-01 00:00:00, foo: 2, bar: 3.5] - - icon_restart [date: 2027-01-01 00:00:00, foo: 2, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 1, 1, 0, 0), 'foo': 2, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - statistics_foo [date: 2027-01-01 00:00:00, bar: 3.0]: - input: - - icon_output [date: 2027-01-01 00:00:00, foo: 0, bar: 3.0] - - icon_output [date: 2027-01-01 00:00:00, foo: 1, bar: 3.0] - - icon_output [date: 2027-01-01 00:00:00, foo: 2, bar: 3.0] - output: - - analysis_foo [date: 2027-01-01 00:00:00, bar: 3.0] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2027, 1, 1, 0, 0), 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo [date: 2027-01-01 00:00:00, bar: 3.5]: - input: - - icon_output [date: 2027-01-01 00:00:00, foo: 0, bar: 3.5] - - icon_output [date: 2027-01-01 00:00:00, foo: 1, bar: 3.5] - - icon_output [date: 2027-01-01 00:00:00, foo: 2, bar: 3.5] - output: - - analysis_foo [date: 2027-01-01 00:00:00, bar: 3.5] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2027, 1, 1, 0, 0), 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo_bar [date: 2027-01-01 00:00:00]: - input: - - analysis_foo [date: 2027-01-01 00:00:00, bar: 3.5] - - analysis_foo [date: 2027-01-01 00:00:00, bar: 3.0] - output: - - analysis_foo_bar [date: 2027-01-01 00:00:00] - name: 'statistics_foo_bar' - coordinates: {'date': datetime.datetime(2027, 1, 1, 0, 0)} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - bimonthly_tasks [date: 2027-03-01 00:00:00]: - tasks: - - icon [date: 2027-03-01 00:00:00, foo: 0, bar: 3.0]: - input: - - icon_restart [date: 2027-01-01 00:00:00, foo: 0, bar: 3.0] - - forcing - output: - - icon_output [date: 2027-03-01 00:00:00, foo: 0, bar: 3.0] - - icon_restart [date: 2027-03-01 00:00:00, foo: 0, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 3, 1, 0, 0), 'foo': 0, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-03-01 00:00:00, foo: 0, bar: 3.5]: - input: - - icon_restart [date: 2027-01-01 00:00:00, foo: 0, bar: 3.5] - - forcing - output: - - icon_output [date: 2027-03-01 00:00:00, foo: 0, bar: 3.5] - - icon_restart [date: 2027-03-01 00:00:00, foo: 0, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 3, 1, 0, 0), 'foo': 0, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-03-01 00:00:00, foo: 1, bar: 3.0]: - input: - - icon_restart [date: 2027-01-01 00:00:00, foo: 1, bar: 3.0] - - forcing - output: - - icon_output [date: 2027-03-01 00:00:00, foo: 1, bar: 3.0] - - icon_restart [date: 2027-03-01 00:00:00, foo: 1, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 3, 1, 0, 0), 'foo': 1, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-03-01 00:00:00, foo: 1, bar: 3.5]: - input: - - icon_restart [date: 2027-01-01 00:00:00, foo: 1, bar: 3.5] - - forcing - output: - - icon_output [date: 2027-03-01 00:00:00, foo: 1, bar: 3.5] - - icon_restart [date: 2027-03-01 00:00:00, foo: 1, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 3, 1, 0, 0), 'foo': 1, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-03-01 00:00:00, foo: 2, bar: 3.0]: - input: - - icon_restart [date: 2027-01-01 00:00:00, foo: 2, bar: 3.0] - - forcing - output: - - icon_output [date: 2027-03-01 00:00:00, foo: 2, bar: 3.0] - - icon_restart [date: 2027-03-01 00:00:00, foo: 2, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 3, 1, 0, 0), 'foo': 2, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-03-01 00:00:00, foo: 2, bar: 3.5]: - input: - - icon_restart [date: 2027-01-01 00:00:00, foo: 2, bar: 3.5] - - forcing - output: - - icon_output [date: 2027-03-01 00:00:00, foo: 2, bar: 3.5] - - icon_restart [date: 2027-03-01 00:00:00, foo: 2, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 3, 1, 0, 0), 'foo': 2, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - statistics_foo [date: 2027-03-01 00:00:00, bar: 3.0]: - input: - - icon_output [date: 2027-03-01 00:00:00, foo: 0, bar: 3.0] - - icon_output [date: 2027-03-01 00:00:00, foo: 1, bar: 3.0] - - icon_output [date: 2027-03-01 00:00:00, foo: 2, bar: 3.0] - output: - - analysis_foo [date: 2027-03-01 00:00:00, bar: 3.0] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2027, 3, 1, 0, 0), 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo [date: 2027-03-01 00:00:00, bar: 3.5]: - input: - - icon_output [date: 2027-03-01 00:00:00, foo: 0, bar: 3.5] - - icon_output [date: 2027-03-01 00:00:00, foo: 1, bar: 3.5] - - icon_output [date: 2027-03-01 00:00:00, foo: 2, bar: 3.5] - output: - - analysis_foo [date: 2027-03-01 00:00:00, bar: 3.5] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2027, 3, 1, 0, 0), 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo_bar [date: 2027-03-01 00:00:00]: - input: - - analysis_foo [date: 2027-03-01 00:00:00, bar: 3.5] - - analysis_foo [date: 2027-03-01 00:00:00, bar: 3.0] - output: - - analysis_foo_bar [date: 2027-03-01 00:00:00] - name: 'statistics_foo_bar' - coordinates: {'date': datetime.datetime(2027, 3, 1, 0, 0)} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - bimonthly_tasks [date: 2027-05-01 00:00:00]: - tasks: - - icon [date: 2027-05-01 00:00:00, foo: 0, bar: 3.0]: - input: - - icon_restart [date: 2027-03-01 00:00:00, foo: 0, bar: 3.0] - - forcing - output: - - icon_output [date: 2027-05-01 00:00:00, foo: 0, bar: 3.0] - - icon_restart [date: 2027-05-01 00:00:00, foo: 0, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 5, 1, 0, 0), 'foo': 0, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-05-01 00:00:00, foo: 0, bar: 3.5]: - input: - - icon_restart [date: 2027-03-01 00:00:00, foo: 0, bar: 3.5] - - forcing - output: - - icon_output [date: 2027-05-01 00:00:00, foo: 0, bar: 3.5] - - icon_restart [date: 2027-05-01 00:00:00, foo: 0, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 5, 1, 0, 0), 'foo': 0, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-05-01 00:00:00, foo: 1, bar: 3.0]: - input: - - icon_restart [date: 2027-03-01 00:00:00, foo: 1, bar: 3.0] - - forcing - output: - - icon_output [date: 2027-05-01 00:00:00, foo: 1, bar: 3.0] - - icon_restart [date: 2027-05-01 00:00:00, foo: 1, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 5, 1, 0, 0), 'foo': 1, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-05-01 00:00:00, foo: 1, bar: 3.5]: - input: - - icon_restart [date: 2027-03-01 00:00:00, foo: 1, bar: 3.5] - - forcing - output: - - icon_output [date: 2027-05-01 00:00:00, foo: 1, bar: 3.5] - - icon_restart [date: 2027-05-01 00:00:00, foo: 1, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 5, 1, 0, 0), 'foo': 1, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-05-01 00:00:00, foo: 2, bar: 3.0]: - input: - - icon_restart [date: 2027-03-01 00:00:00, foo: 2, bar: 3.0] - - forcing - output: - - icon_output [date: 2027-05-01 00:00:00, foo: 2, bar: 3.0] - - icon_restart [date: 2027-05-01 00:00:00, foo: 2, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 5, 1, 0, 0), 'foo': 2, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-05-01 00:00:00, foo: 2, bar: 3.5]: - input: - - icon_restart [date: 2027-03-01 00:00:00, foo: 2, bar: 3.5] - - forcing - output: - - icon_output [date: 2027-05-01 00:00:00, foo: 2, bar: 3.5] - - icon_restart [date: 2027-05-01 00:00:00, foo: 2, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 5, 1, 0, 0), 'foo': 2, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - statistics_foo [date: 2027-05-01 00:00:00, bar: 3.0]: - input: - - icon_output [date: 2027-05-01 00:00:00, foo: 0, bar: 3.0] - - icon_output [date: 2027-05-01 00:00:00, foo: 1, bar: 3.0] - - icon_output [date: 2027-05-01 00:00:00, foo: 2, bar: 3.0] - output: - - analysis_foo [date: 2027-05-01 00:00:00, bar: 3.0] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2027, 5, 1, 0, 0), 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo [date: 2027-05-01 00:00:00, bar: 3.5]: - input: - - icon_output [date: 2027-05-01 00:00:00, foo: 0, bar: 3.5] - - icon_output [date: 2027-05-01 00:00:00, foo: 1, bar: 3.5] - - icon_output [date: 2027-05-01 00:00:00, foo: 2, bar: 3.5] - output: - - analysis_foo [date: 2027-05-01 00:00:00, bar: 3.5] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2027, 5, 1, 0, 0), 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo_bar [date: 2027-05-01 00:00:00]: - input: - - analysis_foo [date: 2027-05-01 00:00:00, bar: 3.5] - - analysis_foo [date: 2027-05-01 00:00:00, bar: 3.0] - output: - - analysis_foo_bar [date: 2027-05-01 00:00:00] - name: 'statistics_foo_bar' - coordinates: {'date': datetime.datetime(2027, 5, 1, 0, 0)} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - bimonthly_tasks [date: 2027-07-01 00:00:00]: - tasks: - - icon [date: 2027-07-01 00:00:00, foo: 0, bar: 3.0]: - input: - - icon_restart [date: 2027-05-01 00:00:00, foo: 0, bar: 3.0] - - forcing - output: - - icon_output [date: 2027-07-01 00:00:00, foo: 0, bar: 3.0] - - icon_restart [date: 2027-07-01 00:00:00, foo: 0, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 7, 1, 0, 0), 'foo': 0, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-07-01 00:00:00, foo: 0, bar: 3.5]: - input: - - icon_restart [date: 2027-05-01 00:00:00, foo: 0, bar: 3.5] - - forcing - output: - - icon_output [date: 2027-07-01 00:00:00, foo: 0, bar: 3.5] - - icon_restart [date: 2027-07-01 00:00:00, foo: 0, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 7, 1, 0, 0), 'foo': 0, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-07-01 00:00:00, foo: 1, bar: 3.0]: - input: - - icon_restart [date: 2027-05-01 00:00:00, foo: 1, bar: 3.0] - - forcing - output: - - icon_output [date: 2027-07-01 00:00:00, foo: 1, bar: 3.0] - - icon_restart [date: 2027-07-01 00:00:00, foo: 1, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 7, 1, 0, 0), 'foo': 1, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-07-01 00:00:00, foo: 1, bar: 3.5]: - input: - - icon_restart [date: 2027-05-01 00:00:00, foo: 1, bar: 3.5] - - forcing - output: - - icon_output [date: 2027-07-01 00:00:00, foo: 1, bar: 3.5] - - icon_restart [date: 2027-07-01 00:00:00, foo: 1, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 7, 1, 0, 0), 'foo': 1, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-07-01 00:00:00, foo: 2, bar: 3.0]: - input: - - icon_restart [date: 2027-05-01 00:00:00, foo: 2, bar: 3.0] - - forcing - output: - - icon_output [date: 2027-07-01 00:00:00, foo: 2, bar: 3.0] - - icon_restart [date: 2027-07-01 00:00:00, foo: 2, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 7, 1, 0, 0), 'foo': 2, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-07-01 00:00:00, foo: 2, bar: 3.5]: - input: - - icon_restart [date: 2027-05-01 00:00:00, foo: 2, bar: 3.5] - - forcing - output: - - icon_output [date: 2027-07-01 00:00:00, foo: 2, bar: 3.5] - - icon_restart [date: 2027-07-01 00:00:00, foo: 2, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 7, 1, 0, 0), 'foo': 2, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - statistics_foo [date: 2027-07-01 00:00:00, bar: 3.0]: - input: - - icon_output [date: 2027-07-01 00:00:00, foo: 0, bar: 3.0] - - icon_output [date: 2027-07-01 00:00:00, foo: 1, bar: 3.0] - - icon_output [date: 2027-07-01 00:00:00, foo: 2, bar: 3.0] - output: - - analysis_foo [date: 2027-07-01 00:00:00, bar: 3.0] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2027, 7, 1, 0, 0), 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo [date: 2027-07-01 00:00:00, bar: 3.5]: - input: - - icon_output [date: 2027-07-01 00:00:00, foo: 0, bar: 3.5] - - icon_output [date: 2027-07-01 00:00:00, foo: 1, bar: 3.5] - - icon_output [date: 2027-07-01 00:00:00, foo: 2, bar: 3.5] - output: - - analysis_foo [date: 2027-07-01 00:00:00, bar: 3.5] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2027, 7, 1, 0, 0), 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo_bar [date: 2027-07-01 00:00:00]: - input: - - analysis_foo [date: 2027-07-01 00:00:00, bar: 3.5] - - analysis_foo [date: 2027-07-01 00:00:00, bar: 3.0] - output: - - analysis_foo_bar [date: 2027-07-01 00:00:00] - name: 'statistics_foo_bar' - coordinates: {'date': datetime.datetime(2027, 7, 1, 0, 0)} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - bimonthly_tasks [date: 2027-09-01 00:00:00]: - tasks: - - icon [date: 2027-09-01 00:00:00, foo: 0, bar: 3.0]: - input: - - icon_restart [date: 2027-07-01 00:00:00, foo: 0, bar: 3.0] - - forcing - output: - - icon_output [date: 2027-09-01 00:00:00, foo: 0, bar: 3.0] - - icon_restart [date: 2027-09-01 00:00:00, foo: 0, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 9, 1, 0, 0), 'foo': 0, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-09-01 00:00:00, foo: 0, bar: 3.5]: - input: - - icon_restart [date: 2027-07-01 00:00:00, foo: 0, bar: 3.5] - - forcing - output: - - icon_output [date: 2027-09-01 00:00:00, foo: 0, bar: 3.5] - - icon_restart [date: 2027-09-01 00:00:00, foo: 0, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 9, 1, 0, 0), 'foo': 0, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-09-01 00:00:00, foo: 1, bar: 3.0]: - input: - - icon_restart [date: 2027-07-01 00:00:00, foo: 1, bar: 3.0] - - forcing - output: - - icon_output [date: 2027-09-01 00:00:00, foo: 1, bar: 3.0] - - icon_restart [date: 2027-09-01 00:00:00, foo: 1, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 9, 1, 0, 0), 'foo': 1, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-09-01 00:00:00, foo: 1, bar: 3.5]: - input: - - icon_restart [date: 2027-07-01 00:00:00, foo: 1, bar: 3.5] - - forcing - output: - - icon_output [date: 2027-09-01 00:00:00, foo: 1, bar: 3.5] - - icon_restart [date: 2027-09-01 00:00:00, foo: 1, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 9, 1, 0, 0), 'foo': 1, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-09-01 00:00:00, foo: 2, bar: 3.0]: - input: - - icon_restart [date: 2027-07-01 00:00:00, foo: 2, bar: 3.0] - - forcing - output: - - icon_output [date: 2027-09-01 00:00:00, foo: 2, bar: 3.0] - - icon_restart [date: 2027-09-01 00:00:00, foo: 2, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 9, 1, 0, 0), 'foo': 2, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-09-01 00:00:00, foo: 2, bar: 3.5]: - input: - - icon_restart [date: 2027-07-01 00:00:00, foo: 2, bar: 3.5] - - forcing - output: - - icon_output [date: 2027-09-01 00:00:00, foo: 2, bar: 3.5] - - icon_restart [date: 2027-09-01 00:00:00, foo: 2, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 9, 1, 0, 0), 'foo': 2, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - statistics_foo [date: 2027-09-01 00:00:00, bar: 3.0]: - input: - - icon_output [date: 2027-09-01 00:00:00, foo: 0, bar: 3.0] - - icon_output [date: 2027-09-01 00:00:00, foo: 1, bar: 3.0] - - icon_output [date: 2027-09-01 00:00:00, foo: 2, bar: 3.0] - output: - - analysis_foo [date: 2027-09-01 00:00:00, bar: 3.0] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2027, 9, 1, 0, 0), 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo [date: 2027-09-01 00:00:00, bar: 3.5]: - input: - - icon_output [date: 2027-09-01 00:00:00, foo: 0, bar: 3.5] - - icon_output [date: 2027-09-01 00:00:00, foo: 1, bar: 3.5] - - icon_output [date: 2027-09-01 00:00:00, foo: 2, bar: 3.5] - output: - - analysis_foo [date: 2027-09-01 00:00:00, bar: 3.5] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2027, 9, 1, 0, 0), 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo_bar [date: 2027-09-01 00:00:00]: - input: - - analysis_foo [date: 2027-09-01 00:00:00, bar: 3.5] - - analysis_foo [date: 2027-09-01 00:00:00, bar: 3.0] - output: - - analysis_foo_bar [date: 2027-09-01 00:00:00] - name: 'statistics_foo_bar' - coordinates: {'date': datetime.datetime(2027, 9, 1, 0, 0)} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - bimonthly_tasks [date: 2027-11-01 00:00:00]: - tasks: - - icon [date: 2027-11-01 00:00:00, foo: 0, bar: 3.0]: - input: - - icon_restart [date: 2027-09-01 00:00:00, foo: 0, bar: 3.0] - - forcing - output: - - icon_output [date: 2027-11-01 00:00:00, foo: 0, bar: 3.0] - - icon_restart [date: 2027-11-01 00:00:00, foo: 0, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 11, 1, 0, 0), 'foo': 0, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-11-01 00:00:00, foo: 0, bar: 3.5]: - input: - - icon_restart [date: 2027-09-01 00:00:00, foo: 0, bar: 3.5] - - forcing - output: - - icon_output [date: 2027-11-01 00:00:00, foo: 0, bar: 3.5] - - icon_restart [date: 2027-11-01 00:00:00, foo: 0, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 11, 1, 0, 0), 'foo': 0, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-11-01 00:00:00, foo: 1, bar: 3.0]: - input: - - icon_restart [date: 2027-09-01 00:00:00, foo: 1, bar: 3.0] - - forcing - output: - - icon_output [date: 2027-11-01 00:00:00, foo: 1, bar: 3.0] - - icon_restart [date: 2027-11-01 00:00:00, foo: 1, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 11, 1, 0, 0), 'foo': 1, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-11-01 00:00:00, foo: 1, bar: 3.5]: - input: - - icon_restart [date: 2027-09-01 00:00:00, foo: 1, bar: 3.5] - - forcing - output: - - icon_output [date: 2027-11-01 00:00:00, foo: 1, bar: 3.5] - - icon_restart [date: 2027-11-01 00:00:00, foo: 1, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 11, 1, 0, 0), 'foo': 1, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-11-01 00:00:00, foo: 2, bar: 3.0]: - input: - - icon_restart [date: 2027-09-01 00:00:00, foo: 2, bar: 3.0] - - forcing - output: - - icon_output [date: 2027-11-01 00:00:00, foo: 2, bar: 3.0] - - icon_restart [date: 2027-11-01 00:00:00, foo: 2, bar: 3.0] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 11, 1, 0, 0), 'foo': 2, 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - icon [date: 2027-11-01 00:00:00, foo: 2, bar: 3.5]: - input: - - icon_restart [date: 2027-09-01 00:00:00, foo: 2, bar: 3.5] - - forcing - output: - - icon_output [date: 2027-11-01 00:00:00, foo: 2, bar: 3.5] - - icon_restart [date: 2027-11-01 00:00:00, foo: 2, bar: 3.5] - name: 'icon' - coordinates: {'date': datetime.datetime(2027, 11, 1, 0, 0), 'foo': 2, 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None - - statistics_foo [date: 2027-11-01 00:00:00, bar: 3.0]: - input: - - icon_output [date: 2027-11-01 00:00:00, foo: 0, bar: 3.0] - - icon_output [date: 2027-11-01 00:00:00, foo: 1, bar: 3.0] - - icon_output [date: 2027-11-01 00:00:00, foo: 2, bar: 3.0] - output: - - analysis_foo [date: 2027-11-01 00:00:00, bar: 3.0] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2027, 11, 1, 0, 0), 'bar': 3.0} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo [date: 2027-11-01 00:00:00, bar: 3.5]: - input: - - icon_output [date: 2027-11-01 00:00:00, foo: 0, bar: 3.5] - - icon_output [date: 2027-11-01 00:00:00, foo: 1, bar: 3.5] - - icon_output [date: 2027-11-01 00:00:00, foo: 2, bar: 3.5] - output: - - analysis_foo [date: 2027-11-01 00:00:00, bar: 3.5] - name: 'statistics_foo' - coordinates: {'date': datetime.datetime(2027, 11, 1, 0, 0), 'bar': 3.5} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - statistics_foo_bar [date: 2027-11-01 00:00:00]: - input: - - analysis_foo [date: 2027-11-01 00:00:00, bar: 3.5] - - analysis_foo [date: 2027-11-01 00:00:00, bar: 3.0] - output: - - analysis_foo_bar [date: 2027-11-01 00:00:00] - name: 'statistics_foo_bar' - coordinates: {'date': datetime.datetime(2027, 11, 1, 0, 0)} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/statistics.py' - - yearly [date: 2026-01-01 00:00:00]: - tasks: - - merge [date: 2026-01-01 00:00:00]: - input: - - analysis_foo_bar [date: 2026-01-01 00:00:00] - - analysis_foo_bar [date: 2026-03-01 00:00:00] - - analysis_foo_bar [date: 2026-05-01 00:00:00] - - analysis_foo_bar [date: 2026-07-01 00:00:00] - - analysis_foo_bar [date: 2026-09-01 00:00:00] - - analysis_foo_bar [date: 2026-11-01 00:00:00] + - analysis_foo_bar [date: 2026-01-01 00:00:00] output: - yearly_analysis [date: 2026-01-01 00:00:00] name: 'merge' coordinates: {'date': datetime.datetime(2026, 1, 1, 0, 0)} start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 - plugin: 'shell' - command: '$PWD/tests/files/scripts/merge.py' - - yearly [date: 2027-01-01 00:00:00]: - tasks: - - merge [date: 2027-01-01 00:00:00]: - input: - - analysis_foo_bar [date: 2027-01-01 00:00:00] - - analysis_foo_bar [date: 2027-03-01 00:00:00] - - analysis_foo_bar [date: 2027-05-01 00:00:00] - - analysis_foo_bar [date: 2027-07-01 00:00:00] - - 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] - name: 'merge' - coordinates: {'date': datetime.datetime(2027, 1, 1, 0, 0)} - start date: 2026-01-01 00:00:00 - end date: 2028-01-01 00:00:00 + end date: 2026-03-01 00:00:00 plugin: 'shell' - command: '$PWD/tests/files/scripts/merge.py' \ No newline at end of file + command: 'scripts/merge.py' + cli arguments: '' + env source files: [] \ No newline at end of file diff --git a/tests/cases/small/config/data/initial_conditions b/tests/cases/small/config/data/initial_conditions new file mode 100644 index 00000000..e69de29b diff --git a/tests/cases/small/config/data/input b/tests/cases/small/config/data/input new file mode 100644 index 00000000..e69de29b diff --git a/tests/cases/small/config/scripts/cleanup.py b/tests/cases/small/config/scripts/cleanup.py new file mode 100755 index 00000000..de7aebad --- /dev/null +++ b/tests/cases/small/config/scripts/cleanup.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python + + +def main(): + # Main script execution continues here + print("Cleaning") + + +if __name__ == "__main__": + main() diff --git a/tests/cases/small/config/scripts/icon.py b/tests/cases/small/config/scripts/icon.py new file mode 100755 index 00000000..32f71ed6 --- /dev/null +++ b/tests/cases/small/config/scripts/icon.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +"""usage: icon.py [-h] [--init [INIT]] [--restart [RESTART]] [--forcing [FORCING]] [namelist] + +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 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("namelist", nargs="?", default=None) + parser.add_argument("--restart", nargs="?", type=str, help="The icon restart file.") + parser.add_argument("--forcing", nargs="?", type=str, help="The icon forcing file.") + + args = parser.parse_args() + + output = Path("icon_output") + output.write_text("") + + if args.restart: + if args.init: + msg = "Cannot use '--init' and '--restart' option at the same time." + raise ValueError(msg) + if not Path(args.restart).exists(): + msg = f"The icon restart file {args.restart!r} was not found." + raise FileNotFoundError(msg) + restart = Path(args.restart) + + log(f"Restarting from file {args.restart!r}.") + elif args.init: + if not Path(args.init).exists(): + msg = f"The icon init file {args.init!r} was not found." + raise FileNotFoundError(msg) + + log(f"Starting from init file {args.init!r}.") + else: + msg = "Please provide a restart or init file with the corresponding option." + raise ValueError(msg) + + if args.namelist: + log(f"Namelist {args.namelist} provided. Continue with it.") + else: + log("No namelist provided. Continue with default one.") + + # Main script execution continues here + log("Script finished running calculations") + + restart = Path("restart") + restart.write_text("") + + +if __name__ == "__main__": + main() diff --git a/tests/cases/small/config/test_config_small.yml b/tests/cases/small/config/test_config_small.yml index 8b163fc4..58555a85 100644 --- a/tests/cases/small/config/test_config_small.yml +++ b/tests/cases/small/config/test_config_small.yml @@ -9,6 +9,10 @@ cycles: tasks: - icon: inputs: + - icon_namelist + - initial_conditions: + when: + at: *root_start_date - icon_restart: when: after: *root_start_date @@ -23,22 +27,23 @@ cycles: tasks: - icon: plugin: shell - command: $PWD/tests/files/scripts/icon.py - cli_arguments: - keyword: - --restart: icon_restart + command: scripts/icon.py + cli_arguments: "{--restart icon_restart} {--init initial_conditions}" - cleanup: plugin: shell - command: $PWD/tests/files/scripts/cleanup.py + command: scripts/cleanup.py data: available: - - icon_input: + - icon_namelist: + type: file + src: data/input + - initial_conditions: type: file - src: $PWD/tests/files/data/input + src: data/initial_conditions generated: - icon_output: type: file - src: output + src: icon_output - icon_restart: type: file src: restart diff --git a/tests/cases/small/data/test_config_small.txt b/tests/cases/small/data/test_config_small.txt index 8af67b5f..c3b0980f 100644 --- a/tests/cases/small/data/test_config_small.txt +++ b/tests/cases/small/data/test_config_small.txt @@ -2,6 +2,9 @@ cycles: - bimonthly_tasks [date: 2026-01-01 00:00:00]: tasks: - icon [date: 2026-01-01 00:00:00]: + input: + - icon_namelist + - initial_conditions output: - icon_output [date: 2026-01-01 00:00:00] - icon_restart [date: 2026-01-01 00:00:00] @@ -10,12 +13,14 @@ cycles: start date: 2026-01-01 00:00:00 end date: 2026-06-01 00:00:00 plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None + command: 'scripts/icon.py' + cli arguments: '{--restart icon_restart} {--init initial_conditions}' + env source files: [] - bimonthly_tasks [date: 2026-03-01 00:00:00]: tasks: - icon [date: 2026-03-01 00:00:00]: input: + - icon_namelist - icon_restart [date: 2026-01-01 00:00:00] output: - icon_output [date: 2026-03-01 00:00:00] @@ -25,12 +30,14 @@ cycles: start date: 2026-01-01 00:00:00 end date: 2026-06-01 00:00:00 plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None + command: 'scripts/icon.py' + cli arguments: '{--restart icon_restart} {--init initial_conditions}' + env source files: [] - bimonthly_tasks [date: 2026-05-01 00:00:00]: tasks: - icon [date: 2026-05-01 00:00:00]: input: + - icon_namelist - icon_restart [date: 2026-03-01 00:00:00] output: - icon_output [date: 2026-05-01 00:00:00] @@ -40,8 +47,9 @@ cycles: start date: 2026-01-01 00:00:00 end date: 2026-06-01 00:00:00 plugin: 'shell' - command: '$PWD/tests/files/scripts/icon.py' - cli arguments: positional=None keyword={'--restart': 'icon_restart'} flags=None source_file=None + command: 'scripts/icon.py' + cli arguments: '{--restart icon_restart} {--init initial_conditions}' + env source files: [] - lastly: tasks: - cleanup: @@ -50,4 +58,6 @@ cycles: name: 'cleanup' coordinates: {} plugin: 'shell' - command: '$PWD/tests/files/scripts/cleanup.py' \ No newline at end of file + command: 'scripts/cleanup.py' + cli arguments: '' + env source files: [] \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index e69de29b..4a579bb5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -0,0 +1 @@ +pytest_plugins = ["aiida.tools.pytest_fixtures"] diff --git a/tests/test_wc_workflow.py b/tests/test_wc_workflow.py index 5c253a3e..c602a29f 100644 --- a/tests/test_wc_workflow.py +++ b/tests/test_wc_workflow.py @@ -5,13 +5,9 @@ from sirocco.core import Workflow from sirocco.pretty_print import PrettyPrinter from sirocco.vizgraph import VizGraph +from sirocco.workgraph import AiidaWorkGraph - -@pytest.fixture -def pprinter(): - return PrettyPrinter() - - +# configs that are tested for parsing config_test_files = [ "tests/cases/small/config/test_config_small.yml", "tests/cases/large/config/test_config_large.yml", @@ -29,14 +25,20 @@ def config_paths(request): } +@pytest.fixture +def pprinter(): + return PrettyPrinter() + + def test_parse_config_file(config_paths, pprinter): reference_str = config_paths["txt"].read_text() test_str = pprinter.format(Workflow.from_yaml(config_paths["yml"])) if test_str != reference_str: new_path = Path(config_paths["txt"]).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}." - 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") @@ -46,3 +48,18 @@ def test_serialize_workflow(config_paths, pprinter): def test_vizgraph(config_paths): VizGraph.from_yaml(config_paths["yml"]).draw(file_path=config_paths["svg"]) + + +# configs that are tested for running workgraph +@pytest.mark.parametrize( + "config_path", + [ + "tests/cases/small/config/test_config_small.yml", + "tests/cases/parameters/config/test_config_parameters.yml", + ], +) +def test_run_workgraph(config_path): + core_workflow = Workflow.from_yaml(config_path) + aiida_workflow = AiidaWorkGraph(core_workflow) + out = aiida_workflow.run() + assert out.get("execution_count", None).value == 0 # TODO: should be 1 but we need to update workgraph for this