hpcflow-new2 0.2.0a190__py3-none-any.whl → 0.2.0a199__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/__pyinstaller/hook-hpcflow.py +1 -0
- hpcflow/_version.py +1 -1
- hpcflow/data/scripts/bad_script.py +2 -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/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_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_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_hdf5_in_obj_2.py +12 -0
- hpcflow/data/scripts/main_script_test_json_out_FAIL.py +3 -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/script_exit_test.py +5 -0
- hpcflow/data/template_components/environments.yaml +1 -1
- hpcflow/sdk/__init__.py +5 -0
- hpcflow/sdk/app.py +150 -89
- hpcflow/sdk/cli.py +263 -84
- hpcflow/sdk/cli_common.py +99 -5
- hpcflow/sdk/config/callbacks.py +38 -1
- hpcflow/sdk/config/config.py +102 -13
- hpcflow/sdk/config/errors.py +19 -5
- hpcflow/sdk/config/types.py +3 -0
- hpcflow/sdk/core/__init__.py +25 -1
- hpcflow/sdk/core/actions.py +914 -262
- hpcflow/sdk/core/cache.py +76 -34
- hpcflow/sdk/core/command_files.py +14 -128
- hpcflow/sdk/core/commands.py +35 -6
- hpcflow/sdk/core/element.py +122 -50
- hpcflow/sdk/core/errors.py +58 -2
- hpcflow/sdk/core/execute.py +207 -0
- hpcflow/sdk/core/loop.py +408 -50
- hpcflow/sdk/core/loop_cache.py +4 -4
- hpcflow/sdk/core/parameters.py +382 -37
- hpcflow/sdk/core/run_dir_files.py +13 -40
- hpcflow/sdk/core/skip_reason.py +7 -0
- hpcflow/sdk/core/task.py +119 -30
- hpcflow/sdk/core/task_schema.py +68 -0
- hpcflow/sdk/core/test_utils.py +66 -27
- hpcflow/sdk/core/types.py +54 -1
- hpcflow/sdk/core/utils.py +78 -7
- hpcflow/sdk/core/workflow.py +1538 -336
- hpcflow/sdk/data/workflow_spec_schema.yaml +2 -0
- hpcflow/sdk/demo/cli.py +7 -0
- hpcflow/sdk/helper/cli.py +1 -0
- hpcflow/sdk/log.py +42 -15
- hpcflow/sdk/persistence/base.py +405 -53
- hpcflow/sdk/persistence/json.py +177 -52
- hpcflow/sdk/persistence/pending.py +237 -69
- hpcflow/sdk/persistence/store_resource.py +3 -2
- hpcflow/sdk/persistence/types.py +15 -4
- hpcflow/sdk/persistence/zarr.py +928 -81
- hpcflow/sdk/submission/jobscript.py +1408 -489
- hpcflow/sdk/submission/schedulers/__init__.py +40 -5
- hpcflow/sdk/submission/schedulers/direct.py +33 -19
- hpcflow/sdk/submission/schedulers/sge.py +51 -16
- hpcflow/sdk/submission/schedulers/slurm.py +44 -16
- hpcflow/sdk/submission/schedulers/utils.py +7 -2
- hpcflow/sdk/submission/shells/base.py +68 -20
- hpcflow/sdk/submission/shells/bash.py +222 -129
- hpcflow/sdk/submission/shells/powershell.py +200 -150
- hpcflow/sdk/submission/submission.py +852 -119
- hpcflow/sdk/submission/types.py +18 -21
- hpcflow/sdk/typing.py +24 -5
- hpcflow/sdk/utils/arrays.py +71 -0
- hpcflow/sdk/utils/deferred_file.py +55 -0
- hpcflow/sdk/utils/hashing.py +16 -0
- hpcflow/sdk/utils/patches.py +12 -0
- hpcflow/sdk/utils/strings.py +33 -0
- hpcflow/tests/api/test_api.py +32 -0
- hpcflow/tests/conftest.py +19 -0
- hpcflow/tests/data/multi_path_sequences.yaml +29 -0
- hpcflow/tests/data/workflow_test_run_abort.yaml +34 -35
- hpcflow/tests/schedulers/sge/test_sge_submission.py +36 -0
- hpcflow/tests/scripts/test_input_file_generators.py +282 -0
- hpcflow/tests/scripts/test_main_scripts.py +821 -70
- 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 +6 -0
- hpcflow/tests/unit/test_action.py +176 -0
- hpcflow/tests/unit/test_app.py +20 -0
- hpcflow/tests/unit/test_cache.py +46 -0
- hpcflow/tests/unit/test_cli.py +133 -0
- hpcflow/tests/unit/test_config.py +122 -1
- hpcflow/tests/unit/test_element_iteration.py +47 -0
- hpcflow/tests/unit/test_jobscript_unit.py +757 -0
- hpcflow/tests/unit/test_loop.py +1332 -27
- hpcflow/tests/unit/test_meta_task.py +325 -0
- hpcflow/tests/unit/test_multi_path_sequences.py +229 -0
- hpcflow/tests/unit/test_parameter.py +13 -0
- hpcflow/tests/unit/test_persistence.py +190 -8
- hpcflow/tests/unit/test_run.py +109 -3
- hpcflow/tests/unit/test_run_directories.py +29 -0
- hpcflow/tests/unit/test_shell.py +20 -0
- hpcflow/tests/unit/test_submission.py +5 -76
- 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/workflows/__init__.py +0 -0
- hpcflow/tests/workflows/test_directory_structure.py +31 -0
- hpcflow/tests/workflows/test_jobscript.py +332 -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 +142 -2
- hpcflow/tests/workflows/test_zip.py +18 -0
- hpcflow/viz_demo.ipynb +6587 -3
- {hpcflow_new2-0.2.0a190.dist-info → hpcflow_new2-0.2.0a199.dist-info}/METADATA +7 -4
- hpcflow_new2-0.2.0a199.dist-info/RECORD +221 -0
- hpcflow_new2-0.2.0a190.dist-info/RECORD +0 -165
- {hpcflow_new2-0.2.0a190.dist-info → hpcflow_new2-0.2.0a199.dist-info}/LICENSE +0 -0
- {hpcflow_new2-0.2.0a190.dist-info → hpcflow_new2-0.2.0a199.dist-info}/WHEEL +0 -0
- {hpcflow_new2-0.2.0a190.dist-info → hpcflow_new2-0.2.0a199.dist-info}/entry_points.txt +0 -0
@@ -39,25 +39,50 @@ class Bash(Shell):
|
|
39
39
|
JS_ENV_SETUP_INDENT: ClassVar[str] = 2 * JS_INDENT
|
40
40
|
#: Template for the jobscript shebang line.
|
41
41
|
JS_SHEBANG: ClassVar[str] = """#!{shebang_executable} {shebang_args}"""
|
42
|
-
#: Template for the
|
43
|
-
|
42
|
+
#: Template for the jobscript functions file.
|
43
|
+
JS_FUNCS: ClassVar[str] = dedent(
|
44
44
|
"""\
|
45
45
|
{workflow_app_alias} () {{
|
46
46
|
(
|
47
47
|
{env_setup}{app_invoc}\\
|
48
|
-
--with-config log_file_path "
|
48
|
+
--with-config log_file_path "${app_caps}_LOG_PATH"\\
|
49
49
|
--config-dir "{config_dir}"\\
|
50
50
|
--config-key "{config_invoc_key}"\\
|
51
51
|
"$@"
|
52
52
|
)
|
53
53
|
}}
|
54
|
-
|
54
|
+
"""
|
55
|
+
)
|
56
|
+
#: Template for the common part of the jobscript header.
|
57
|
+
JS_HEADER: ClassVar[str] = dedent(
|
58
|
+
"""\
|
55
59
|
WK_PATH=`pwd`
|
56
60
|
WK_PATH_ARG="$WK_PATH"
|
57
61
|
SUB_IDX={sub_idx}
|
58
62
|
JS_IDX={js_idx}
|
59
|
-
|
60
|
-
|
63
|
+
APP_CAPS={app_caps}
|
64
|
+
|
65
|
+
SUB_DIR="$WK_PATH/artifacts/submissions/${{SUB_IDX}}"
|
66
|
+
JS_FUNCS_PATH="$SUB_DIR/{jobscript_functions_dir}/{jobscript_functions_name}"
|
67
|
+
. "$JS_FUNCS_PATH"
|
68
|
+
|
69
|
+
EAR_ID_FILE="$WK_PATH/artifacts/submissions/${{SUB_IDX}}/{run_IDs_file_dir}/{run_IDs_file_name}"
|
70
|
+
SUB_TMP_DIR="$SUB_DIR/{tmp_dir_name}"
|
71
|
+
SUB_LOG_DIR="$SUB_DIR/{log_dir_name}"
|
72
|
+
SUB_STD_DIR="$SUB_DIR/{app_std_dir_name}"
|
73
|
+
SUB_SCRIPTS_DIR="$SUB_DIR/{scripts_dir_name}"
|
74
|
+
|
75
|
+
export {app_caps}_WK_PATH=$WK_PATH
|
76
|
+
export {app_caps}_WK_PATH_ARG=$WK_PATH_ARG
|
77
|
+
export {app_caps}_SUB_IDX={sub_idx}
|
78
|
+
export {app_caps}_SUB_SCRIPTS_DIR=$SUB_SCRIPTS_DIR
|
79
|
+
export {app_caps}_SUB_TMP_DIR=$SUB_TMP_DIR
|
80
|
+
export {app_caps}_SUB_LOG_DIR=$SUB_LOG_DIR
|
81
|
+
export {app_caps}_SUB_STD_DIR=$SUB_STD_DIR
|
82
|
+
export {app_caps}_LOG_PATH="$SUB_LOG_DIR/js_${{JS_IDX}}.log"
|
83
|
+
export {app_caps}_JS_FUNCS_PATH=$JS_FUNCS_PATH
|
84
|
+
export {app_caps}_JS_IDX={js_idx}
|
85
|
+
export {app_caps}_RUN_ID_FILE=$EAR_ID_FILE
|
61
86
|
"""
|
62
87
|
)
|
63
88
|
#: Template for the jobscript header when scheduled.
|
@@ -73,76 +98,118 @@ class Bash(Shell):
|
|
73
98
|
JS_DIRECT_HEADER: ClassVar[str] = dedent(
|
74
99
|
"""\
|
75
100
|
{shebang}
|
76
|
-
|
77
101
|
{header}
|
78
102
|
{wait_command}
|
79
103
|
"""
|
80
104
|
)
|
81
|
-
#: Template for the
|
105
|
+
#: Template for enabling writing of the app log.
|
106
|
+
JS_RUN_LOG_PATH_ENABLE: ClassVar[str] = '"$SUB_LOG_DIR/{run_log_file_name}"'
|
107
|
+
#: Template for disabling writing of the app log.
|
108
|
+
JS_RUN_LOG_PATH_DISABLE: ClassVar[str] = '" "'
|
109
|
+
#: Template for the run execution command.
|
110
|
+
JS_RUN_CMD: ClassVar[str] = (
|
111
|
+
'{workflow_app_alias} internal workflow "$WK_PATH_ARG" execute-run '
|
112
|
+
"$SUB_IDX $JS_IDX $block_idx $block_act_idx $EAR_ID\n"
|
113
|
+
)
|
114
|
+
#: Template for the execution command for multiple combined runs.
|
115
|
+
JS_RUN_CMD_COMBINED: ClassVar[str] = (
|
116
|
+
'{workflow_app_alias} internal workflow "$WK_PATH_ARG" execute-combined-runs '
|
117
|
+
"$SUB_IDX $JS_IDX\n"
|
118
|
+
)
|
119
|
+
#: Template for setting up run environment variables and executing the run.
|
120
|
+
JS_RUN: ClassVar[str] = dedent(
|
121
|
+
"""\
|
122
|
+
EAR_ID="$(cut -d'{EAR_files_delimiter}' -f $(($block_act_idx + 1)) <<< $elem_EAR_IDs)"
|
123
|
+
if [ "$EAR_ID" = "-1" ]; then
|
124
|
+
continue
|
125
|
+
fi
|
126
|
+
|
127
|
+
export {app_caps}_RUN_ID=$EAR_ID
|
128
|
+
export {app_caps}_RUN_LOG_PATH={run_log_enable_disable}
|
129
|
+
export {app_caps}_LOG_PATH="${app_caps}_RUN_LOG_PATH"
|
130
|
+
export {app_caps}_RUN_STD_PATH="$SUB_STD_DIR/${app_caps}_RUN_ID.txt"
|
131
|
+
export {app_caps}_BLOCK_ACT_IDX=$block_act_idx
|
132
|
+
|
133
|
+
cd "$SUB_TMP_DIR"
|
134
|
+
|
135
|
+
{run_cmd}
|
136
|
+
"""
|
137
|
+
)
|
138
|
+
#: Template for the action-run processing loop in a jobscript.
|
139
|
+
JS_ACT_MULTI: ClassVar[str] = dedent(
|
140
|
+
"""\
|
141
|
+
for ((block_act_idx=0;block_act_idx<{num_actions};block_act_idx++))
|
142
|
+
do
|
143
|
+
{run_block}
|
144
|
+
done
|
145
|
+
"""
|
146
|
+
)
|
147
|
+
#: Template for the single-action-run execution in a jobscript.
|
148
|
+
JS_ACT_SINGLE: ClassVar[str] = dedent(
|
149
|
+
"""\
|
150
|
+
block_act_idx=0
|
151
|
+
{run_block}
|
152
|
+
"""
|
153
|
+
)
|
154
|
+
#: Template for setting up environment variables and running one or more action-runs.
|
82
155
|
JS_MAIN: ClassVar[str] = dedent(
|
83
156
|
"""\
|
157
|
+
block_elem_idx=$(( $JS_elem_idx - {block_start_elem_idx} ))
|
84
158
|
elem_EAR_IDs=`sed "$((${{JS_elem_idx}} + 1))q;d" "$EAR_ID_FILE"`
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
if [ "$skip" = "1" ]; then
|
105
|
-
continue
|
106
|
-
fi
|
107
|
-
|
108
|
-
{workflow_app_alias} internal workflow "$WK_PATH_ARG" write-commands $SUB_IDX $JS_IDX $JS_act_idx $EAR_ID >> "$app_stream_file" 2>&1
|
109
|
-
exc_wc=$?
|
110
|
-
|
111
|
-
{workflow_app_alias} internal workflow "$WK_PATH_ARG" set-ear-start $EAR_ID >> "$app_stream_file" 2>&1
|
112
|
-
exc_se=$?
|
113
|
-
|
114
|
-
if [ $exc_wc -eq 0 ] && [ $exc_se -eq 0 ]; then
|
115
|
-
. {commands_file_name}
|
116
|
-
exit_code=$?
|
117
|
-
else
|
118
|
-
exit_code=$([ $exc_wc -ne 0 ] && echo "$exc_wc" || echo "$exc_se")
|
119
|
-
fi
|
120
|
-
|
121
|
-
else
|
122
|
-
exit_code=$exc_sk
|
123
|
-
fi
|
124
|
-
|
125
|
-
{workflow_app_alias} internal workflow "$WK_PATH_ARG" set-ear-end $JS_IDX $JS_act_idx $EAR_ID "--" "$exit_code" >> "$app_stream_file" 2>&1
|
126
|
-
|
127
|
-
done
|
159
|
+
export {app_caps}_JS_ELEM_IDX=$JS_elem_idx
|
160
|
+
export {app_caps}_BLOCK_ELEM_IDX=$block_elem_idx
|
161
|
+
|
162
|
+
{action}
|
163
|
+
"""
|
164
|
+
)
|
165
|
+
#: Template for a jobscript-block header.
|
166
|
+
JS_BLOCK_HEADER: ClassVar[str] = dedent( # for single-block jobscripts only
|
167
|
+
"""\
|
168
|
+
block_idx=0
|
169
|
+
export {app_caps}_BLOCK_IDX=0
|
170
|
+
"""
|
171
|
+
)
|
172
|
+
#: Template for single-element execution.
|
173
|
+
JS_ELEMENT_SINGLE: ClassVar[str] = dedent(
|
174
|
+
"""\
|
175
|
+
JS_elem_idx={block_start_elem_idx}
|
176
|
+
{main}
|
128
177
|
"""
|
129
178
|
)
|
130
179
|
#: Template for the element processing loop in a jobscript.
|
131
|
-
|
180
|
+
JS_ELEMENT_MULTI_LOOP: ClassVar[str] = dedent(
|
132
181
|
"""\
|
133
|
-
for ((JS_elem_idx=
|
182
|
+
for ((JS_elem_idx={block_start_elem_idx};JS_elem_idx<$(({block_start_elem_idx} + {num_elements}));JS_elem_idx++))
|
134
183
|
do
|
135
184
|
{main}
|
136
185
|
done
|
137
|
-
cd "$WK_PATH"
|
138
186
|
"""
|
139
187
|
)
|
140
188
|
#: Template for the array handling code in a jobscript.
|
141
|
-
|
189
|
+
JS_ELEMENT_MULTI_ARRAY: ClassVar[str] = dedent(
|
142
190
|
"""\
|
143
191
|
JS_elem_idx=$(({scheduler_array_item_var} - 1))
|
144
192
|
{main}
|
145
|
-
|
193
|
+
"""
|
194
|
+
)
|
195
|
+
#: Template for the jobscript block loop in a jobscript.
|
196
|
+
JS_BLOCK_LOOP: ClassVar[str] = dedent(
|
197
|
+
"""\
|
198
|
+
num_elements={num_elements}
|
199
|
+
num_actions={num_actions}
|
200
|
+
block_start_elem_idx=0
|
201
|
+
for ((block_idx=0;block_idx<{num_blocks};block_idx++))
|
202
|
+
do
|
203
|
+
export {app_caps}_BLOCK_IDX=$block_idx
|
204
|
+
{element_loop}
|
205
|
+
block_start_elem_idx=$(($block_start_elem_idx + ${{num_elements[$block_idx]}}))
|
206
|
+
done
|
207
|
+
"""
|
208
|
+
)
|
209
|
+
#: Template for the jobscript footer.
|
210
|
+
JS_FOOTER: ClassVar[str] = dedent(
|
211
|
+
"""\
|
212
|
+
cd $WK_PATH
|
146
213
|
"""
|
147
214
|
)
|
148
215
|
|
@@ -191,22 +258,61 @@ class Bash(Shell):
|
|
191
258
|
return app_invoc_exe.replace(" ", r"\ ")
|
192
259
|
|
193
260
|
@override
|
194
|
-
|
195
|
-
|
261
|
+
def format_env_var_get(self, var: str) -> str:
|
262
|
+
"""
|
263
|
+
Format retrieval of a shell environment variable.
|
264
|
+
"""
|
265
|
+
return f"${var}"
|
266
|
+
|
267
|
+
@override
|
268
|
+
def format_array(self, lst: list) -> str:
|
269
|
+
"""
|
270
|
+
Format construction of a shell array.
|
271
|
+
"""
|
272
|
+
return "(" + " ".join(str(i) for i in lst) + ")"
|
273
|
+
|
274
|
+
@override
|
275
|
+
def format_array_get_item(self, arr_name: str, index: int | str) -> str:
|
276
|
+
"""
|
277
|
+
Format retrieval of a shell array item at a specified index.
|
278
|
+
"""
|
279
|
+
return f"${{{arr_name}[{index}]}}"
|
280
|
+
|
281
|
+
@override
|
282
|
+
def format_stream_assignment(self, shell_var_name: str, command: str) -> str:
|
196
283
|
"""
|
197
284
|
Produce code to assign the output of the command to a shell variable.
|
198
285
|
"""
|
199
286
|
return f"{shell_var_name}=`{command}`"
|
200
287
|
|
288
|
+
@override
|
289
|
+
def format_source_functions_file(self, app_name: str, commands: str) -> str:
|
290
|
+
"""
|
291
|
+
Format sourcing (i.e. invocation) of the jobscript functions file.
|
292
|
+
"""
|
293
|
+
return dedent(
|
294
|
+
"""\
|
295
|
+
. "${app_caps}_JS_FUNCS_PATH"
|
296
|
+
|
297
|
+
"""
|
298
|
+
).format(app_caps=app_name.upper())
|
299
|
+
|
300
|
+
@override
|
301
|
+
def format_commands_file(self, app_name: str, commands: str) -> str:
|
302
|
+
"""
|
303
|
+
Format the commands file.
|
304
|
+
"""
|
305
|
+
return self.format_source_functions_file(app_name, commands) + commands
|
306
|
+
|
201
307
|
@override
|
202
308
|
def format_save_parameter(
|
203
309
|
self,
|
204
310
|
workflow_app_alias: str,
|
205
311
|
param_name: str,
|
206
312
|
shell_var_name: str,
|
207
|
-
EAR_ID: int,
|
208
313
|
cmd_idx: int,
|
209
314
|
stderr: bool,
|
315
|
+
app_name: str,
|
210
316
|
):
|
211
317
|
"""
|
212
318
|
Produce code to save a parameter's value into the workflow persistent store.
|
@@ -214,78 +320,15 @@ class Bash(Shell):
|
|
214
320
|
# TODO: quote shell_var_name as well? e.g. if it's a white-space delimited list?
|
215
321
|
# and test.
|
216
322
|
stderr_str = " --stderr" if stderr else ""
|
323
|
+
app_caps = app_name.upper()
|
217
324
|
return (
|
218
|
-
f
|
219
|
-
f'internal workflow "$
|
220
|
-
f"{param_name} ${shell_var_name} {
|
221
|
-
f'>> "$app_stream_file" 2>&1'
|
325
|
+
f'{workflow_app_alias} --std-stream "${app_caps}_RUN_STD_PATH" '
|
326
|
+
f'internal workflow "${app_caps}_WK_PATH_ARG" save-parameter {stderr_str}'
|
327
|
+
f'"--" {param_name} ${shell_var_name} ${app_caps}_RUN_ID {cmd_idx}'
|
222
328
|
f"\n"
|
223
329
|
)
|
224
330
|
|
225
|
-
@override
|
226
|
-
def format_loop_check(
|
227
|
-
self, workflow_app_alias: str, loop_name: str, run_ID: int
|
228
|
-
) -> str:
|
229
|
-
"""
|
230
|
-
Produce code to check the looping status of part of a workflow.
|
231
|
-
"""
|
232
|
-
return (
|
233
|
-
f"{workflow_app_alias} "
|
234
|
-
f'internal workflow "$WK_PATH_ARG" check-loop '
|
235
|
-
f"{loop_name} {run_ID} "
|
236
|
-
f'>> "$app_stream_file" 2>&1'
|
237
|
-
f"\n"
|
238
|
-
)
|
239
|
-
|
240
|
-
@override
|
241
|
-
def wrap_in_subshell(self, commands: str, abortable: bool) -> str:
|
242
|
-
"""Format commands to run within a subshell.
|
243
331
|
|
244
|
-
This assumes commands ends in a newline.
|
245
|
-
|
246
|
-
"""
|
247
|
-
commands = indent(commands, self.JS_INDENT)
|
248
|
-
if abortable:
|
249
|
-
# run commands in the background, and poll a file to check for abort requests:
|
250
|
-
return dedent(
|
251
|
-
"""\
|
252
|
-
(
|
253
|
-
{commands}) &
|
254
|
-
|
255
|
-
pid=$!
|
256
|
-
abort_file=$WK_PATH/artifacts/submissions/$SUB_IDX/abort_EARs.txt
|
257
|
-
while true
|
258
|
-
do
|
259
|
-
is_abort=`sed "$(($EAR_ID + 1))q;d" $abort_file`
|
260
|
-
ps -p $pid > /dev/null
|
261
|
-
if [ $? == 1 ]; then
|
262
|
-
wait $pid
|
263
|
-
exitcode=$?
|
264
|
-
break
|
265
|
-
elif [ "$is_abort" = "1" ]; then
|
266
|
-
echo "Abort instruction received; stopping commands..." >> "$app_stream_file"
|
267
|
-
kill $pid
|
268
|
-
wait $pid 2>/dev/null
|
269
|
-
exitcode={abort_exit_code}
|
270
|
-
break
|
271
|
-
else
|
272
|
-
sleep 1 # TODO: TEMP: increase for production
|
273
|
-
fi
|
274
|
-
done
|
275
|
-
return $exitcode
|
276
|
-
"""
|
277
|
-
).format(commands=commands, abort_exit_code=ABORT_EXIT_CODE)
|
278
|
-
else:
|
279
|
-
# run commands in "foreground":
|
280
|
-
return dedent(
|
281
|
-
"""\
|
282
|
-
(
|
283
|
-
{commands})
|
284
|
-
"""
|
285
|
-
).format(commands=commands)
|
286
|
-
|
287
|
-
|
288
|
-
@hydrate
|
289
332
|
class WSLBash(Bash):
|
290
333
|
"""
|
291
334
|
A variant of bash that handles running under WSL on Windows.
|
@@ -294,13 +337,59 @@ class WSLBash(Bash):
|
|
294
337
|
#: Default name of the WSL interface executable.
|
295
338
|
DEFAULT_WSL_EXE: ClassVar[str] = "wsl"
|
296
339
|
|
340
|
+
#: Template for the jobscript functions file.
|
341
|
+
JS_FUNCS: ClassVar[str] = dedent(
|
342
|
+
"""\
|
343
|
+
{{workflow_app_alias}} () {{{{
|
344
|
+
(
|
345
|
+
{log_path_block}
|
346
|
+
{{env_setup}}{{app_invoc}}\\
|
347
|
+
--with-config log_file_path "$LOG_FILE_PATH"\\
|
348
|
+
--config-dir "{{config_dir}}"\\
|
349
|
+
--config-key "{{config_invoc_key}}"\\
|
350
|
+
"$@"
|
351
|
+
)
|
352
|
+
}}}}
|
353
|
+
"""
|
354
|
+
).format(
|
355
|
+
log_path_block=indent(
|
356
|
+
dedent(
|
357
|
+
"""\
|
358
|
+
if [ -z "${app_caps}_LOG_PATH" ] || [ "${app_caps}_LOG_PATH" = " " ]; then
|
359
|
+
LOG_FILE_PATH=" "
|
360
|
+
else
|
361
|
+
LOG_FILE_PATH="$(wslpath -m ${app_caps}_LOG_PATH)"
|
362
|
+
fi
|
363
|
+
"""
|
364
|
+
),
|
365
|
+
prefix=Bash.JS_ENV_SETUP_INDENT,
|
366
|
+
)
|
367
|
+
)
|
297
368
|
#: Template for the common part of the jobscript header.
|
298
369
|
JS_HEADER: ClassVar[str] = Bash.JS_HEADER.replace(
|
299
370
|
'WK_PATH_ARG="$WK_PATH"',
|
300
371
|
'WK_PATH_ARG=`wslpath -m "$WK_PATH"`',
|
301
|
-
)
|
302
|
-
|
303
|
-
|
372
|
+
)
|
373
|
+
#: Template for the run execution command.
|
374
|
+
JS_RUN_CMD: ClassVar[str] = (
|
375
|
+
dedent(
|
376
|
+
"""\
|
377
|
+
WSLENV=$WSLENV:${{APP_CAPS}}_WK_PATH
|
378
|
+
WSLENV=$WSLENV:${{APP_CAPS}}_WK_PATH_ARG
|
379
|
+
WSLENV=$WSLENV:${{APP_CAPS}}_JS_FUNCS_PATH
|
380
|
+
WSLENV=$WSLENV:${{APP_CAPS}}_STD_STREAM_FILE
|
381
|
+
WSLENV=$WSLENV:${{APP_CAPS}}_SUB_IDX
|
382
|
+
WSLENV=$WSLENV:${{APP_CAPS}}_JS_IDX
|
383
|
+
WSLENV=$WSLENV:${{APP_CAPS}}_RUN_ID
|
384
|
+
WSLENV=$WSLENV:${{APP_CAPS}}_BLOCK_ACT_IDX
|
385
|
+
WSLENV=$WSLENV:${{APP_CAPS}}_JS_ELEM_IDX
|
386
|
+
WSLENV=$WSLENV:${{APP_CAPS}}_BLOCK_ELEM_IDX
|
387
|
+
WSLENV=$WSLENV:${{APP_CAPS}}_BLOCK_IDX
|
388
|
+
WSLENV=$WSLENV:${{APP_CAPS}}_LOG_PATH/p
|
389
|
+
|
390
|
+
"""
|
391
|
+
)
|
392
|
+
+ Bash.JS_RUN_CMD
|
304
393
|
)
|
305
394
|
|
306
395
|
def __init__(
|
@@ -398,3 +487,7 @@ class WSLBash(Bash):
|
|
398
487
|
vers_info.update(**get_OS_info_windows())
|
399
488
|
|
400
489
|
return vers_info
|
490
|
+
|
491
|
+
def get_command_file_launch_command(self, cmd_file_path: str) -> list[str]:
|
492
|
+
"""Get the command for launching the commands file for a given run."""
|
493
|
+
return self.executable + [self._convert_to_wsl_path(cmd_file_path)]
|