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
hpcflow/sdk/demo/cli.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
"""
|
2
2
|
CLI components for demonstration code.
|
3
3
|
"""
|
4
|
+
|
4
5
|
from __future__ import annotations
|
5
6
|
from pathlib import Path
|
6
7
|
from random import randint
|
@@ -25,12 +26,14 @@ from hpcflow.sdk.cli_common import (
|
|
25
26
|
cancel_opt,
|
26
27
|
submit_status_opt,
|
27
28
|
make_status_opt,
|
29
|
+
add_sub_opt,
|
28
30
|
)
|
29
31
|
|
30
32
|
if TYPE_CHECKING:
|
31
33
|
from collections.abc import Iterable
|
32
34
|
from typing import Literal
|
33
35
|
from ..app import BaseApp
|
36
|
+
from ..core.workflow import Workflow
|
34
37
|
|
35
38
|
|
36
39
|
def get_demo_software_CLI(app: BaseApp):
|
@@ -116,6 +119,7 @@ def get_demo_workflow_CLI(app: BaseApp):
|
|
116
119
|
@ts_name_fmt_option
|
117
120
|
@variables_option
|
118
121
|
@make_status_opt
|
122
|
+
@add_sub_opt
|
119
123
|
def make_demo_workflow(
|
120
124
|
workflow_name: str,
|
121
125
|
format: Literal["json", "yaml"] | None,
|
@@ -127,6 +131,7 @@ def get_demo_workflow_CLI(app: BaseApp):
|
|
127
131
|
ts_name_fmt: str | None = None,
|
128
132
|
variables: Iterable[tuple[str, str]] = (),
|
129
133
|
status: bool = True,
|
134
|
+
add_submission: bool = False,
|
130
135
|
):
|
131
136
|
wk = app.make_demo_workflow(
|
132
137
|
workflow_name=workflow_name,
|
@@ -139,7 +144,9 @@ def get_demo_workflow_CLI(app: BaseApp):
|
|
139
144
|
ts_name_fmt=ts_name_fmt,
|
140
145
|
variables=dict(variables),
|
141
146
|
status=status,
|
147
|
+
add_submission=add_submission,
|
142
148
|
)
|
149
|
+
assert isinstance(wk, Workflow)
|
143
150
|
click.echo(wk.path)
|
144
151
|
|
145
152
|
@demo_workflow.command("go")
|
hpcflow/sdk/helper/cli.py
CHANGED
hpcflow/sdk/log.py
CHANGED
@@ -58,6 +58,17 @@ class TimeIt:
|
|
58
58
|
#: Preceding trace indices.
|
59
59
|
trace_idx_prev: ClassVar[list[int]] = []
|
60
60
|
|
61
|
+
def __enter__(self):
|
62
|
+
self.__class__.active = True
|
63
|
+
return self
|
64
|
+
|
65
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
66
|
+
try:
|
67
|
+
self.__class__.summarise_string()
|
68
|
+
finally:
|
69
|
+
self.__class__.reset()
|
70
|
+
self.__class__.active = False
|
71
|
+
|
61
72
|
@classmethod
|
62
73
|
def decorator(cls, func: Callable[P, T]) -> Callable[P, T]:
|
63
74
|
"""
|
@@ -167,6 +178,14 @@ class TimeIt:
|
|
167
178
|
else:
|
168
179
|
print(out_str)
|
169
180
|
|
181
|
+
@classmethod
|
182
|
+
def reset(cls):
|
183
|
+
cls.timers = defaultdict(list)
|
184
|
+
cls.trace = []
|
185
|
+
cls.trace_idx = []
|
186
|
+
cls.trace_prev = []
|
187
|
+
cls.trace_idx_prev = []
|
188
|
+
|
170
189
|
|
171
190
|
class AppLog:
|
172
191
|
"""
|
@@ -176,11 +195,11 @@ class AppLog:
|
|
176
195
|
#: Default logging level for the console.
|
177
196
|
DEFAULT_LOG_CONSOLE_LEVEL: ClassVar = "WARNING"
|
178
197
|
#: Default logging level for log files.
|
179
|
-
DEFAULT_LOG_FILE_LEVEL: ClassVar = "
|
198
|
+
DEFAULT_LOG_FILE_LEVEL: ClassVar = "WARNING"
|
180
199
|
|
181
200
|
def __init__(self, app: BaseApp, log_console_level: str | None = None) -> None:
|
182
201
|
#: The application context.
|
183
|
-
self.
|
202
|
+
self._app = app
|
184
203
|
#: The base logger for the application.
|
185
204
|
self.logger = logging.getLogger(app.package_name)
|
186
205
|
self.logger.setLevel(logging.DEBUG)
|
@@ -188,6 +207,7 @@ class AppLog:
|
|
188
207
|
self.console_handler = self.__add_console_logger(
|
189
208
|
level=log_console_level or AppLog.DEFAULT_LOG_CONSOLE_LEVEL
|
190
209
|
)
|
210
|
+
self.file_handler: logging.FileHandler | None = None
|
191
211
|
|
192
212
|
def __add_console_logger(self, level: str, fmt: str | None = None) -> logging.Handler:
|
193
213
|
fmt = fmt or "%(levelname)s %(name)s: %(message)s"
|
@@ -197,23 +217,29 @@ class AppLog:
|
|
197
217
|
self.logger.addHandler(handler)
|
198
218
|
return handler
|
199
219
|
|
200
|
-
def update_console_level(self, new_level: str) -> None:
|
220
|
+
def update_console_level(self, new_level: str | None = None) -> None:
|
201
221
|
"""
|
202
222
|
Set the logging level for console messages.
|
203
223
|
"""
|
204
|
-
|
205
|
-
|
224
|
+
new_level = new_level or AppLog.DEFAULT_LOG_CONSOLE_LEVEL
|
225
|
+
self.console_handler.setLevel(new_level.upper())
|
226
|
+
|
227
|
+
def update_file_level(self, new_level: str | None = None) -> None:
|
228
|
+
if self.file_handler:
|
229
|
+
new_level = new_level or AppLog.DEFAULT_LOG_FILE_LEVEL
|
230
|
+
self.file_handler.setLevel(new_level.upper())
|
206
231
|
|
207
232
|
def add_file_logger(
|
208
233
|
self,
|
209
|
-
path: Path,
|
234
|
+
path: str | Path,
|
210
235
|
level: str | None = None,
|
211
236
|
fmt: str | None = None,
|
212
237
|
max_bytes: int | None = None,
|
213
|
-
) ->
|
238
|
+
) -> None:
|
214
239
|
"""
|
215
240
|
Add a log file.
|
216
241
|
"""
|
242
|
+
path = Path(path)
|
217
243
|
fmt = fmt or "%(asctime)s %(levelname)s %(name)s: %(message)s"
|
218
244
|
level = level or AppLog.DEFAULT_LOG_FILE_LEVEL
|
219
245
|
max_bytes = max_bytes or int(10e6)
|
@@ -226,12 +252,13 @@ class AppLog:
|
|
226
252
|
handler.setFormatter(logging.Formatter(fmt))
|
227
253
|
handler.setLevel(level.upper())
|
228
254
|
self.logger.addHandler(handler)
|
229
|
-
|
255
|
+
self.file_handler = handler
|
230
256
|
|
231
|
-
def
|
232
|
-
"""Remove
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
257
|
+
def remove_file_handler(self) -> None:
|
258
|
+
"""Remove the file handler."""
|
259
|
+
if self.file_handler:
|
260
|
+
self.logger.debug(
|
261
|
+
f"Removing file handler from the AppLog: {self.file_handler!r}."
|
262
|
+
)
|
263
|
+
self.logger.removeHandler(self.file_handler)
|
264
|
+
self.file_handler = None
|