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.
Files changed (275) hide show
  1. hpcflow/__init__.py +2 -11
  2. hpcflow/__pyinstaller/__init__.py +5 -0
  3. hpcflow/__pyinstaller/hook-hpcflow.py +40 -0
  4. hpcflow/_version.py +1 -1
  5. hpcflow/app.py +43 -0
  6. hpcflow/cli.py +2 -462
  7. hpcflow/data/demo_data_manifest/__init__.py +3 -0
  8. hpcflow/data/demo_data_manifest/demo_data_manifest.json +6 -0
  9. hpcflow/data/jinja_templates/test/test_template.txt +8 -0
  10. hpcflow/data/programs/hello_world/README.md +1 -0
  11. hpcflow/data/programs/hello_world/hello_world.c +87 -0
  12. hpcflow/data/programs/hello_world/linux/hello_world +0 -0
  13. hpcflow/data/programs/hello_world/macos/hello_world +0 -0
  14. hpcflow/data/programs/hello_world/win/hello_world.exe +0 -0
  15. hpcflow/data/scripts/__init__.py +1 -0
  16. hpcflow/data/scripts/bad_script.py +2 -0
  17. hpcflow/data/scripts/demo_task_1_generate_t1_infile_1.py +8 -0
  18. hpcflow/data/scripts/demo_task_1_generate_t1_infile_2.py +8 -0
  19. hpcflow/data/scripts/demo_task_1_parse_p3.py +7 -0
  20. hpcflow/data/scripts/do_nothing.py +2 -0
  21. hpcflow/data/scripts/env_specifier_test/input_file_generator_pass_env_spec.py +4 -0
  22. hpcflow/data/scripts/env_specifier_test/main_script_test_pass_env_spec.py +8 -0
  23. hpcflow/data/scripts/env_specifier_test/output_file_parser_pass_env_spec.py +4 -0
  24. hpcflow/data/scripts/env_specifier_test/v1/input_file_generator_basic.py +4 -0
  25. hpcflow/data/scripts/env_specifier_test/v1/main_script_test_direct_in_direct_out.py +7 -0
  26. hpcflow/data/scripts/env_specifier_test/v1/output_file_parser_basic.py +4 -0
  27. hpcflow/data/scripts/env_specifier_test/v2/main_script_test_direct_in_direct_out.py +7 -0
  28. hpcflow/data/scripts/generate_t1_file_01.py +7 -0
  29. hpcflow/data/scripts/import_future_script.py +7 -0
  30. hpcflow/data/scripts/input_file_generator_basic.py +3 -0
  31. hpcflow/data/scripts/input_file_generator_basic_FAIL.py +3 -0
  32. hpcflow/data/scripts/input_file_generator_test_stdout_stderr.py +8 -0
  33. hpcflow/data/scripts/main_script_test_direct_in.py +3 -0
  34. hpcflow/data/scripts/main_script_test_direct_in_direct_out.py +6 -0
  35. hpcflow/data/scripts/main_script_test_direct_in_direct_out_2.py +6 -0
  36. hpcflow/data/scripts/main_script_test_direct_in_direct_out_2_fail_allowed.py +6 -0
  37. hpcflow/data/scripts/main_script_test_direct_in_direct_out_2_fail_allowed_group.py +7 -0
  38. hpcflow/data/scripts/main_script_test_direct_in_direct_out_3.py +6 -0
  39. hpcflow/data/scripts/main_script_test_direct_in_direct_out_all_iters_test.py +15 -0
  40. hpcflow/data/scripts/main_script_test_direct_in_direct_out_env_spec.py +7 -0
  41. hpcflow/data/scripts/main_script_test_direct_in_direct_out_labels.py +8 -0
  42. hpcflow/data/scripts/main_script_test_direct_in_group_direct_out_3.py +6 -0
  43. hpcflow/data/scripts/main_script_test_direct_in_group_one_fail_direct_out_3.py +6 -0
  44. hpcflow/data/scripts/main_script_test_direct_sub_param_in_direct_out.py +6 -0
  45. hpcflow/data/scripts/main_script_test_hdf5_in_obj.py +12 -0
  46. hpcflow/data/scripts/main_script_test_hdf5_in_obj_2.py +12 -0
  47. hpcflow/data/scripts/main_script_test_hdf5_in_obj_group.py +12 -0
  48. hpcflow/data/scripts/main_script_test_hdf5_out_obj.py +11 -0
  49. hpcflow/data/scripts/main_script_test_json_and_direct_in_json_out.py +14 -0
  50. hpcflow/data/scripts/main_script_test_json_in_json_and_direct_out.py +17 -0
  51. hpcflow/data/scripts/main_script_test_json_in_json_out.py +14 -0
  52. hpcflow/data/scripts/main_script_test_json_in_json_out_labels.py +16 -0
  53. hpcflow/data/scripts/main_script_test_json_in_obj.py +12 -0
  54. hpcflow/data/scripts/main_script_test_json_out_FAIL.py +3 -0
  55. hpcflow/data/scripts/main_script_test_json_out_obj.py +10 -0
  56. hpcflow/data/scripts/main_script_test_json_sub_param_in_json_out_labels.py +16 -0
  57. hpcflow/data/scripts/main_script_test_shell_env_vars.py +12 -0
  58. hpcflow/data/scripts/main_script_test_std_out_std_err.py +6 -0
  59. hpcflow/data/scripts/output_file_parser_basic.py +3 -0
  60. hpcflow/data/scripts/output_file_parser_basic_FAIL.py +7 -0
  61. hpcflow/data/scripts/output_file_parser_test_stdout_stderr.py +8 -0
  62. hpcflow/data/scripts/parse_t1_file_01.py +4 -0
  63. hpcflow/data/scripts/script_exit_test.py +5 -0
  64. hpcflow/data/template_components/__init__.py +1 -0
  65. hpcflow/data/template_components/command_files.yaml +26 -0
  66. hpcflow/data/template_components/environments.yaml +13 -0
  67. hpcflow/data/template_components/parameters.yaml +14 -0
  68. hpcflow/data/template_components/task_schemas.yaml +139 -0
  69. hpcflow/data/workflows/workflow_1.yaml +5 -0
  70. hpcflow/examples.ipynb +1037 -0
  71. hpcflow/sdk/__init__.py +149 -0
  72. hpcflow/sdk/app.py +4266 -0
  73. hpcflow/sdk/cli.py +1479 -0
  74. hpcflow/sdk/cli_common.py +385 -0
  75. hpcflow/sdk/config/__init__.py +5 -0
  76. hpcflow/sdk/config/callbacks.py +246 -0
  77. hpcflow/sdk/config/cli.py +388 -0
  78. hpcflow/sdk/config/config.py +1410 -0
  79. hpcflow/sdk/config/config_file.py +501 -0
  80. hpcflow/sdk/config/errors.py +272 -0
  81. hpcflow/sdk/config/types.py +150 -0
  82. hpcflow/sdk/core/__init__.py +38 -0
  83. hpcflow/sdk/core/actions.py +3857 -0
  84. hpcflow/sdk/core/app_aware.py +25 -0
  85. hpcflow/sdk/core/cache.py +224 -0
  86. hpcflow/sdk/core/command_files.py +814 -0
  87. hpcflow/sdk/core/commands.py +424 -0
  88. hpcflow/sdk/core/element.py +2071 -0
  89. hpcflow/sdk/core/enums.py +221 -0
  90. hpcflow/sdk/core/environment.py +256 -0
  91. hpcflow/sdk/core/errors.py +1043 -0
  92. hpcflow/sdk/core/execute.py +207 -0
  93. hpcflow/sdk/core/json_like.py +809 -0
  94. hpcflow/sdk/core/loop.py +1320 -0
  95. hpcflow/sdk/core/loop_cache.py +282 -0
  96. hpcflow/sdk/core/object_list.py +933 -0
  97. hpcflow/sdk/core/parameters.py +3371 -0
  98. hpcflow/sdk/core/rule.py +196 -0
  99. hpcflow/sdk/core/run_dir_files.py +57 -0
  100. hpcflow/sdk/core/skip_reason.py +7 -0
  101. hpcflow/sdk/core/task.py +3792 -0
  102. hpcflow/sdk/core/task_schema.py +993 -0
  103. hpcflow/sdk/core/test_utils.py +538 -0
  104. hpcflow/sdk/core/types.py +447 -0
  105. hpcflow/sdk/core/utils.py +1207 -0
  106. hpcflow/sdk/core/validation.py +87 -0
  107. hpcflow/sdk/core/values.py +477 -0
  108. hpcflow/sdk/core/workflow.py +4820 -0
  109. hpcflow/sdk/core/zarr_io.py +206 -0
  110. hpcflow/sdk/data/__init__.py +13 -0
  111. hpcflow/sdk/data/config_file_schema.yaml +34 -0
  112. hpcflow/sdk/data/config_schema.yaml +260 -0
  113. hpcflow/sdk/data/environments_spec_schema.yaml +21 -0
  114. hpcflow/sdk/data/files_spec_schema.yaml +5 -0
  115. hpcflow/sdk/data/parameters_spec_schema.yaml +7 -0
  116. hpcflow/sdk/data/task_schema_spec_schema.yaml +3 -0
  117. hpcflow/sdk/data/workflow_spec_schema.yaml +22 -0
  118. hpcflow/sdk/demo/__init__.py +3 -0
  119. hpcflow/sdk/demo/cli.py +242 -0
  120. hpcflow/sdk/helper/__init__.py +3 -0
  121. hpcflow/sdk/helper/cli.py +137 -0
  122. hpcflow/sdk/helper/helper.py +300 -0
  123. hpcflow/sdk/helper/watcher.py +192 -0
  124. hpcflow/sdk/log.py +288 -0
  125. hpcflow/sdk/persistence/__init__.py +18 -0
  126. hpcflow/sdk/persistence/base.py +2817 -0
  127. hpcflow/sdk/persistence/defaults.py +6 -0
  128. hpcflow/sdk/persistence/discovery.py +39 -0
  129. hpcflow/sdk/persistence/json.py +954 -0
  130. hpcflow/sdk/persistence/pending.py +948 -0
  131. hpcflow/sdk/persistence/store_resource.py +203 -0
  132. hpcflow/sdk/persistence/types.py +309 -0
  133. hpcflow/sdk/persistence/utils.py +73 -0
  134. hpcflow/sdk/persistence/zarr.py +2388 -0
  135. hpcflow/sdk/runtime.py +320 -0
  136. hpcflow/sdk/submission/__init__.py +3 -0
  137. hpcflow/sdk/submission/enums.py +70 -0
  138. hpcflow/sdk/submission/jobscript.py +2379 -0
  139. hpcflow/sdk/submission/schedulers/__init__.py +281 -0
  140. hpcflow/sdk/submission/schedulers/direct.py +233 -0
  141. hpcflow/sdk/submission/schedulers/sge.py +376 -0
  142. hpcflow/sdk/submission/schedulers/slurm.py +598 -0
  143. hpcflow/sdk/submission/schedulers/utils.py +25 -0
  144. hpcflow/sdk/submission/shells/__init__.py +52 -0
  145. hpcflow/sdk/submission/shells/base.py +229 -0
  146. hpcflow/sdk/submission/shells/bash.py +504 -0
  147. hpcflow/sdk/submission/shells/os_version.py +115 -0
  148. hpcflow/sdk/submission/shells/powershell.py +352 -0
  149. hpcflow/sdk/submission/submission.py +1402 -0
  150. hpcflow/sdk/submission/types.py +140 -0
  151. hpcflow/sdk/typing.py +194 -0
  152. hpcflow/sdk/utils/arrays.py +69 -0
  153. hpcflow/sdk/utils/deferred_file.py +55 -0
  154. hpcflow/sdk/utils/hashing.py +16 -0
  155. hpcflow/sdk/utils/patches.py +31 -0
  156. hpcflow/sdk/utils/strings.py +69 -0
  157. hpcflow/tests/api/test_api.py +32 -0
  158. hpcflow/tests/conftest.py +123 -0
  159. hpcflow/tests/data/__init__.py +0 -0
  160. hpcflow/tests/data/benchmark_N_elements.yaml +6 -0
  161. hpcflow/tests/data/benchmark_script_runner.yaml +26 -0
  162. hpcflow/tests/data/multi_path_sequences.yaml +29 -0
  163. hpcflow/tests/data/workflow_1.json +10 -0
  164. hpcflow/tests/data/workflow_1.yaml +5 -0
  165. hpcflow/tests/data/workflow_1_slurm.yaml +8 -0
  166. hpcflow/tests/data/workflow_1_wsl.yaml +8 -0
  167. hpcflow/tests/data/workflow_test_run_abort.yaml +42 -0
  168. hpcflow/tests/jinja_templates/test_jinja_templates.py +161 -0
  169. hpcflow/tests/programs/test_programs.py +180 -0
  170. hpcflow/tests/schedulers/direct_linux/test_direct_linux_submission.py +12 -0
  171. hpcflow/tests/schedulers/sge/test_sge_submission.py +36 -0
  172. hpcflow/tests/schedulers/slurm/test_slurm_submission.py +14 -0
  173. hpcflow/tests/scripts/test_input_file_generators.py +282 -0
  174. hpcflow/tests/scripts/test_main_scripts.py +1361 -0
  175. hpcflow/tests/scripts/test_non_snippet_script.py +46 -0
  176. hpcflow/tests/scripts/test_ouput_file_parsers.py +353 -0
  177. hpcflow/tests/shells/wsl/test_wsl_submission.py +14 -0
  178. hpcflow/tests/unit/test_action.py +1066 -0
  179. hpcflow/tests/unit/test_action_rule.py +24 -0
  180. hpcflow/tests/unit/test_app.py +132 -0
  181. hpcflow/tests/unit/test_cache.py +46 -0
  182. hpcflow/tests/unit/test_cli.py +172 -0
  183. hpcflow/tests/unit/test_command.py +377 -0
  184. hpcflow/tests/unit/test_config.py +195 -0
  185. hpcflow/tests/unit/test_config_file.py +162 -0
  186. hpcflow/tests/unit/test_element.py +666 -0
  187. hpcflow/tests/unit/test_element_iteration.py +88 -0
  188. hpcflow/tests/unit/test_element_set.py +158 -0
  189. hpcflow/tests/unit/test_group.py +115 -0
  190. hpcflow/tests/unit/test_input_source.py +1479 -0
  191. hpcflow/tests/unit/test_input_value.py +398 -0
  192. hpcflow/tests/unit/test_jobscript_unit.py +757 -0
  193. hpcflow/tests/unit/test_json_like.py +1247 -0
  194. hpcflow/tests/unit/test_loop.py +2674 -0
  195. hpcflow/tests/unit/test_meta_task.py +325 -0
  196. hpcflow/tests/unit/test_multi_path_sequences.py +259 -0
  197. hpcflow/tests/unit/test_object_list.py +116 -0
  198. hpcflow/tests/unit/test_parameter.py +243 -0
  199. hpcflow/tests/unit/test_persistence.py +664 -0
  200. hpcflow/tests/unit/test_resources.py +243 -0
  201. hpcflow/tests/unit/test_run.py +286 -0
  202. hpcflow/tests/unit/test_run_directories.py +29 -0
  203. hpcflow/tests/unit/test_runtime.py +9 -0
  204. hpcflow/tests/unit/test_schema_input.py +372 -0
  205. hpcflow/tests/unit/test_shell.py +129 -0
  206. hpcflow/tests/unit/test_slurm.py +39 -0
  207. hpcflow/tests/unit/test_submission.py +502 -0
  208. hpcflow/tests/unit/test_task.py +2560 -0
  209. hpcflow/tests/unit/test_task_schema.py +182 -0
  210. hpcflow/tests/unit/test_utils.py +616 -0
  211. hpcflow/tests/unit/test_value_sequence.py +549 -0
  212. hpcflow/tests/unit/test_values.py +91 -0
  213. hpcflow/tests/unit/test_workflow.py +827 -0
  214. hpcflow/tests/unit/test_workflow_template.py +186 -0
  215. hpcflow/tests/unit/utils/test_arrays.py +40 -0
  216. hpcflow/tests/unit/utils/test_deferred_file_writer.py +34 -0
  217. hpcflow/tests/unit/utils/test_hashing.py +65 -0
  218. hpcflow/tests/unit/utils/test_patches.py +5 -0
  219. hpcflow/tests/unit/utils/test_redirect_std.py +50 -0
  220. hpcflow/tests/unit/utils/test_strings.py +97 -0
  221. hpcflow/tests/workflows/__init__.py +0 -0
  222. hpcflow/tests/workflows/test_directory_structure.py +31 -0
  223. hpcflow/tests/workflows/test_jobscript.py +355 -0
  224. hpcflow/tests/workflows/test_run_status.py +198 -0
  225. hpcflow/tests/workflows/test_skip_downstream.py +696 -0
  226. hpcflow/tests/workflows/test_submission.py +140 -0
  227. hpcflow/tests/workflows/test_workflows.py +564 -0
  228. hpcflow/tests/workflows/test_zip.py +18 -0
  229. hpcflow/viz_demo.ipynb +6794 -0
  230. hpcflow-0.2.0a271.dist-info/LICENSE +375 -0
  231. hpcflow-0.2.0a271.dist-info/METADATA +65 -0
  232. hpcflow-0.2.0a271.dist-info/RECORD +237 -0
  233. {hpcflow-0.1.9.dist-info → hpcflow-0.2.0a271.dist-info}/WHEEL +4 -5
  234. hpcflow-0.2.0a271.dist-info/entry_points.txt +6 -0
  235. hpcflow/api.py +0 -458
  236. hpcflow/archive/archive.py +0 -308
  237. hpcflow/archive/cloud/cloud.py +0 -47
  238. hpcflow/archive/cloud/errors.py +0 -9
  239. hpcflow/archive/cloud/providers/dropbox.py +0 -432
  240. hpcflow/archive/errors.py +0 -5
  241. hpcflow/base_db.py +0 -4
  242. hpcflow/config.py +0 -232
  243. hpcflow/copytree.py +0 -66
  244. hpcflow/data/examples/_config.yml +0 -14
  245. hpcflow/data/examples/damask/demo/1.run.yml +0 -4
  246. hpcflow/data/examples/damask/demo/2.process.yml +0 -29
  247. hpcflow/data/examples/damask/demo/geom.geom +0 -2052
  248. hpcflow/data/examples/damask/demo/load.load +0 -1
  249. hpcflow/data/examples/damask/demo/material.config +0 -185
  250. hpcflow/data/examples/damask/inputs/geom.geom +0 -2052
  251. hpcflow/data/examples/damask/inputs/load.load +0 -1
  252. hpcflow/data/examples/damask/inputs/material.config +0 -185
  253. hpcflow/data/examples/damask/profiles/_variable_lookup.yml +0 -21
  254. hpcflow/data/examples/damask/profiles/damask.yml +0 -4
  255. hpcflow/data/examples/damask/profiles/damask_process.yml +0 -8
  256. hpcflow/data/examples/damask/profiles/damask_run.yml +0 -5
  257. hpcflow/data/examples/damask/profiles/default.yml +0 -6
  258. hpcflow/data/examples/thinking.yml +0 -177
  259. hpcflow/errors.py +0 -2
  260. hpcflow/init_db.py +0 -37
  261. hpcflow/models.py +0 -2549
  262. hpcflow/nesting.py +0 -9
  263. hpcflow/profiles.py +0 -455
  264. hpcflow/project.py +0 -81
  265. hpcflow/scheduler.py +0 -323
  266. hpcflow/utils.py +0 -103
  267. hpcflow/validation.py +0 -167
  268. hpcflow/variables.py +0 -544
  269. hpcflow-0.1.9.dist-info/METADATA +0 -168
  270. hpcflow-0.1.9.dist-info/RECORD +0 -45
  271. hpcflow-0.1.9.dist-info/entry_points.txt +0 -8
  272. hpcflow-0.1.9.dist-info/top_level.txt +0 -1
  273. /hpcflow/{archive → data/jinja_templates}/__init__.py +0 -0
  274. /hpcflow/{archive/cloud → data/programs}/__init__.py +0 -0
  275. /hpcflow/{archive/cloud/providers → data/workflows}/__init__.py +0 -0
