hpcflow 0.1.9__py3-none-any.whl → 0.2.0a271__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hpcflow/__init__.py +2 -11
- hpcflow/__pyinstaller/__init__.py +5 -0
- hpcflow/__pyinstaller/hook-hpcflow.py +40 -0
- hpcflow/_version.py +1 -1
- hpcflow/app.py +43 -0
- hpcflow/cli.py +2 -462
- hpcflow/data/demo_data_manifest/__init__.py +3 -0
- hpcflow/data/demo_data_manifest/demo_data_manifest.json +6 -0
- hpcflow/data/jinja_templates/test/test_template.txt +8 -0
- hpcflow/data/programs/hello_world/README.md +1 -0
- hpcflow/data/programs/hello_world/hello_world.c +87 -0
- hpcflow/data/programs/hello_world/linux/hello_world +0 -0
- hpcflow/data/programs/hello_world/macos/hello_world +0 -0
- hpcflow/data/programs/hello_world/win/hello_world.exe +0 -0
- hpcflow/data/scripts/__init__.py +1 -0
- hpcflow/data/scripts/bad_script.py +2 -0
- hpcflow/data/scripts/demo_task_1_generate_t1_infile_1.py +8 -0
- hpcflow/data/scripts/demo_task_1_generate_t1_infile_2.py +8 -0
- hpcflow/data/scripts/demo_task_1_parse_p3.py +7 -0
- hpcflow/data/scripts/do_nothing.py +2 -0
- hpcflow/data/scripts/env_specifier_test/input_file_generator_pass_env_spec.py +4 -0
- hpcflow/data/scripts/env_specifier_test/main_script_test_pass_env_spec.py +8 -0
- hpcflow/data/scripts/env_specifier_test/output_file_parser_pass_env_spec.py +4 -0
- hpcflow/data/scripts/env_specifier_test/v1/input_file_generator_basic.py +4 -0
- hpcflow/data/scripts/env_specifier_test/v1/main_script_test_direct_in_direct_out.py +7 -0
- hpcflow/data/scripts/env_specifier_test/v1/output_file_parser_basic.py +4 -0
- hpcflow/data/scripts/env_specifier_test/v2/main_script_test_direct_in_direct_out.py +7 -0
- hpcflow/data/scripts/generate_t1_file_01.py +7 -0
- hpcflow/data/scripts/import_future_script.py +7 -0
- hpcflow/data/scripts/input_file_generator_basic.py +3 -0
- hpcflow/data/scripts/input_file_generator_basic_FAIL.py +3 -0
- hpcflow/data/scripts/input_file_generator_test_stdout_stderr.py +8 -0
- hpcflow/data/scripts/main_script_test_direct_in.py +3 -0
- hpcflow/data/scripts/main_script_test_direct_in_direct_out.py +6 -0
- hpcflow/data/scripts/main_script_test_direct_in_direct_out_2.py +6 -0
- hpcflow/data/scripts/main_script_test_direct_in_direct_out_2_fail_allowed.py +6 -0
- hpcflow/data/scripts/main_script_test_direct_in_direct_out_2_fail_allowed_group.py +7 -0
- hpcflow/data/scripts/main_script_test_direct_in_direct_out_3.py +6 -0
- hpcflow/data/scripts/main_script_test_direct_in_direct_out_all_iters_test.py +15 -0
- hpcflow/data/scripts/main_script_test_direct_in_direct_out_env_spec.py +7 -0
- hpcflow/data/scripts/main_script_test_direct_in_direct_out_labels.py +8 -0
- hpcflow/data/scripts/main_script_test_direct_in_group_direct_out_3.py +6 -0
- hpcflow/data/scripts/main_script_test_direct_in_group_one_fail_direct_out_3.py +6 -0
- hpcflow/data/scripts/main_script_test_direct_sub_param_in_direct_out.py +6 -0
- hpcflow/data/scripts/main_script_test_hdf5_in_obj.py +12 -0
- hpcflow/data/scripts/main_script_test_hdf5_in_obj_2.py +12 -0
- hpcflow/data/scripts/main_script_test_hdf5_in_obj_group.py +12 -0
- hpcflow/data/scripts/main_script_test_hdf5_out_obj.py +11 -0
- hpcflow/data/scripts/main_script_test_json_and_direct_in_json_out.py +14 -0
- hpcflow/data/scripts/main_script_test_json_in_json_and_direct_out.py +17 -0
- hpcflow/data/scripts/main_script_test_json_in_json_out.py +14 -0
- hpcflow/data/scripts/main_script_test_json_in_json_out_labels.py +16 -0
- hpcflow/data/scripts/main_script_test_json_in_obj.py +12 -0
- hpcflow/data/scripts/main_script_test_json_out_FAIL.py +3 -0
- hpcflow/data/scripts/main_script_test_json_out_obj.py +10 -0
- hpcflow/data/scripts/main_script_test_json_sub_param_in_json_out_labels.py +16 -0
- hpcflow/data/scripts/main_script_test_shell_env_vars.py +12 -0
- hpcflow/data/scripts/main_script_test_std_out_std_err.py +6 -0
- hpcflow/data/scripts/output_file_parser_basic.py +3 -0
- hpcflow/data/scripts/output_file_parser_basic_FAIL.py +7 -0
- hpcflow/data/scripts/output_file_parser_test_stdout_stderr.py +8 -0
- hpcflow/data/scripts/parse_t1_file_01.py +4 -0
- hpcflow/data/scripts/script_exit_test.py +5 -0
- hpcflow/data/template_components/__init__.py +1 -0
- hpcflow/data/template_components/command_files.yaml +26 -0
- hpcflow/data/template_components/environments.yaml +13 -0
- hpcflow/data/template_components/parameters.yaml +14 -0
- hpcflow/data/template_components/task_schemas.yaml +139 -0
- hpcflow/data/workflows/workflow_1.yaml +5 -0
- hpcflow/examples.ipynb +1037 -0
- hpcflow/sdk/__init__.py +149 -0
- hpcflow/sdk/app.py +4266 -0
- hpcflow/sdk/cli.py +1479 -0
- hpcflow/sdk/cli_common.py +385 -0
- hpcflow/sdk/config/__init__.py +5 -0
- hpcflow/sdk/config/callbacks.py +246 -0
- hpcflow/sdk/config/cli.py +388 -0
- hpcflow/sdk/config/config.py +1410 -0
- hpcflow/sdk/config/config_file.py +501 -0
- hpcflow/sdk/config/errors.py +272 -0
- hpcflow/sdk/config/types.py +150 -0
- hpcflow/sdk/core/__init__.py +38 -0
- hpcflow/sdk/core/actions.py +3857 -0
- hpcflow/sdk/core/app_aware.py +25 -0
- hpcflow/sdk/core/cache.py +224 -0
- hpcflow/sdk/core/command_files.py +814 -0
- hpcflow/sdk/core/commands.py +424 -0
- hpcflow/sdk/core/element.py +2071 -0
- hpcflow/sdk/core/enums.py +221 -0
- hpcflow/sdk/core/environment.py +256 -0
- hpcflow/sdk/core/errors.py +1043 -0
- hpcflow/sdk/core/execute.py +207 -0
- hpcflow/sdk/core/json_like.py +809 -0
- hpcflow/sdk/core/loop.py +1320 -0
- hpcflow/sdk/core/loop_cache.py +282 -0
- hpcflow/sdk/core/object_list.py +933 -0
- hpcflow/sdk/core/parameters.py +3371 -0
- hpcflow/sdk/core/rule.py +196 -0
- hpcflow/sdk/core/run_dir_files.py +57 -0
- hpcflow/sdk/core/skip_reason.py +7 -0
- hpcflow/sdk/core/task.py +3792 -0
- hpcflow/sdk/core/task_schema.py +993 -0
- hpcflow/sdk/core/test_utils.py +538 -0
- hpcflow/sdk/core/types.py +447 -0
- hpcflow/sdk/core/utils.py +1207 -0
- hpcflow/sdk/core/validation.py +87 -0
- hpcflow/sdk/core/values.py +477 -0
- hpcflow/sdk/core/workflow.py +4820 -0
- hpcflow/sdk/core/zarr_io.py +206 -0
- hpcflow/sdk/data/__init__.py +13 -0
- hpcflow/sdk/data/config_file_schema.yaml +34 -0
- hpcflow/sdk/data/config_schema.yaml +260 -0
- hpcflow/sdk/data/environments_spec_schema.yaml +21 -0
- hpcflow/sdk/data/files_spec_schema.yaml +5 -0
- hpcflow/sdk/data/parameters_spec_schema.yaml +7 -0
- hpcflow/sdk/data/task_schema_spec_schema.yaml +3 -0
- hpcflow/sdk/data/workflow_spec_schema.yaml +22 -0
- hpcflow/sdk/demo/__init__.py +3 -0
- hpcflow/sdk/demo/cli.py +242 -0
- hpcflow/sdk/helper/__init__.py +3 -0
- hpcflow/sdk/helper/cli.py +137 -0
- hpcflow/sdk/helper/helper.py +300 -0
- hpcflow/sdk/helper/watcher.py +192 -0
- hpcflow/sdk/log.py +288 -0
- hpcflow/sdk/persistence/__init__.py +18 -0
- hpcflow/sdk/persistence/base.py +2817 -0
- hpcflow/sdk/persistence/defaults.py +6 -0
- hpcflow/sdk/persistence/discovery.py +39 -0
- hpcflow/sdk/persistence/json.py +954 -0
- hpcflow/sdk/persistence/pending.py +948 -0
- hpcflow/sdk/persistence/store_resource.py +203 -0
- hpcflow/sdk/persistence/types.py +309 -0
- hpcflow/sdk/persistence/utils.py +73 -0
- hpcflow/sdk/persistence/zarr.py +2388 -0
- hpcflow/sdk/runtime.py +320 -0
- hpcflow/sdk/submission/__init__.py +3 -0
- hpcflow/sdk/submission/enums.py +70 -0
- hpcflow/sdk/submission/jobscript.py +2379 -0
- hpcflow/sdk/submission/schedulers/__init__.py +281 -0
- hpcflow/sdk/submission/schedulers/direct.py +233 -0
- hpcflow/sdk/submission/schedulers/sge.py +376 -0
- hpcflow/sdk/submission/schedulers/slurm.py +598 -0
- hpcflow/sdk/submission/schedulers/utils.py +25 -0
- hpcflow/sdk/submission/shells/__init__.py +52 -0
- hpcflow/sdk/submission/shells/base.py +229 -0
- hpcflow/sdk/submission/shells/bash.py +504 -0
- hpcflow/sdk/submission/shells/os_version.py +115 -0
- hpcflow/sdk/submission/shells/powershell.py +352 -0
- hpcflow/sdk/submission/submission.py +1402 -0
- hpcflow/sdk/submission/types.py +140 -0
- hpcflow/sdk/typing.py +194 -0
- hpcflow/sdk/utils/arrays.py +69 -0
- hpcflow/sdk/utils/deferred_file.py +55 -0
- hpcflow/sdk/utils/hashing.py +16 -0
- hpcflow/sdk/utils/patches.py +31 -0
- hpcflow/sdk/utils/strings.py +69 -0
- hpcflow/tests/api/test_api.py +32 -0
- hpcflow/tests/conftest.py +123 -0
- hpcflow/tests/data/__init__.py +0 -0
- hpcflow/tests/data/benchmark_N_elements.yaml +6 -0
- hpcflow/tests/data/benchmark_script_runner.yaml +26 -0
- hpcflow/tests/data/multi_path_sequences.yaml +29 -0
- hpcflow/tests/data/workflow_1.json +10 -0
- hpcflow/tests/data/workflow_1.yaml +5 -0
- hpcflow/tests/data/workflow_1_slurm.yaml +8 -0
- hpcflow/tests/data/workflow_1_wsl.yaml +8 -0
- hpcflow/tests/data/workflow_test_run_abort.yaml +42 -0
- hpcflow/tests/jinja_templates/test_jinja_templates.py +161 -0
- hpcflow/tests/programs/test_programs.py +180 -0
- hpcflow/tests/schedulers/direct_linux/test_direct_linux_submission.py +12 -0
- hpcflow/tests/schedulers/sge/test_sge_submission.py +36 -0
- hpcflow/tests/schedulers/slurm/test_slurm_submission.py +14 -0
- hpcflow/tests/scripts/test_input_file_generators.py +282 -0
- hpcflow/tests/scripts/test_main_scripts.py +1361 -0
- hpcflow/tests/scripts/test_non_snippet_script.py +46 -0
- hpcflow/tests/scripts/test_ouput_file_parsers.py +353 -0
- hpcflow/tests/shells/wsl/test_wsl_submission.py +14 -0
- hpcflow/tests/unit/test_action.py +1066 -0
- hpcflow/tests/unit/test_action_rule.py +24 -0
- hpcflow/tests/unit/test_app.py +132 -0
- hpcflow/tests/unit/test_cache.py +46 -0
- hpcflow/tests/unit/test_cli.py +172 -0
- hpcflow/tests/unit/test_command.py +377 -0
- hpcflow/tests/unit/test_config.py +195 -0
- hpcflow/tests/unit/test_config_file.py +162 -0
- hpcflow/tests/unit/test_element.py +666 -0
- hpcflow/tests/unit/test_element_iteration.py +88 -0
- hpcflow/tests/unit/test_element_set.py +158 -0
- hpcflow/tests/unit/test_group.py +115 -0
- hpcflow/tests/unit/test_input_source.py +1479 -0
- hpcflow/tests/unit/test_input_value.py +398 -0
- hpcflow/tests/unit/test_jobscript_unit.py +757 -0
- hpcflow/tests/unit/test_json_like.py +1247 -0
- hpcflow/tests/unit/test_loop.py +2674 -0
- hpcflow/tests/unit/test_meta_task.py +325 -0
- hpcflow/tests/unit/test_multi_path_sequences.py +259 -0
- hpcflow/tests/unit/test_object_list.py +116 -0
- hpcflow/tests/unit/test_parameter.py +243 -0
- hpcflow/tests/unit/test_persistence.py +664 -0
- hpcflow/tests/unit/test_resources.py +243 -0
- hpcflow/tests/unit/test_run.py +286 -0
- hpcflow/tests/unit/test_run_directories.py +29 -0
- hpcflow/tests/unit/test_runtime.py +9 -0
- hpcflow/tests/unit/test_schema_input.py +372 -0
- hpcflow/tests/unit/test_shell.py +129 -0
- hpcflow/tests/unit/test_slurm.py +39 -0
- hpcflow/tests/unit/test_submission.py +502 -0
- hpcflow/tests/unit/test_task.py +2560 -0
- hpcflow/tests/unit/test_task_schema.py +182 -0
- hpcflow/tests/unit/test_utils.py +616 -0
- hpcflow/tests/unit/test_value_sequence.py +549 -0
- hpcflow/tests/unit/test_values.py +91 -0
- hpcflow/tests/unit/test_workflow.py +827 -0
- hpcflow/tests/unit/test_workflow_template.py +186 -0
- hpcflow/tests/unit/utils/test_arrays.py +40 -0
- hpcflow/tests/unit/utils/test_deferred_file_writer.py +34 -0
- hpcflow/tests/unit/utils/test_hashing.py +65 -0
- hpcflow/tests/unit/utils/test_patches.py +5 -0
- hpcflow/tests/unit/utils/test_redirect_std.py +50 -0
- hpcflow/tests/unit/utils/test_strings.py +97 -0
- hpcflow/tests/workflows/__init__.py +0 -0
- hpcflow/tests/workflows/test_directory_structure.py +31 -0
- hpcflow/tests/workflows/test_jobscript.py +355 -0
- hpcflow/tests/workflows/test_run_status.py +198 -0
- hpcflow/tests/workflows/test_skip_downstream.py +696 -0
- hpcflow/tests/workflows/test_submission.py +140 -0
- hpcflow/tests/workflows/test_workflows.py +564 -0
- hpcflow/tests/workflows/test_zip.py +18 -0
- hpcflow/viz_demo.ipynb +6794 -0
- hpcflow-0.2.0a271.dist-info/LICENSE +375 -0
- hpcflow-0.2.0a271.dist-info/METADATA +65 -0
- hpcflow-0.2.0a271.dist-info/RECORD +237 -0
- {hpcflow-0.1.9.dist-info → hpcflow-0.2.0a271.dist-info}/WHEEL +4 -5
- hpcflow-0.2.0a271.dist-info/entry_points.txt +6 -0
- hpcflow/api.py +0 -458
- hpcflow/archive/archive.py +0 -308
- hpcflow/archive/cloud/cloud.py +0 -47
- hpcflow/archive/cloud/errors.py +0 -9
- hpcflow/archive/cloud/providers/dropbox.py +0 -432
- hpcflow/archive/errors.py +0 -5
- hpcflow/base_db.py +0 -4
- hpcflow/config.py +0 -232
- hpcflow/copytree.py +0 -66
- hpcflow/data/examples/_config.yml +0 -14
- hpcflow/data/examples/damask/demo/1.run.yml +0 -4
- hpcflow/data/examples/damask/demo/2.process.yml +0 -29
- hpcflow/data/examples/damask/demo/geom.geom +0 -2052
- hpcflow/data/examples/damask/demo/load.load +0 -1
- hpcflow/data/examples/damask/demo/material.config +0 -185
- hpcflow/data/examples/damask/inputs/geom.geom +0 -2052
- hpcflow/data/examples/damask/inputs/load.load +0 -1
- hpcflow/data/examples/damask/inputs/material.config +0 -185
- hpcflow/data/examples/damask/profiles/_variable_lookup.yml +0 -21
- hpcflow/data/examples/damask/profiles/damask.yml +0 -4
- hpcflow/data/examples/damask/profiles/damask_process.yml +0 -8
- hpcflow/data/examples/damask/profiles/damask_run.yml +0 -5
- hpcflow/data/examples/damask/profiles/default.yml +0 -6
- hpcflow/data/examples/thinking.yml +0 -177
- hpcflow/errors.py +0 -2
- hpcflow/init_db.py +0 -37
- hpcflow/models.py +0 -2549
- hpcflow/nesting.py +0 -9
- hpcflow/profiles.py +0 -455
- hpcflow/project.py +0 -81
- hpcflow/scheduler.py +0 -323
- hpcflow/utils.py +0 -103
- hpcflow/validation.py +0 -167
- hpcflow/variables.py +0 -544
- hpcflow-0.1.9.dist-info/METADATA +0 -168
- hpcflow-0.1.9.dist-info/RECORD +0 -45
- hpcflow-0.1.9.dist-info/entry_points.txt +0 -8
- hpcflow-0.1.9.dist-info/top_level.txt +0 -1
- /hpcflow/{archive → data/jinja_templates}/__init__.py +0 -0
- /hpcflow/{archive/cloud → data/programs}/__init__.py +0 -0
- /hpcflow/{archive/cloud/providers → data/workflows}/__init__.py +0 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Shell models based on Microsoft PowerShell.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
import subprocess
|
|
7
|
+
from textwrap import dedent
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
|
+
from typing_extensions import override
|
|
10
|
+
from hpcflow.sdk.typing import hydrate
|
|
11
|
+
from hpcflow.sdk.submission.shells.base import Shell
|
|
12
|
+
from hpcflow.sdk.submission.shells.os_version import get_OS_info_windows
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from typing import ClassVar
|
|
16
|
+
from .base import VersionInfo
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@hydrate
|
|
20
|
+
class WindowsPowerShell(Shell):
|
|
21
|
+
"""Class to represent using PowerShell on Windows to generate and submit a jobscript."""
|
|
22
|
+
|
|
23
|
+
# TODO: add snippets that can be used in demo task schemas?
|
|
24
|
+
|
|
25
|
+
#: Default for executable name.
|
|
26
|
+
DEFAULT_EXE: ClassVar[str] = "powershell.exe"
|
|
27
|
+
|
|
28
|
+
#: File extension for jobscripts.
|
|
29
|
+
JS_EXT: ClassVar[str] = ".ps1"
|
|
30
|
+
#: Basic indent.
|
|
31
|
+
JS_INDENT: ClassVar[str] = " "
|
|
32
|
+
#: Indent for environment setup.
|
|
33
|
+
JS_ENV_SETUP_INDENT: ClassVar[str] = 2 * JS_INDENT
|
|
34
|
+
#: Template for the jobscript shebang line.
|
|
35
|
+
JS_SHEBANG: ClassVar[str] = ""
|
|
36
|
+
#: Template for the jobscript functions file.
|
|
37
|
+
JS_FUNCS: ClassVar[str] = dedent(
|
|
38
|
+
"""\
|
|
39
|
+
function {workflow_app_alias} {{
|
|
40
|
+
& {{
|
|
41
|
+
{env_setup}{app_invoc} `
|
|
42
|
+
--with-config log_file_path "$env:{app_caps}_LOG_PATH" `
|
|
43
|
+
--config-dir "{config_dir}" `
|
|
44
|
+
--config-key "{config_invoc_key}" `
|
|
45
|
+
$args
|
|
46
|
+
}} @args
|
|
47
|
+
}}
|
|
48
|
+
|
|
49
|
+
function get_nth_line($file, $line) {{
|
|
50
|
+
Get-Content $file | Select-Object -Skip $line -First 1
|
|
51
|
+
}}
|
|
52
|
+
"""
|
|
53
|
+
)
|
|
54
|
+
#: Template for the common part of the jobscript header.
|
|
55
|
+
JS_HEADER: ClassVar[str] = dedent(
|
|
56
|
+
"""\
|
|
57
|
+
$ErrorActionPreference = 'Stop'
|
|
58
|
+
|
|
59
|
+
function JoinMultiPath {{
|
|
60
|
+
$numArgs = $args.Length
|
|
61
|
+
$path = $args[0]
|
|
62
|
+
for ($i = 1; $i -lt $numArgs; $i++) {{
|
|
63
|
+
$path = Join-Path $path $args[$i]
|
|
64
|
+
}}
|
|
65
|
+
return $path
|
|
66
|
+
}}
|
|
67
|
+
|
|
68
|
+
$WK_PATH = $(Get-Location)
|
|
69
|
+
$WK_PATH_ARG = $WK_PATH
|
|
70
|
+
$SUB_IDX = {sub_idx}
|
|
71
|
+
$JS_IDX = {js_idx}
|
|
72
|
+
|
|
73
|
+
$SUB_DIR = JoinMultiPath $WK_PATH artifacts submissions $SUB_IDX
|
|
74
|
+
$JS_FUNCS_PATH = JoinMultiPath $SUB_DIR {jobscript_functions_dir} {jobscript_functions_name}
|
|
75
|
+
. $JS_FUNCS_PATH
|
|
76
|
+
|
|
77
|
+
$EAR_ID_FILE = JoinMultiPath $SUB_DIR {run_IDs_file_dir} {run_IDs_file_name}
|
|
78
|
+
$SUB_TMP_DIR = Join-Path $SUB_DIR {tmp_dir_name}
|
|
79
|
+
$SUB_LOG_DIR = Join-Path $SUB_DIR {log_dir_name}
|
|
80
|
+
$SUB_STD_DIR = Join-Path $SUB_DIR {app_std_dir_name}
|
|
81
|
+
$SUB_SCRIPTS_DIR = Join-Path $SUB_DIR {scripts_dir_name}
|
|
82
|
+
|
|
83
|
+
$env:{app_caps}_WK_PATH = $WK_PATH
|
|
84
|
+
$env:{app_caps}_WK_PATH_ARG = $WK_PATH_ARG
|
|
85
|
+
$env:{app_caps}_SUB_IDX = {sub_idx}
|
|
86
|
+
$env:{app_caps}_SUB_SCRIPTS_DIR = $SUB_SCRIPTS_DIR
|
|
87
|
+
$env:{app_caps}_SUB_TMP_DIR = $SUB_TMP_DIR
|
|
88
|
+
$env:{app_caps}_SUB_LOG_DIR = $SUB_LOG_DIR
|
|
89
|
+
$env:{app_caps}_SUB_STD_DIR = $SUB_STD_DIR
|
|
90
|
+
$env:{app_caps}_LOG_PATH = Join-Path $SUB_LOG_DIR "js_$JS_IDX.log"
|
|
91
|
+
$env:{app_caps}_JS_FUNCS_PATH = $JS_FUNCS_PATH
|
|
92
|
+
$env:{app_caps}_JS_IDX = {js_idx}
|
|
93
|
+
$env:{app_caps}_RUN_ID_FILE = $EAR_ID_FILE
|
|
94
|
+
"""
|
|
95
|
+
)
|
|
96
|
+
#: Template for the jobscript header when directly executed.
|
|
97
|
+
JS_DIRECT_HEADER: ClassVar[str] = dedent(
|
|
98
|
+
"""\
|
|
99
|
+
{shebang}
|
|
100
|
+
{header}
|
|
101
|
+
{wait_command}
|
|
102
|
+
"""
|
|
103
|
+
)
|
|
104
|
+
#: Template for enabling writing of the app log.
|
|
105
|
+
JS_RUN_LOG_PATH_ENABLE: ClassVar[str] = 'Join-Path $SUB_LOG_DIR "{run_log_file_name}"'
|
|
106
|
+
#: Template for disabling writing of the app log.
|
|
107
|
+
JS_RUN_LOG_PATH_DISABLE: ClassVar[str] = '" "'
|
|
108
|
+
#: Template for the run execution command.
|
|
109
|
+
JS_RUN_CMD: ClassVar[str] = (
|
|
110
|
+
"{workflow_app_alias} internal workflow $WK_PATH execute-run "
|
|
111
|
+
"$SUB_IDX $JS_IDX $block_idx $block_act_idx $EAR_ID\n"
|
|
112
|
+
)
|
|
113
|
+
#: Template for the execution command for multiple combined runs.
|
|
114
|
+
JS_RUN_CMD_COMBINED: ClassVar[str] = (
|
|
115
|
+
"{workflow_app_alias} internal workflow $WK_PATH execute-combined-runs "
|
|
116
|
+
"$SUB_IDX $JS_IDX\n"
|
|
117
|
+
)
|
|
118
|
+
#: Template for setting up run environment variables and executing the run.
|
|
119
|
+
JS_RUN: ClassVar[str] = dedent(
|
|
120
|
+
"""\
|
|
121
|
+
$EAR_ID = ($elem_EAR_IDs -split "{EAR_files_delimiter}")[$block_act_idx]
|
|
122
|
+
if ($EAR_ID -eq -1) {{
|
|
123
|
+
continue
|
|
124
|
+
}}
|
|
125
|
+
|
|
126
|
+
$env:{app_caps}_RUN_ID = $EAR_ID
|
|
127
|
+
$env:{app_caps}_RUN_LOG_PATH = {run_log_enable_disable}
|
|
128
|
+
$env:{app_caps}_LOG_PATH = $env:{app_caps}_RUN_LOG_PATH
|
|
129
|
+
$env:{app_caps}_RUN_STD_PATH = Join-Path $SUB_STD_DIR "$env:{app_caps}_RUN_ID.txt"
|
|
130
|
+
$env:{app_caps}_BLOCK_ACT_IDX = $block_act_idx
|
|
131
|
+
|
|
132
|
+
Set-Location $SUB_TMP_DIR
|
|
133
|
+
|
|
134
|
+
{run_cmd}
|
|
135
|
+
"""
|
|
136
|
+
)
|
|
137
|
+
#: Template for the action-run processing loop in a jobscript.
|
|
138
|
+
JS_ACT_MULTI: ClassVar[str] = dedent(
|
|
139
|
+
"""\
|
|
140
|
+
for ($block_act_idx = 0; $block_act_idx -lt {num_actions}; $block_act_idx += 1) {{
|
|
141
|
+
{run_block}
|
|
142
|
+
}}
|
|
143
|
+
"""
|
|
144
|
+
)
|
|
145
|
+
#: Template for the single-action-run execution in a jobscript.
|
|
146
|
+
JS_ACT_SINGLE: ClassVar[str] = dedent(
|
|
147
|
+
"""\
|
|
148
|
+
$block_act_idx = 0
|
|
149
|
+
{run_block}
|
|
150
|
+
"""
|
|
151
|
+
)
|
|
152
|
+
#: Template for setting up environment variables and running one or more action-runs.
|
|
153
|
+
JS_MAIN: ClassVar[str] = dedent(
|
|
154
|
+
"""\
|
|
155
|
+
$block_elem_idx = ($JS_elem_idx - {block_start_elem_idx})
|
|
156
|
+
$elem_EAR_IDs = get_nth_line $EAR_ID_FILE $JS_elem_idx
|
|
157
|
+
$env:{app_caps}_JS_ELEM_IDX = $JS_elem_idx
|
|
158
|
+
$env:{app_caps}_BLOCK_ELEM_IDX = $block_elem_idx
|
|
159
|
+
|
|
160
|
+
{action}
|
|
161
|
+
"""
|
|
162
|
+
)
|
|
163
|
+
#: Template for a jobscript-block header.
|
|
164
|
+
JS_BLOCK_HEADER: ClassVar[str] = dedent( # for single-block jobscripts only
|
|
165
|
+
"""\
|
|
166
|
+
$block_idx = 0
|
|
167
|
+
$env:{app_caps}_BLOCK_IDX = 0
|
|
168
|
+
"""
|
|
169
|
+
)
|
|
170
|
+
#: Template for single-element execution.
|
|
171
|
+
JS_ELEMENT_SINGLE: ClassVar[str] = dedent(
|
|
172
|
+
"""\
|
|
173
|
+
$JS_elem_idx = {block_start_elem_idx}
|
|
174
|
+
{main}
|
|
175
|
+
"""
|
|
176
|
+
)
|
|
177
|
+
#: Template for the element processing loop in a jobscript.
|
|
178
|
+
JS_ELEMENT_MULTI_LOOP: ClassVar[str] = dedent(
|
|
179
|
+
"""\
|
|
180
|
+
for ($JS_elem_idx = {block_start_elem_idx}; $JS_elem_idx -lt ({block_start_elem_idx} + {num_elements}); $JS_elem_idx += 1) {{
|
|
181
|
+
{main}
|
|
182
|
+
}}
|
|
183
|
+
"""
|
|
184
|
+
)
|
|
185
|
+
#: Template for the jobscript block loop in a jobscript.
|
|
186
|
+
JS_BLOCK_LOOP: ClassVar[str] = dedent(
|
|
187
|
+
"""\
|
|
188
|
+
$num_elements = {num_elements}
|
|
189
|
+
$num_actions = {num_actions}
|
|
190
|
+
$block_start_elem_idx = 0
|
|
191
|
+
for ($block_idx = 0; $block_idx -lt {num_blocks}; $block_idx += 1 ) {{
|
|
192
|
+
$env:{app_caps}_BLOCK_IDX = $block_idx
|
|
193
|
+
{element_loop}
|
|
194
|
+
$block_start_elem_idx += $num_elements[$block_idx]
|
|
195
|
+
}}
|
|
196
|
+
"""
|
|
197
|
+
)
|
|
198
|
+
#: Template for the jobscript footer.
|
|
199
|
+
JS_FOOTER: ClassVar[str] = dedent(
|
|
200
|
+
"""\
|
|
201
|
+
Set-Location $WK_PATH
|
|
202
|
+
"""
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
def get_direct_submit_command(self, js_path: str) -> list[str]:
|
|
206
|
+
"""Get the command for submitting a non-scheduled jobscript."""
|
|
207
|
+
return [*self.executable, "-File", js_path]
|
|
208
|
+
|
|
209
|
+
def get_command_file_launch_command(self, cmd_file_path: str) -> list[str]:
|
|
210
|
+
"""Get the command for launching the commands file for a given run."""
|
|
211
|
+
# note the "-File" argument is required for the correct exit code to be recorded.
|
|
212
|
+
return [*self.executable, "-File", cmd_file_path]
|
|
213
|
+
|
|
214
|
+
@override
|
|
215
|
+
def get_version_info(self, exclude_os: bool = False) -> VersionInfo:
|
|
216
|
+
"""Get powershell version information.
|
|
217
|
+
|
|
218
|
+
Parameters
|
|
219
|
+
----------
|
|
220
|
+
exclude_os
|
|
221
|
+
If True, exclude operating system information.
|
|
222
|
+
|
|
223
|
+
"""
|
|
224
|
+
|
|
225
|
+
proc = subprocess.run(
|
|
226
|
+
args=self.executable + ["-Command", "$PSVersionTable.PSVersion.ToString()"],
|
|
227
|
+
stdout=subprocess.PIPE,
|
|
228
|
+
text=True,
|
|
229
|
+
)
|
|
230
|
+
if proc.returncode == 0:
|
|
231
|
+
PS_version = proc.stdout.strip()
|
|
232
|
+
else:
|
|
233
|
+
raise RuntimeError("Failed to parse PowerShell version information.")
|
|
234
|
+
|
|
235
|
+
osinfo = {} if exclude_os else get_OS_info_windows()
|
|
236
|
+
return {
|
|
237
|
+
"shell_name": "powershell",
|
|
238
|
+
"shell_executable": self.executable,
|
|
239
|
+
"shell_version": PS_version,
|
|
240
|
+
**osinfo,
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
@staticmethod
|
|
244
|
+
def process_app_invoc_executable(app_invoc_exe: str) -> str:
|
|
245
|
+
if " " in app_invoc_exe:
|
|
246
|
+
# use call operator and single-quote the executable path:
|
|
247
|
+
app_invoc_exe = f"& '{app_invoc_exe}'"
|
|
248
|
+
return app_invoc_exe
|
|
249
|
+
|
|
250
|
+
@override
|
|
251
|
+
def format_env_var_get(self, var: str) -> str:
|
|
252
|
+
"""
|
|
253
|
+
Format retrieval of a shell environment variable.
|
|
254
|
+
"""
|
|
255
|
+
return f"$env:{var}"
|
|
256
|
+
|
|
257
|
+
@override
|
|
258
|
+
def format_array(self, lst: list) -> str:
|
|
259
|
+
"""
|
|
260
|
+
Format construction of a shell array.
|
|
261
|
+
"""
|
|
262
|
+
return "@(" + ", ".join(str(i) for i in lst) + ")"
|
|
263
|
+
|
|
264
|
+
@override
|
|
265
|
+
def format_array_get_item(self, arr_name: str, index: int | str) -> str:
|
|
266
|
+
"""
|
|
267
|
+
Format retrieval of a shell array item at a specified index.
|
|
268
|
+
"""
|
|
269
|
+
return f"${arr_name}[{index}]"
|
|
270
|
+
|
|
271
|
+
@override
|
|
272
|
+
def format_stream_assignment(self, shell_var_name: str, command: str) -> str:
|
|
273
|
+
"""
|
|
274
|
+
Produce code to assign the output of the command to a shell variable.
|
|
275
|
+
"""
|
|
276
|
+
return f"${shell_var_name} = {command}"
|
|
277
|
+
|
|
278
|
+
@override
|
|
279
|
+
def format_source_functions_file(self, app_name: str, commands: str) -> str:
|
|
280
|
+
"""
|
|
281
|
+
Format sourcing (i.e. invocation) of the jobscript functions file.
|
|
282
|
+
"""
|
|
283
|
+
app_caps = app_name.upper()
|
|
284
|
+
out = dedent(
|
|
285
|
+
"""\
|
|
286
|
+
. $env:{app_name}_JS_FUNCS_PATH
|
|
287
|
+
|
|
288
|
+
"""
|
|
289
|
+
).format(app_name=app_caps)
|
|
290
|
+
|
|
291
|
+
var_strings = (
|
|
292
|
+
f"{app_caps}_WK_PATH",
|
|
293
|
+
f"{app_caps}_SUB_SCRIPTS_DIR",
|
|
294
|
+
f"{app_caps}_JS_IDX",
|
|
295
|
+
f"{app_caps}_BLOCK_IDX",
|
|
296
|
+
f"{app_caps}_BLOCK_ACT_IDX",
|
|
297
|
+
f"{app_caps}_RUN_ID",
|
|
298
|
+
f"{app_caps}_RUN_STD_PATH",
|
|
299
|
+
f"{app_caps}_RUN_SCRIPT_NAME",
|
|
300
|
+
f"{app_caps}_RUN_SCRIPT_NAME_NO_EXT",
|
|
301
|
+
f"{app_caps}_RUN_SCRIPT_DIR",
|
|
302
|
+
f"{app_caps}_RUN_SCRIPT_PATH",
|
|
303
|
+
f"{app_caps}_RUN_PROGRAM_NAME",
|
|
304
|
+
f"{app_caps}_RUN_PROGRAM_NAME_NO_EXT",
|
|
305
|
+
f"{app_caps}_RUN_PROGRAM_DIR",
|
|
306
|
+
f"{app_caps}_RUN_PROGRAM_PATH",
|
|
307
|
+
)
|
|
308
|
+
add = False
|
|
309
|
+
for i in var_strings:
|
|
310
|
+
if i in commands:
|
|
311
|
+
add = True
|
|
312
|
+
out += f"${i} = $env:{i}\n"
|
|
313
|
+
|
|
314
|
+
if add:
|
|
315
|
+
out += "\n"
|
|
316
|
+
|
|
317
|
+
return out
|
|
318
|
+
|
|
319
|
+
@override
|
|
320
|
+
def format_commands_file(self, app_name: str, commands: str) -> str:
|
|
321
|
+
"""
|
|
322
|
+
Format the commands file.
|
|
323
|
+
"""
|
|
324
|
+
return (
|
|
325
|
+
self.format_source_functions_file(app_name, commands)
|
|
326
|
+
+ commands
|
|
327
|
+
+ "\nexit $LASTEXITCODE\n"
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
@override
|
|
331
|
+
def format_save_parameter(
|
|
332
|
+
self,
|
|
333
|
+
workflow_app_alias: str,
|
|
334
|
+
param_name: str,
|
|
335
|
+
shell_var_name: str,
|
|
336
|
+
cmd_idx: int,
|
|
337
|
+
stderr: bool,
|
|
338
|
+
app_name: str,
|
|
339
|
+
) -> str:
|
|
340
|
+
"""
|
|
341
|
+
Produce code to save a parameter's value into the workflow persistent store.
|
|
342
|
+
"""
|
|
343
|
+
# TODO: quote shell_var_name as well? e.g. if it's a white-space delimited list?
|
|
344
|
+
# and test.
|
|
345
|
+
stderr_str = " --stderr" if stderr else ""
|
|
346
|
+
app_caps = app_name.upper()
|
|
347
|
+
return (
|
|
348
|
+
f'{workflow_app_alias} --std-stream "${app_caps}_RUN_STD_PATH" '
|
|
349
|
+
f'internal workflow "${app_caps}_WK_PATH" save-parameter {stderr_str}'
|
|
350
|
+
f'"--" {param_name} ${shell_var_name} ${app_caps}_RUN_ID {cmd_idx}'
|
|
351
|
+
f"\n"
|
|
352
|
+
)
|