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,221 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Core enumeration types.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
from collections.abc import Sequence
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from enum import Enum
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ActionScopeType(Enum):
|
|
12
|
+
"""
|
|
13
|
+
Types of action scope.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
#: Scope that applies to anything.
|
|
17
|
+
ANY = 0
|
|
18
|
+
#: Scope that only applies to main scripts.
|
|
19
|
+
MAIN = 1
|
|
20
|
+
#: Scope that applies to processing steps.
|
|
21
|
+
PROCESSING = 2
|
|
22
|
+
#: Scope that applies to input file generators.
|
|
23
|
+
INPUT_FILE_GENERATOR = 3
|
|
24
|
+
#: Scope that applies to output file parsers.
|
|
25
|
+
OUTPUT_FILE_PARSER = 4
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass(frozen=True)
|
|
29
|
+
class _ReportableStateData:
|
|
30
|
+
"""
|
|
31
|
+
Model of the state of something that is renderable using a symbol and colour.
|
|
32
|
+
|
|
33
|
+
Notes
|
|
34
|
+
-----
|
|
35
|
+
This class is used as the value in the the enumeration subclasses
|
|
36
|
+
:py:class:`EARStatus` and :py:class:`JobscriptElementState`.
|
|
37
|
+
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
#: ID that distinguishes the state.
|
|
41
|
+
id: int
|
|
42
|
+
#: Symbol to use when rendering a state.
|
|
43
|
+
symbol: str
|
|
44
|
+
#: Colour to use when rendering a state.
|
|
45
|
+
colour: str
|
|
46
|
+
#: Documentation of the meaning of the state.
|
|
47
|
+
__doc__: str = ""
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class _ReportableStateEnum(Enum):
|
|
51
|
+
"""Enumeration superclass for reportable state subclasses with some shared methods."""
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def id(self) -> int:
|
|
55
|
+
"""
|
|
56
|
+
The integer ID associated with this state.
|
|
57
|
+
"""
|
|
58
|
+
return self.value.id
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def colour(self) -> str:
|
|
62
|
+
"""
|
|
63
|
+
The colour associated with this state.
|
|
64
|
+
"""
|
|
65
|
+
return self.value.colour
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def symbol(self) -> str:
|
|
69
|
+
"""
|
|
70
|
+
The symbol associated with this state.
|
|
71
|
+
"""
|
|
72
|
+
return self.value.symbol
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def rich_repr(self) -> str:
|
|
76
|
+
"""
|
|
77
|
+
Rich representation of this enumeration element.
|
|
78
|
+
"""
|
|
79
|
+
return f"[{self.colour}]{self.symbol}[/{self.colour}]"
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class EARStatus(_ReportableStateEnum):
|
|
83
|
+
"""Enumeration of all possible EAR statuses, and their associated status colour."""
|
|
84
|
+
|
|
85
|
+
#: Not yet associated with a submission.
|
|
86
|
+
pending = _ReportableStateData(
|
|
87
|
+
0,
|
|
88
|
+
".",
|
|
89
|
+
"grey46",
|
|
90
|
+
"Not yet associated with a submission.",
|
|
91
|
+
)
|
|
92
|
+
#: Associated with a prepared submission that is not yet submitted.
|
|
93
|
+
prepared = _ReportableStateData(
|
|
94
|
+
1,
|
|
95
|
+
".",
|
|
96
|
+
"grey46",
|
|
97
|
+
"Associated with a prepared submission that is not yet submitted.",
|
|
98
|
+
)
|
|
99
|
+
#: Submitted for execution.
|
|
100
|
+
submitted = _ReportableStateData(
|
|
101
|
+
2,
|
|
102
|
+
".",
|
|
103
|
+
"grey46",
|
|
104
|
+
"Submitted for execution.",
|
|
105
|
+
)
|
|
106
|
+
#: Executing now.
|
|
107
|
+
running = _ReportableStateData(
|
|
108
|
+
3,
|
|
109
|
+
"●",
|
|
110
|
+
"dodger_blue1",
|
|
111
|
+
"Executing now.",
|
|
112
|
+
)
|
|
113
|
+
#: Not attempted due to a failure of an upstream action on which this depends,
|
|
114
|
+
#: or a loop termination condition being satisfied.
|
|
115
|
+
skipped = _ReportableStateData(
|
|
116
|
+
4,
|
|
117
|
+
"s",
|
|
118
|
+
"dark_orange",
|
|
119
|
+
(
|
|
120
|
+
"Not attempted due to a failure of an upstream action on which this depends, "
|
|
121
|
+
"or a loop termination condition being satisfied."
|
|
122
|
+
),
|
|
123
|
+
)
|
|
124
|
+
#: Aborted by the user; downstream actions will be attempted.
|
|
125
|
+
aborted = _ReportableStateData(
|
|
126
|
+
5,
|
|
127
|
+
"A",
|
|
128
|
+
"deep_pink4",
|
|
129
|
+
"Aborted by the user; downstream actions will be attempted.",
|
|
130
|
+
)
|
|
131
|
+
#: Probably exited successfully.
|
|
132
|
+
success = _ReportableStateData(
|
|
133
|
+
6,
|
|
134
|
+
"■",
|
|
135
|
+
"green3",
|
|
136
|
+
"Probably exited successfully.",
|
|
137
|
+
)
|
|
138
|
+
#: Probably failed.
|
|
139
|
+
error = _ReportableStateData(
|
|
140
|
+
7,
|
|
141
|
+
"E",
|
|
142
|
+
"red3",
|
|
143
|
+
"Probably failed.",
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
@classmethod
|
|
147
|
+
def get_non_running_submitted_states(cls) -> frozenset[EARStatus]:
|
|
148
|
+
"""Return the set of all non-running states, excluding those before submission."""
|
|
149
|
+
return frozenset(
|
|
150
|
+
{
|
|
151
|
+
cls.skipped,
|
|
152
|
+
cls.aborted,
|
|
153
|
+
cls.success,
|
|
154
|
+
cls.error,
|
|
155
|
+
}
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class InputSourceType(Enum):
|
|
160
|
+
"""
|
|
161
|
+
The types of input sources.
|
|
162
|
+
"""
|
|
163
|
+
|
|
164
|
+
#: Input source is an import.
|
|
165
|
+
IMPORT = 0
|
|
166
|
+
#: Input source is local.
|
|
167
|
+
LOCAL = 1
|
|
168
|
+
#: Input source is a default.
|
|
169
|
+
DEFAULT = 2
|
|
170
|
+
#: Input source is a task.
|
|
171
|
+
TASK = 3
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class ParallelMode(Enum):
|
|
175
|
+
"""
|
|
176
|
+
Potential parallel modes.
|
|
177
|
+
"""
|
|
178
|
+
|
|
179
|
+
#: Use distributed-memory parallelism (e.g. MPI).
|
|
180
|
+
DISTRIBUTED = 0
|
|
181
|
+
#: Use shared-memory parallelism (e.g. OpenMP).
|
|
182
|
+
SHARED = 1
|
|
183
|
+
#: Use both distributed- and shared-memory parallelism.
|
|
184
|
+
#:
|
|
185
|
+
#: Note
|
|
186
|
+
#: ----
|
|
187
|
+
#: This is not yet implemented in any meaningful way!
|
|
188
|
+
HYBRID = 2
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class ParameterPropagationMode(Enum):
|
|
192
|
+
"""
|
|
193
|
+
How a parameter is propagated.
|
|
194
|
+
"""
|
|
195
|
+
|
|
196
|
+
#: Parameter is propagated implicitly.
|
|
197
|
+
IMPLICIT = 0
|
|
198
|
+
#: Parameter is propagated explicitly.
|
|
199
|
+
EXPLICIT = 1
|
|
200
|
+
#: Parameter is never propagated.
|
|
201
|
+
NEVER = 2
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class TaskSourceType(Enum):
|
|
205
|
+
"""
|
|
206
|
+
The types of task-based input sources.
|
|
207
|
+
"""
|
|
208
|
+
|
|
209
|
+
#: Input source is a task input.
|
|
210
|
+
INPUT = 0
|
|
211
|
+
#: Input source is a task output.
|
|
212
|
+
OUTPUT = 1
|
|
213
|
+
#: Input source is unspecified.
|
|
214
|
+
ANY = 2
|
|
215
|
+
|
|
216
|
+
@classmethod
|
|
217
|
+
def names(cls) -> Sequence[str]:
|
|
218
|
+
"""
|
|
219
|
+
Get the names of the task source types.
|
|
220
|
+
"""
|
|
221
|
+
return cls._member_names_
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Model of an execution environment.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
from hpcflow.sdk.typing import hydrate
|
|
11
|
+
from hpcflow.sdk.core.errors import DuplicateExecutableError
|
|
12
|
+
from hpcflow.sdk.core.json_like import ChildObjectSpec, JSONLike
|
|
13
|
+
from hpcflow.sdk.core.object_list import ExecutablesList
|
|
14
|
+
from hpcflow.sdk.core.utils import check_valid_py_identifier, get_duplicate_items
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from collections.abc import Mapping, Sequence
|
|
18
|
+
from typing import Any, ClassVar
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class NumCores(JSONLike):
|
|
23
|
+
"""
|
|
24
|
+
A range of cores supported by an executable instance.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
start:
|
|
29
|
+
The minimum number of cores supported.
|
|
30
|
+
stop:
|
|
31
|
+
The maximum number of cores supported.
|
|
32
|
+
step: int
|
|
33
|
+
The step in the number of cores supported. Defaults to 1.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
#: The minimum number of cores supported.
|
|
37
|
+
start: int
|
|
38
|
+
#: The maximum number of cores supported.
|
|
39
|
+
stop: int
|
|
40
|
+
#: The step in the number of cores supported. Normally 1.
|
|
41
|
+
step: int = 1
|
|
42
|
+
|
|
43
|
+
def __contains__(self, x: int) -> bool:
|
|
44
|
+
return x in range(self.start, self.stop + 1, self.step)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass
|
|
48
|
+
@hydrate
|
|
49
|
+
class ExecutableInstance(JSONLike):
|
|
50
|
+
"""
|
|
51
|
+
A particular instance of an executable that can support some mode of operation.
|
|
52
|
+
|
|
53
|
+
Parameters
|
|
54
|
+
----------
|
|
55
|
+
parallel_mode:
|
|
56
|
+
What parallel mode is supported by this executable instance.
|
|
57
|
+
num_cores: NumCores | int | dict[str, int]
|
|
58
|
+
The number of cores supported by this executable instance.
|
|
59
|
+
command:
|
|
60
|
+
The actual command to use for this executable instance.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
#: What parallel mode is supported by this executable instance.
|
|
64
|
+
parallel_mode: str | None
|
|
65
|
+
#: The number of cores supported by this executable instance.
|
|
66
|
+
num_cores: NumCores
|
|
67
|
+
#: The actual command to use for this executable instance.
|
|
68
|
+
command: str
|
|
69
|
+
|
|
70
|
+
def __init__(
|
|
71
|
+
self, parallel_mode: str | None, num_cores: NumCores | int | dict, command: str
|
|
72
|
+
):
|
|
73
|
+
self.parallel_mode = parallel_mode
|
|
74
|
+
self.command = command
|
|
75
|
+
if isinstance(num_cores, NumCores):
|
|
76
|
+
self.num_cores = num_cores
|
|
77
|
+
elif isinstance(num_cores, int):
|
|
78
|
+
self.num_cores = NumCores(num_cores, num_cores)
|
|
79
|
+
else:
|
|
80
|
+
self.num_cores = NumCores(**num_cores)
|
|
81
|
+
|
|
82
|
+
@classmethod
|
|
83
|
+
def from_spec(cls, spec: dict[str, Any]) -> ExecutableInstance:
|
|
84
|
+
"""
|
|
85
|
+
Construct an instance from a specification dictionary.
|
|
86
|
+
"""
|
|
87
|
+
return cls(**spec)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class Executable(JSONLike):
|
|
91
|
+
"""
|
|
92
|
+
A program managed by the environment.
|
|
93
|
+
|
|
94
|
+
Parameters
|
|
95
|
+
----------
|
|
96
|
+
label:
|
|
97
|
+
The abstract name of the program.
|
|
98
|
+
instances: list[ExecutableInstance]
|
|
99
|
+
The concrete instances of the application that may be present.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
_child_objects: ClassVar[tuple[ChildObjectSpec, ...]] = (
|
|
103
|
+
ChildObjectSpec(
|
|
104
|
+
name="instances",
|
|
105
|
+
class_name="ExecutableInstance",
|
|
106
|
+
is_multiple=True,
|
|
107
|
+
),
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
def __init__(self, label: str, instances: list[ExecutableInstance]):
|
|
111
|
+
#: The abstract name of the program.
|
|
112
|
+
self.label = check_valid_py_identifier(label)
|
|
113
|
+
#: The concrete instances of the application that may be present.
|
|
114
|
+
self.instances = instances
|
|
115
|
+
|
|
116
|
+
self._executables_list: ExecutablesList | None = None # assigned by parent
|
|
117
|
+
|
|
118
|
+
def __repr__(self):
|
|
119
|
+
return (
|
|
120
|
+
f"{self.__class__.__name__}("
|
|
121
|
+
f"label={self.label}, "
|
|
122
|
+
f"instances={self.instances!r}"
|
|
123
|
+
f")"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
def __eq__(self, other: Any) -> bool:
|
|
127
|
+
return (
|
|
128
|
+
isinstance(other, self.__class__)
|
|
129
|
+
and self.label == other.label
|
|
130
|
+
and self.instances == other.instances
|
|
131
|
+
and (
|
|
132
|
+
(
|
|
133
|
+
self.environment
|
|
134
|
+
and other.environment
|
|
135
|
+
and self.environment.name == other.environment.name
|
|
136
|
+
)
|
|
137
|
+
or (not self.environment and not other.environment)
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
@property
|
|
142
|
+
def environment(self) -> Environment | None:
|
|
143
|
+
"""
|
|
144
|
+
The environment that the executable is going to run in.
|
|
145
|
+
"""
|
|
146
|
+
return None if (el := self._executables_list) is None else el.environment
|
|
147
|
+
|
|
148
|
+
def filter_instances(
|
|
149
|
+
self, parallel_mode: str | None = None, num_cores: int | None = None
|
|
150
|
+
) -> list[ExecutableInstance]:
|
|
151
|
+
"""
|
|
152
|
+
Select the instances of the executable that are compatible with the given
|
|
153
|
+
requirements.
|
|
154
|
+
|
|
155
|
+
Parameters
|
|
156
|
+
----------
|
|
157
|
+
parallel_mode: str
|
|
158
|
+
If given, the parallel mode to require.
|
|
159
|
+
num_cores: int
|
|
160
|
+
If given, the number of cores desired.
|
|
161
|
+
|
|
162
|
+
Returns
|
|
163
|
+
-------
|
|
164
|
+
list[ExecutableInstance]:
|
|
165
|
+
The known executable instances that match the requirements.
|
|
166
|
+
"""
|
|
167
|
+
return [
|
|
168
|
+
inst
|
|
169
|
+
for inst in self.instances
|
|
170
|
+
if (parallel_mode is None or inst.parallel_mode == parallel_mode)
|
|
171
|
+
and (num_cores is None or num_cores in inst.num_cores)
|
|
172
|
+
]
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class Environment(JSONLike):
|
|
176
|
+
"""
|
|
177
|
+
An execution environment that contains a number of executables.
|
|
178
|
+
|
|
179
|
+
Parameters
|
|
180
|
+
----------
|
|
181
|
+
name: str
|
|
182
|
+
The name of the environment.
|
|
183
|
+
setup: list[str]
|
|
184
|
+
Commands to run to enter the environment.
|
|
185
|
+
specifiers: dict[str, str]
|
|
186
|
+
Dictionary of attributes that may be used to supply additional key/value pairs to
|
|
187
|
+
look up an environment by.
|
|
188
|
+
executables: list[Executable]
|
|
189
|
+
List of abstract executables in the environment.
|
|
190
|
+
"""
|
|
191
|
+
|
|
192
|
+
_validation_schema: ClassVar[str] = "environments_spec_schema.yaml"
|
|
193
|
+
_child_objects: ClassVar[tuple[ChildObjectSpec, ...]] = (
|
|
194
|
+
ChildObjectSpec(
|
|
195
|
+
name="executables",
|
|
196
|
+
class_name="ExecutablesList",
|
|
197
|
+
parent_ref="environment",
|
|
198
|
+
),
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
def __init__(
|
|
202
|
+
self,
|
|
203
|
+
name: str,
|
|
204
|
+
setup: Sequence[str] | None = None,
|
|
205
|
+
specifiers: Mapping[str, str] | None = None,
|
|
206
|
+
executables: ExecutablesList | Sequence[Executable] | None = None,
|
|
207
|
+
doc: str = "",
|
|
208
|
+
_hash_value: str | None = None,
|
|
209
|
+
):
|
|
210
|
+
#: The name of the environment.
|
|
211
|
+
self.name = name
|
|
212
|
+
#: Documentation for the environment.
|
|
213
|
+
self.doc = doc
|
|
214
|
+
#: Dictionary of attributes that may be used to supply additional key/value pairs
|
|
215
|
+
#: to look up an environment by.
|
|
216
|
+
self.specifiers: Mapping[str, str] = specifiers or {}
|
|
217
|
+
#: List of abstract executables in the environment.
|
|
218
|
+
self.executables = (
|
|
219
|
+
executables
|
|
220
|
+
if isinstance(executables, ExecutablesList)
|
|
221
|
+
else self._app.ExecutablesList(executables or ())
|
|
222
|
+
)
|
|
223
|
+
self._hash_value = _hash_value
|
|
224
|
+
#: Commands to run to enter the environment.
|
|
225
|
+
self.setup: tuple[str, ...] | None
|
|
226
|
+
if not setup:
|
|
227
|
+
self.setup = None
|
|
228
|
+
elif isinstance(setup, str):
|
|
229
|
+
self.setup = tuple(cmd.strip() for cmd in setup.strip().split("\n"))
|
|
230
|
+
else:
|
|
231
|
+
self.setup = tuple(setup)
|
|
232
|
+
self._set_parent_refs()
|
|
233
|
+
self._validate()
|
|
234
|
+
|
|
235
|
+
def __eq__(self, other: Any) -> bool:
|
|
236
|
+
return (
|
|
237
|
+
isinstance(other, self.__class__)
|
|
238
|
+
and self.setup == other.setup
|
|
239
|
+
and self.executables == other.executables
|
|
240
|
+
and self.specifiers == other.specifiers
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
def __repr__(self):
|
|
244
|
+
return f"{self.__class__.__name__}({self.name!r})"
|
|
245
|
+
|
|
246
|
+
def _validate(self):
|
|
247
|
+
if dup_labels := get_duplicate_items(exe.label for exe in self.executables):
|
|
248
|
+
raise DuplicateExecutableError(dup_labels)
|
|
249
|
+
|
|
250
|
+
@property
|
|
251
|
+
def documentation(self) -> str:
|
|
252
|
+
if self.doc:
|
|
253
|
+
import markupsafe
|
|
254
|
+
|
|
255
|
+
return markupsafe.Markup(self.doc)
|
|
256
|
+
return repr(self)
|