@@ -0,0 +1,196 @@
1
+ """
2
+ Rules apply conditions to workflow elements or loops.
3
+ """
4
+
5
+ from __future__ import annotations
6
+ from typing import TYPE_CHECKING
7
+
8
+ from valida.conditions import ConditionLike # type: ignore
9
+ from valida import Rule as ValidaRule # type: ignore
10
+
11
+ from hpcflow.sdk.core.errors import ContainerKeyError, UnsetParameterDataError
12
+ from hpcflow.sdk.core.json_like import JSONLike
13
+ from hpcflow.sdk.core.utils import get_in_container
14
+ from hpcflow.sdk.log import TimeIt
15
+
16
+ if TYPE_CHECKING:
17
+ from typing import Any
18
+ from typing_extensions import TypeIs
19
+ from .actions import Action, ElementActionRun
20
+ from .element import ElementIteration
21
+
22
+
23
+ class Rule(JSONLike):
24
+ """
25
+ Class to represent a testable condition on an element iteration or run.
26
+
27
+ Exactly one of ``check_exists``, ``check_missing`` and ``condition`` must be provided.
28
+
29
+ Parameters
30
+ ----------
31
+ check_exists: str
32
+ If set, check this attribute exists.
33
+ check_missing: str
34
+ If set, check this attribute does *not* exist.
35
+ path: str
36
+ Where to look up the attribute to check.
37
+ If not specified, determined by context.
38
+ condition: ConditionLike
39
+ A general condition to check (or kwargs used to generate one).
40
+ cast: str
41
+ If set, a cast to apply prior to running the general check.
42
+ doc: str
43
+ Optional descriptive text.
44
+ default: bool
45
+ Optional default value to return when testing the rule if the path is not valid.
46
+ """
47
+
48
+ def __init__(
49
+ self,
50
+ check_exists: str | None = None,
51
+ check_missing: str | None = None,
52
+ path: str | None = None,
53
+ condition: dict[str, Any] | ConditionLike | None = None,
54
+ cast: str | None = None,
55
+ doc: str | None = None,
56
+ default: bool | None = None,
57
+ ):
58
+ if sum(arg is not None for arg in (check_exists, check_missing, condition)) != 1:
59
+ raise ValueError(
60
+ "Specify either one of `check_exists`, `check_missing` or a `condition` "
61
+ "(and optional `path`)"
62
+ )
63
+
64
+ if not isinstance(condition, dict):
65
+ #: A general condition for this rule to check.
66
+ self.condition = condition
67
+ else:
68
+ self.condition = ConditionLike.from_json_like(condition)
69
+
70
+ #: If set, this rule checks this attribute exists.
71
+ self.check_exists = check_exists
72
+ #: If set, this rule checks this attribute does *not* exist.
73
+ self.check_missing = check_missing
74
+ #: Where to look up the attribute to check (if not determined by context).
75
+ self.path = path
76
+ #: If set, a cast to apply prior to running the general check.
77
+ self.cast = cast
78
+ #: Optional descriptive text.
79
+ self.doc = doc
80
+ #: A default value to return from testing the rule if the path is not valid.
81
+ self.default = default
82
+
83
+ def __repr__(self) -> str:
84
+ out = f"{self.__class__.__name__}("
85
+ if self.check_exists:
86
+ out += f"check_exists={self.check_exists!r}"
87
+ elif self.check_missing:
88
+ out += f"check_missing={self.check_missing!r}"
89
+ else:
90
+ out += f"condition={self.condition!r}"
91
+ if self.path:
92
+ out += f", path={self.path!r}"
93
+ if self.cast:
94
+ out += f", cast={self.cast!r}"
95
+ if self.default is not None:
96
+ out += f", default={self.default!r}"
97
+
98
+ out += ")"
99
+ return out
100
+
101
+ def __eq__(self, other) -> bool:
102
+ if not isinstance(other, self.__class__):
103
+ return False
104
+ return (
105
+ self.check_exists == other.check_exists
106
+ and self.check_missing == other.check_missing
107
+ and self.path == other.path
108
+ and self.condition == other.condition
109
+ and self.cast == other.cast
110
+ and self.doc == other.doc
111
+ and self.default == other.default
112
+ )
113
+
114
+ @classmethod
115
+ def __is_ElementIteration(cls, value) -> TypeIs[ElementIteration]:
116
+ return isinstance(value, cls._app.ElementIteration)
117
+
118
+ @TimeIt.decorator
119
+ def test(
120
+ self,
121
+ element_like: ElementIteration | ElementActionRun,
122
+ action: Action | None = None,
123
+ ) -> bool:
124
+ """Test if the rule evaluates to true or false for a given run, or element
125
+ iteration and action combination."""
126
+
127
+ task = element_like.task
128
+ schema_data_idx = element_like.data_idx
129
+
130
+ if check := self.check_exists or self.check_missing:
131
+ if len(check.split(".")) > 2:
132
+ # sub-parameter, so need to try to retrieve parameter data
133
+ try:
134
+ task._get_merged_parameter_data(
135
+ schema_data_idx, raise_on_missing=True
136
+ )
137
+ return bool(self.check_exists)
138
+ except ValueError:
139
+ return not self.check_exists
140
+ else:
141
+ if self.check_exists:
142
+ return self.check_exists in schema_data_idx
143
+ elif self.check_missing:
144
+ return self.check_missing not in schema_data_idx
145
+ else:
146
+ if self.path and self.path.startswith("resources."):
147
+ if self.__is_ElementIteration(element_like):
148
+ assert action is not None
149
+ elem_res = element_like.get_resources(
150
+ action=action, set_defaults=True
151
+ )
152
+ else:
153
+ elem_res = element_like.get_resources()
154
+
155
+ res_path = self.path.split(".")[1:]
156
+ try:
157
+ element_dat = get_in_container(
158
+ cont=elem_res, path=res_path, cast_indices=True
159
+ )
160
+ except ContainerKeyError:
161
+ if self.default is not None:
162
+ return bool(self.default)
163
+ else:
164
+ raise
165
+ else:
166
+ try:
167
+ element_dat = element_like.get(
168
+ self.path,
169
+ raise_on_missing=True,
170
+ raise_on_unset=True,
171
+ )
172
+ except (ValueError, IndexError, UnsetParameterDataError):
173
+ if self.default is not None:
174
+ return bool(self.default)
175
+ else:
176
+ raise
177
+ # test the rule:
178
+ return self._valida_check(element_dat)
179
+
180
+ # Something bizarre was specified. Don't match it!
181
+ return False
182
+
183
+ def _valida_check(self, value: Any) -> bool:
184
+ """
185
+ Check this rule against the specific object, under the assumption that we need
186
+ to use valida for the check. Does not do path tracing to select the object to
187
+ pass; that is the caller's responsibility.
188
+ """
189
+ # note: Valida can't `rule.test` scalars yet, so wrap it in a list and set
190
+ # path to first element (see: https://github.com/hpcflow/valida/issues/9):
191
+ rule = ValidaRule(
192
+ path=[0],
193
+ condition=self.condition,
194
+ cast=self.cast,
195
+ )
196
+ return rule.test([value]).is_valid
@@ -0,0 +1,57 @@
1
+ """
2
+ Model of files in the run directory.
3
+ """
4
+
5
+ from __future__ import annotations
6
+ from typing import Any, TYPE_CHECKING
7
+ from hpcflow.sdk.core.app_aware import AppAware
8
+ from hpcflow.sdk.core.utils import JSONLikeDirSnapShot
9
+
10
+ if TYPE_CHECKING:
11
+ from ..submission.shells.base import Shell
12
+ from .types import BlockActionKey
13
+
14
+
15
+ class RunDirAppFiles(AppAware):
16
+ """A class to encapsulate the naming/recognition of app-created files within run
17
+ directories."""
18
+
19
+ @staticmethod
20
+ def get_run_file_prefix(block_act_key: BlockActionKey) -> str:
21
+ """
22
+ Get the common prefix for files associated with a run.
23
+ """
24
+ return f"js_{block_act_key[0]}_block_{block_act_key[1]}_act_{block_act_key[2]}"
25
+
26
+ @classmethod
27
+ def get_commands_file_name(cls, block_act_key: BlockActionKey, shell: Shell) -> str:
28
+ """
29
+ Get the name of the file containing commands.
30
+ """
31
+ return cls.get_run_file_prefix(block_act_key) + shell.JS_EXT
32
+
33
+ @classmethod
34
+ def get_run_param_dump_file_prefix(cls, block_act_key: BlockActionKey) -> str:
35
+ """Get the prefix to a file in the run directory that the app will dump parameter
36
+ data to."""
37
+ return cls.get_run_file_prefix(block_act_key) + "_inputs"
38
+
39
+ @classmethod
40
+ def get_run_param_load_file_prefix(cls, block_act_key: BlockActionKey) -> str:
41
+ """Get the prefix to a file in the run directory that the app will load parameter
42
+ data from."""
43
+ return cls.get_run_file_prefix(block_act_key) + "_outputs"
44
+
45
+ @classmethod
46
+ def take_snapshot(cls, root_path=None) -> dict[str, Any]:
47
+ """
48
+ Take a :py:class:`JSONLikeDirSnapShot`.
49
+
50
+ This includes command files that are invoked by jobscripts, the app log file, and
51
+ the app standard out/error file.
52
+ """
53
+ snapshot = JSONLikeDirSnapShot()
54
+ snapshot.take(root_path or ".")
55
+ ss_js = snapshot.to_json_like(use_strings=True)
56
+ ss_js.pop("root_path") # always the current working directory of the run
57
+ return ss_js
@@ -0,0 +1,7 @@
1
+ import enum
2
+
3
+
4
+ class SkipReason(enum.Enum):
5
+ NOT_SKIPPED = 0
6
+ UPSTREAM_FAILURE = 1
7
+ LOOP_TERMINATION = 2