hpcflow-new2 0.2.0a189__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.
Files changed (176) hide show
  1. hpcflow/__pyinstaller/hook-hpcflow.py +9 -6
  2. hpcflow/_version.py +1 -1
  3. hpcflow/app.py +1 -0
  4. hpcflow/data/scripts/bad_script.py +2 -0
  5. hpcflow/data/scripts/do_nothing.py +2 -0
  6. hpcflow/data/scripts/env_specifier_test/input_file_generator_pass_env_spec.py +4 -0
  7. hpcflow/data/scripts/env_specifier_test/main_script_test_pass_env_spec.py +8 -0
  8. hpcflow/data/scripts/env_specifier_test/output_file_parser_pass_env_spec.py +4 -0
  9. hpcflow/data/scripts/env_specifier_test/v1/input_file_generator_basic.py +4 -0
  10. hpcflow/data/scripts/env_specifier_test/v1/main_script_test_direct_in_direct_out.py +7 -0
  11. hpcflow/data/scripts/env_specifier_test/v1/output_file_parser_basic.py +4 -0
  12. hpcflow/data/scripts/env_specifier_test/v2/main_script_test_direct_in_direct_out.py +7 -0
  13. hpcflow/data/scripts/input_file_generator_basic.py +3 -0
  14. hpcflow/data/scripts/input_file_generator_basic_FAIL.py +3 -0
  15. hpcflow/data/scripts/input_file_generator_test_stdout_stderr.py +8 -0
  16. hpcflow/data/scripts/main_script_test_direct_in.py +3 -0
  17. hpcflow/data/scripts/main_script_test_direct_in_direct_out_2.py +6 -0
  18. hpcflow/data/scripts/main_script_test_direct_in_direct_out_2_fail_allowed.py +6 -0
  19. hpcflow/data/scripts/main_script_test_direct_in_direct_out_2_fail_allowed_group.py +7 -0
  20. hpcflow/data/scripts/main_script_test_direct_in_direct_out_3.py +6 -0
  21. hpcflow/data/scripts/main_script_test_direct_in_group_direct_out_3.py +6 -0
  22. hpcflow/data/scripts/main_script_test_direct_in_group_one_fail_direct_out_3.py +6 -0
  23. hpcflow/data/scripts/main_script_test_hdf5_in_obj.py +1 -1
  24. hpcflow/data/scripts/main_script_test_hdf5_in_obj_2.py +12 -0
  25. hpcflow/data/scripts/main_script_test_hdf5_out_obj.py +1 -1
  26. hpcflow/data/scripts/main_script_test_json_out_FAIL.py +3 -0
  27. hpcflow/data/scripts/main_script_test_shell_env_vars.py +12 -0
  28. hpcflow/data/scripts/main_script_test_std_out_std_err.py +6 -0
  29. hpcflow/data/scripts/output_file_parser_basic.py +3 -0
  30. hpcflow/data/scripts/output_file_parser_basic_FAIL.py +7 -0
  31. hpcflow/data/scripts/output_file_parser_test_stdout_stderr.py +8 -0
  32. hpcflow/data/scripts/script_exit_test.py +5 -0
  33. hpcflow/data/template_components/environments.yaml +1 -1
  34. hpcflow/sdk/__init__.py +26 -15
  35. hpcflow/sdk/app.py +2192 -768
  36. hpcflow/sdk/cli.py +506 -296
  37. hpcflow/sdk/cli_common.py +105 -7
  38. hpcflow/sdk/config/__init__.py +1 -1
  39. hpcflow/sdk/config/callbacks.py +115 -43
  40. hpcflow/sdk/config/cli.py +126 -103
  41. hpcflow/sdk/config/config.py +674 -318
  42. hpcflow/sdk/config/config_file.py +131 -95
  43. hpcflow/sdk/config/errors.py +125 -84
  44. hpcflow/sdk/config/types.py +148 -0
  45. hpcflow/sdk/core/__init__.py +25 -1
  46. hpcflow/sdk/core/actions.py +1771 -1059
  47. hpcflow/sdk/core/app_aware.py +24 -0
  48. hpcflow/sdk/core/cache.py +139 -79
  49. hpcflow/sdk/core/command_files.py +263 -287
  50. hpcflow/sdk/core/commands.py +145 -112
  51. hpcflow/sdk/core/element.py +828 -535
  52. hpcflow/sdk/core/enums.py +192 -0
  53. hpcflow/sdk/core/environment.py +74 -93
  54. hpcflow/sdk/core/errors.py +455 -52
  55. hpcflow/sdk/core/execute.py +207 -0
  56. hpcflow/sdk/core/json_like.py +540 -272
  57. hpcflow/sdk/core/loop.py +751 -347
  58. hpcflow/sdk/core/loop_cache.py +164 -47
  59. hpcflow/sdk/core/object_list.py +370 -207
  60. hpcflow/sdk/core/parameters.py +1100 -627
  61. hpcflow/sdk/core/rule.py +59 -41
  62. hpcflow/sdk/core/run_dir_files.py +21 -37
  63. hpcflow/sdk/core/skip_reason.py +7 -0
  64. hpcflow/sdk/core/task.py +1649 -1339
  65. hpcflow/sdk/core/task_schema.py +308 -196
  66. hpcflow/sdk/core/test_utils.py +191 -114
  67. hpcflow/sdk/core/types.py +440 -0
  68. hpcflow/sdk/core/utils.py +485 -309
  69. hpcflow/sdk/core/validation.py +82 -9
  70. hpcflow/sdk/core/workflow.py +2544 -1178
  71. hpcflow/sdk/core/zarr_io.py +98 -137
  72. hpcflow/sdk/data/workflow_spec_schema.yaml +2 -0
  73. hpcflow/sdk/demo/cli.py +53 -33
  74. hpcflow/sdk/helper/cli.py +18 -15
  75. hpcflow/sdk/helper/helper.py +75 -63
  76. hpcflow/sdk/helper/watcher.py +61 -28
  77. hpcflow/sdk/log.py +122 -71
  78. hpcflow/sdk/persistence/__init__.py +8 -31
  79. hpcflow/sdk/persistence/base.py +1360 -606
  80. hpcflow/sdk/persistence/defaults.py +6 -0
  81. hpcflow/sdk/persistence/discovery.py +38 -0
  82. hpcflow/sdk/persistence/json.py +568 -188
  83. hpcflow/sdk/persistence/pending.py +382 -179
  84. hpcflow/sdk/persistence/store_resource.py +39 -23
  85. hpcflow/sdk/persistence/types.py +318 -0
  86. hpcflow/sdk/persistence/utils.py +14 -11
  87. hpcflow/sdk/persistence/zarr.py +1337 -433
  88. hpcflow/sdk/runtime.py +44 -41
  89. hpcflow/sdk/submission/{jobscript_info.py → enums.py} +39 -12
  90. hpcflow/sdk/submission/jobscript.py +1651 -692
  91. hpcflow/sdk/submission/schedulers/__init__.py +167 -39
  92. hpcflow/sdk/submission/schedulers/direct.py +121 -81
  93. hpcflow/sdk/submission/schedulers/sge.py +170 -129
  94. hpcflow/sdk/submission/schedulers/slurm.py +291 -268
  95. hpcflow/sdk/submission/schedulers/utils.py +12 -2
  96. hpcflow/sdk/submission/shells/__init__.py +14 -15
  97. hpcflow/sdk/submission/shells/base.py +150 -29
  98. hpcflow/sdk/submission/shells/bash.py +283 -173
  99. hpcflow/sdk/submission/shells/os_version.py +31 -30
  100. hpcflow/sdk/submission/shells/powershell.py +228 -170
  101. hpcflow/sdk/submission/submission.py +1014 -335
  102. hpcflow/sdk/submission/types.py +140 -0
  103. hpcflow/sdk/typing.py +182 -12
  104. hpcflow/sdk/utils/arrays.py +71 -0
  105. hpcflow/sdk/utils/deferred_file.py +55 -0
  106. hpcflow/sdk/utils/hashing.py +16 -0
  107. hpcflow/sdk/utils/patches.py +12 -0
  108. hpcflow/sdk/utils/strings.py +33 -0
  109. hpcflow/tests/api/test_api.py +32 -0
  110. hpcflow/tests/conftest.py +27 -6
  111. hpcflow/tests/data/multi_path_sequences.yaml +29 -0
  112. hpcflow/tests/data/workflow_test_run_abort.yaml +34 -35
  113. hpcflow/tests/schedulers/sge/test_sge_submission.py +36 -0
  114. hpcflow/tests/schedulers/slurm/test_slurm_submission.py +5 -2
  115. hpcflow/tests/scripts/test_input_file_generators.py +282 -0
  116. hpcflow/tests/scripts/test_main_scripts.py +866 -85
  117. hpcflow/tests/scripts/test_non_snippet_script.py +46 -0
  118. hpcflow/tests/scripts/test_ouput_file_parsers.py +353 -0
  119. hpcflow/tests/shells/wsl/test_wsl_submission.py +12 -4
  120. hpcflow/tests/unit/test_action.py +262 -75
  121. hpcflow/tests/unit/test_action_rule.py +9 -4
  122. hpcflow/tests/unit/test_app.py +33 -6
  123. hpcflow/tests/unit/test_cache.py +46 -0
  124. hpcflow/tests/unit/test_cli.py +134 -1
  125. hpcflow/tests/unit/test_command.py +71 -54
  126. hpcflow/tests/unit/test_config.py +142 -16
  127. hpcflow/tests/unit/test_config_file.py +21 -18
  128. hpcflow/tests/unit/test_element.py +58 -62
  129. hpcflow/tests/unit/test_element_iteration.py +50 -1
  130. hpcflow/tests/unit/test_element_set.py +29 -19
  131. hpcflow/tests/unit/test_group.py +4 -2
  132. hpcflow/tests/unit/test_input_source.py +116 -93
  133. hpcflow/tests/unit/test_input_value.py +29 -24
  134. hpcflow/tests/unit/test_jobscript_unit.py +757 -0
  135. hpcflow/tests/unit/test_json_like.py +44 -35
  136. hpcflow/tests/unit/test_loop.py +1396 -84
  137. hpcflow/tests/unit/test_meta_task.py +325 -0
  138. hpcflow/tests/unit/test_multi_path_sequences.py +229 -0
  139. hpcflow/tests/unit/test_object_list.py +17 -12
  140. hpcflow/tests/unit/test_parameter.py +29 -7
  141. hpcflow/tests/unit/test_persistence.py +237 -42
  142. hpcflow/tests/unit/test_resources.py +20 -18
  143. hpcflow/tests/unit/test_run.py +117 -6
  144. hpcflow/tests/unit/test_run_directories.py +29 -0
  145. hpcflow/tests/unit/test_runtime.py +2 -1
  146. hpcflow/tests/unit/test_schema_input.py +23 -15
  147. hpcflow/tests/unit/test_shell.py +23 -2
  148. hpcflow/tests/unit/test_slurm.py +8 -7
  149. hpcflow/tests/unit/test_submission.py +38 -89
  150. hpcflow/tests/unit/test_task.py +352 -247
  151. hpcflow/tests/unit/test_task_schema.py +33 -20
  152. hpcflow/tests/unit/test_utils.py +9 -11
  153. hpcflow/tests/unit/test_value_sequence.py +15 -12
  154. hpcflow/tests/unit/test_workflow.py +114 -83
  155. hpcflow/tests/unit/test_workflow_template.py +0 -1
  156. hpcflow/tests/unit/utils/test_arrays.py +40 -0
  157. hpcflow/tests/unit/utils/test_deferred_file_writer.py +34 -0
  158. hpcflow/tests/unit/utils/test_hashing.py +65 -0
  159. hpcflow/tests/unit/utils/test_patches.py +5 -0
  160. hpcflow/tests/unit/utils/test_redirect_std.py +50 -0
  161. hpcflow/tests/workflows/__init__.py +0 -0
  162. hpcflow/tests/workflows/test_directory_structure.py +31 -0
  163. hpcflow/tests/workflows/test_jobscript.py +334 -1
  164. hpcflow/tests/workflows/test_run_status.py +198 -0
  165. hpcflow/tests/workflows/test_skip_downstream.py +696 -0
  166. hpcflow/tests/workflows/test_submission.py +140 -0
  167. hpcflow/tests/workflows/test_workflows.py +160 -15
  168. hpcflow/tests/workflows/test_zip.py +18 -0
  169. hpcflow/viz_demo.ipynb +6587 -3
  170. {hpcflow_new2-0.2.0a189.dist-info → hpcflow_new2-0.2.0a199.dist-info}/METADATA +8 -4
  171. hpcflow_new2-0.2.0a199.dist-info/RECORD +221 -0
  172. hpcflow/sdk/core/parallel.py +0 -21
  173. hpcflow_new2-0.2.0a189.dist-info/RECORD +0 -158
  174. {hpcflow_new2-0.2.0a189.dist-info → hpcflow_new2-0.2.0a199.dist-info}/LICENSE +0 -0
  175. {hpcflow_new2-0.2.0a189.dist-info → hpcflow_new2-0.2.0a199.dist-info}/WHEEL +0 -0
  176. {hpcflow_new2-0.2.0a189.dist-info → hpcflow_new2-0.2.0a199.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,440 @@
1
+ """
2
+ Types to support the core SDK.
3
+ """
4
+
5
+ from __future__ import annotations
6
+ from typing import Any, Literal, Protocol, TYPE_CHECKING
7
+ from typing_extensions import NotRequired, TypeAlias, TypedDict
8
+
9
+ if TYPE_CHECKING:
10
+ from collections.abc import Mapping, Sequence
11
+ from datetime import datetime, timedelta
12
+ import numpy as np
13
+ from valida.conditions import ConditionLike # type: ignore
14
+ from .actions import ActionScope
15
+ from .command_files import FileSpec
16
+ from .enums import ParallelMode, ParameterPropagationMode
17
+ from .object_list import ResourceList
18
+ from .parameters import (
19
+ InputSource,
20
+ InputValue,
21
+ Parameter,
22
+ ResourceSpec,
23
+ )
24
+ from .task import InputStatus
25
+ from ..persistence.types import ParamSource
26
+
27
+
28
+ class ParameterDependence(TypedDict):
29
+ """
30
+ Dependency descriptor for a parameter.
31
+ """
32
+
33
+ #: The input file writers that can use the parameter.
34
+ input_file_writers: list[FileSpec]
35
+ #: The commands that can use the parameter.
36
+ commands: list[int]
37
+
38
+
39
+ class ScriptData(TypedDict, total=False):
40
+ """
41
+ Descriptor for data relating to a script.
42
+ """
43
+
44
+ #: The format of the data.
45
+ format: str
46
+ #: Whether the data is required for all iterations.
47
+ all_iterations: NotRequired[bool]
48
+
49
+
50
+ class JobscriptSubmissionFailureArgs(TypedDict):
51
+ """
52
+ Arguments that can be expanded to create a
53
+ :class:`JobscriptSubmissionFailure`.
54
+ """
55
+
56
+ #: The command that was submitted.
57
+ submit_cmd: list[str]
58
+ #: The jobscript index.
59
+ js_idx: int
60
+ #: The jobscript path.
61
+ js_path: str
62
+ #: Where to write stdout.
63
+ stdout: NotRequired[str]
64
+ #: Where to write stderr.
65
+ stderr: NotRequired[str]
66
+ #: The exception from the exec of the subprocess.
67
+ subprocess_exc: NotRequired[Exception]
68
+ #: The exception from parsing the job ID.
69
+ job_ID_parse_exc: NotRequired[Exception]
70
+
71
+
72
+ class ElementDescriptor(TypedDict):
73
+ """
74
+ Descriptor for elements.
75
+ """
76
+
77
+ #: The statuses of inputs.
78
+ input_statuses: Mapping[str, InputStatus]
79
+ #: The sources of inputs.
80
+ input_sources: Mapping[str, InputSource]
81
+ #: The insertion ID.
82
+ task_insert_ID: int
83
+
84
+
85
+ class _DependentDescriptor(TypedDict):
86
+ #: The names of groups of dependents.
87
+ group_names: tuple[str, ...]
88
+
89
+
90
+ class DependentDescriptor(_DependentDescriptor, total=False):
91
+ """
92
+ Descriptor for dependents.
93
+ """
94
+
95
+
96
+ class IterableParam(TypedDict):
97
+ """
98
+ The type of the descriptor for an iterable parameter.
99
+ """
100
+
101
+ #: Identifier for the input task supplying the parameter.
102
+ input_task: int
103
+ #: Identifiers for the output tasks consuming the parameter.
104
+ output_tasks: list[int]
105
+
106
+
107
+ #: Type of an address.
108
+ Address: TypeAlias = "list[int | float | str]"
109
+ #: Type of something numeric.
110
+ Numeric: TypeAlias = "int | float | np.number"
111
+
112
+
113
+ class LabelInfo(TypedDict):
114
+ """
115
+ Information about a label.
116
+ """
117
+
118
+ #: The label propagation mode, if known.
119
+ propagation_mode: NotRequired[ParameterPropagationMode]
120
+ #: The group containing the label, if known.
121
+ group: NotRequired[str]
122
+ #: The default value for the label, if known.
123
+ default_value: NotRequired[InputValue]
124
+
125
+
126
+ class LabellingDescriptor(TypedDict):
127
+ """
128
+ Descriptor for a labelling.
129
+ """
130
+
131
+ #: The type with the label.
132
+ labelled_type: str
133
+ #: The propagation mode for the label.
134
+ propagation_mode: ParameterPropagationMode
135
+ #: The group containing the label.
136
+ group: str | None
137
+ #: The default value for the label, if known.
138
+ default_value: NotRequired[InputValue]
139
+
140
+
141
+ class ResourceSpecArgs(TypedDict):
142
+ """
143
+ Supported keyword arguments for a ResourceSpec.
144
+ """
145
+
146
+ #: Which scope does this apply to.
147
+ scope: NotRequired[ActionScope | str]
148
+ #: Which scratch space to use.
149
+ scratch: NotRequired[str]
150
+ #: Which parallel mode to use.
151
+ parallel_mode: NotRequired[str | ParallelMode]
152
+ #: How many cores to request.
153
+ num_cores: NotRequired[int]
154
+ #: How many cores per compute node to request.
155
+ num_cores_per_node: NotRequired[int]
156
+ #: How many threads to request.
157
+ num_threads: NotRequired[int]
158
+ #: How many compute nodes to request.
159
+ num_nodes: NotRequired[int]
160
+ #: Which scheduler to use.
161
+ scheduler: NotRequired[str]
162
+ #: Which system shell to use.
163
+ shell: NotRequired[str]
164
+ #: Whether to use array jobs.
165
+ use_job_array: NotRequired[bool]
166
+ #: If using array jobs, up to how many items should be in the job array.
167
+ max_array_items: NotRequired[int]
168
+ #: How long to run for.
169
+ time_limit: NotRequired[str | timedelta]
170
+ #: Additional arguments to pass to the scheduler.
171
+ scheduler_args: NotRequired[dict[str, Any]]
172
+ #: Additional arguments to pass to the shell.
173
+ shell_args: NotRequired[dict[str, Any]]
174
+ #: Which OS to use.
175
+ os_name: NotRequired[str]
176
+ #: Which execution environments to use.
177
+ environments: NotRequired[dict[str, dict[str, Any]]]
178
+ #: Which SGE parallel environment to request.
179
+ SGE_parallel_env: NotRequired[str]
180
+ #: Which SLURM partition to request.
181
+ SLURM_partition: NotRequired[str]
182
+ #: How many SLURM tasks to request.
183
+ SLURM_num_tasks: NotRequired[str]
184
+ #: How many SLURM tasks per compute node to request.
185
+ SLURM_num_tasks_per_node: NotRequired[str]
186
+ #: How many compute nodes to request.
187
+ SLURM_num_nodes: NotRequired[str]
188
+ #: How many CPU cores to ask for per SLURM task.
189
+ SLURM_num_cpus_per_task: NotRequired[str]
190
+
191
+
192
+ # Used in declaration of Resources below
193
+ _R: TypeAlias = "ResourceSpec | ResourceSpecArgs | dict"
194
+ #: The type of things we can normalise to a :py:class:`ResourceList`.
195
+ Resources: TypeAlias = "_R | ResourceList | None | Sequence[_R]"
196
+
197
+
198
+ class SchemaInputKwargs(TypedDict):
199
+ """
200
+ Just used when deep copying `SchemaInput`.
201
+ """
202
+
203
+ #: The parameter.
204
+ parameter: Parameter | str
205
+ #: Whether this is multiple.
206
+ multiple: bool
207
+ #: The labels.
208
+ labels: dict[str, LabelInfo] | None
209
+ #: The number or proportional of permitted unset parameter data found when reolving
210
+ #: this input from upstream outputs.
211
+ allow_failed_dependencies: int | float | bool | None
212
+
213
+
214
+ class RuleArgs(TypedDict):
215
+ """
216
+ The keyword arguments that may be used to create a Rule.
217
+ """
218
+
219
+ #: If present, check this attribute exists.
220
+ check_exists: NotRequired[str]
221
+ #: If present, check this attribute does *not* exist.
222
+ check_missing: NotRequired[str]
223
+ #: Where to look up the attribute to check.
224
+ #: If not present, determined by context.
225
+ path: NotRequired[str]
226
+ #: If present, a general condition to check (or kwargs used to generate one).
227
+ condition: NotRequired[dict[str, Any] | ConditionLike]
228
+ #: If present, a cast to apply prior to running the general check.
229
+ cast: NotRequired[str]
230
+ #: Optional descriptive text.
231
+ doc: NotRequired[str]
232
+
233
+
234
+ class ActParameterDependence(TypedDict):
235
+ """
236
+ Action parameter dependency descriptor.
237
+ """
238
+
239
+ #: The input file writers that produce the parameter.
240
+ input_file_writers: list[tuple[int, FileSpec]]
241
+ #: The commands that produce the parameter.
242
+ commands: list[tuple[int, int]]
243
+
244
+
245
+ #: A relevant path when applying an update.
246
+ RelevantPath: TypeAlias = "ParentPath | UpdatePath | SiblingPath"
247
+
248
+
249
+ class RepeatsDescriptor(TypedDict):
250
+ """
251
+ Descriptor for repeats.
252
+ """
253
+
254
+ #: Name of the repeat.
255
+ name: str
256
+ #: The repeat count.
257
+ number: int
258
+ #: The nesting order. Normally an integer; non-integer values have special meanings.
259
+ nesting_order: float
260
+
261
+
262
+ class MultiplicityDescriptor(TypedDict):
263
+ """
264
+ Descriptor for multiplicities.
265
+ """
266
+
267
+ #: The size of the multiplicity.
268
+ multiplicity: int
269
+ #: The nesting order. Normally an integer; non-integer values have special meanings.
270
+ nesting_order: float
271
+ #: The path to the multiplicity.
272
+ path: str
273
+
274
+
275
+ class ParentPath(TypedDict):
276
+ """
277
+ A `RelevantPath` that is a path to a parent.
278
+ """
279
+
280
+ #: Type ID.
281
+ type: Literal["parent"]
282
+ relative_path: Sequence[str]
283
+
284
+
285
+ class UpdatePath(TypedDict):
286
+ """
287
+ A `RelevantPath` that is a path to an update.
288
+ """
289
+
290
+ #: Type ID.
291
+ type: Literal["update"]
292
+ update_path: Sequence[str]
293
+
294
+
295
+ class SiblingPath(TypedDict):
296
+ """
297
+ A `RelevantPath` that is a path to a sibling.
298
+ """
299
+
300
+ #: Type ID.
301
+ type: Literal["sibling"]
302
+
303
+
304
+ class RelevantData(TypedDict):
305
+ """
306
+ Data relevant to performing an update.
307
+ """
308
+
309
+ #: The data to set.
310
+ data: list[Any] | Any
311
+ #: Which method to use for handling the data, if any.
312
+ value_class_method: list[str | None] | str | None
313
+ #: Whether the value is set.
314
+ is_set: bool | list[bool]
315
+ #: Whether the value is multiple.
316
+ is_multi: bool
317
+
318
+
319
+ class CreationInfo(TypedDict):
320
+ """
321
+ Descriptor for creation information about a workflow.
322
+ """
323
+
324
+ #: Description of information about the application.
325
+ app_info: dict[str, Any]
326
+ #: When the workflow was created.
327
+ create_time: datetime
328
+ #: Unique identifier for the workflow.
329
+ id: str
330
+
331
+
332
+ class WorkflowTemplateTaskData(TypedDict):
333
+ """
334
+ Descriptor for information about tasks described in a workflow template.
335
+ """
336
+
337
+ #: The schema, if known.
338
+ schema: NotRequired[Any | list[Any]]
339
+ #: The element sets, if known.
340
+ element_sets: NotRequired[list[WorkflowTemplateElementSetData]]
341
+ #: The output labels, if known.
342
+ output_labels: NotRequired[list[str]]
343
+
344
+
345
+ class WorkflowTemplateElementSetData(TypedDict):
346
+ """
347
+ Descriptor for element set data within a workflow template parametrisation.
348
+ """
349
+
350
+ #: Inputs to the set of elements.
351
+ inputs: NotRequired[list[dict[str, Any]]]
352
+ #: Input files to the set of elements.
353
+ input_files: NotRequired[list[dict[str, Any]]]
354
+ #: Description of how to repeat the set of elements.
355
+ repeats: NotRequired[int | list[RepeatsDescriptor]]
356
+ #: Groupings in the set of elements.
357
+ groups: NotRequired[list[dict[str, Any]]]
358
+ #: Resources to use for the set of elements.
359
+ resources: NotRequired[dict[str, Any]]
360
+ #: Input value sequences to parameterise over.
361
+ sequences: NotRequired[list[dict[str, Any]]]
362
+ #: Input value multi-path sequences to parameterise over.
363
+ multi_path_sequences: NotRequired[list[dict[str, Any]]]
364
+ #: Input source descriptors.
365
+ input_sources: NotRequired[dict[str, list]]
366
+ #: How to handle nesting of iterations.
367
+ nesting_order: NotRequired[dict[str, float]]
368
+ #: Which environment preset to use.
369
+ env_preset: NotRequired[str]
370
+ #: Environment descriptors to use.
371
+ environments: NotRequired[dict[str, dict[str, Any]]]
372
+ #: List of global element iteration indices from which inputs for
373
+ #: the new elements associated with this element set may be sourced.
374
+ #: If ``None``, all iterations are valid.
375
+ sourceable_elem_iters: NotRequired[list[int]]
376
+ #: Whether to allow sources to come from distinct element sub-sets.
377
+ allow_non_coincident_task_sources: NotRequired[bool]
378
+ #: Whether this initialisation is the first for this data (i.e. not a
379
+ #: reconstruction from persistent workflow data), in which case, we merge
380
+ #: ``environments`` into ``resources`` using the "any" scope, and merge any multi-
381
+ #: path sequences into the sequences list.
382
+ is_creation: NotRequired[bool]
383
+
384
+
385
+ class Pending(TypedDict):
386
+ """
387
+ Pending update information. Internal use only.
388
+ """
389
+
390
+ #: Template components to update.
391
+ template_components: dict[str, list[int]]
392
+ #: Tasks to update.
393
+ tasks: list[int]
394
+ #: Loops to update.
395
+ loops: list[int]
396
+ #: Submissions to update.
397
+ submissions: list[int]
398
+
399
+
400
+ class AbstractFileSystem(Protocol):
401
+ """
402
+ Type constraints for an abstract file system.
403
+ """
404
+
405
+ # Because a dependency is not fully typed...
406
+ def exists(self, path: str) -> bool:
407
+ """Test if a path points to a file or directory that exists."""
408
+
409
+ def rename(self, from_: str, to: str, *, recursive: bool = False) -> None:
410
+ """Rename a file or directory."""
411
+
412
+ def rm(self, path: str, *, recursive: bool = False) -> None:
413
+ """Delete a file or directory."""
414
+
415
+ def glob(self, pattern: str) -> list[str]:
416
+ """List files in a directory that match a pattern."""
417
+
418
+
419
+ class ResourcePersistingWorkflow(Protocol):
420
+ """
421
+ An object to pass to :py:meth:`ResourceSpec.make_persistent` that handles
422
+ persisting resources.
423
+ """
424
+
425
+ def _add_parameter_data(self, data: Any, source: ParamSource) -> int:
426
+ ...
427
+
428
+ def check_parameters_exist(self, id_lst: int | list[int]) -> bool:
429
+ """
430
+ Check if all the parameters exist.
431
+ """
432
+
433
+
434
+ BlockActionKey: TypeAlias = "tuple[int | str, int | str, int | str]"
435
+ """
436
+ The type of indices that locate an action within a submission. The indices represent,
437
+ respectively, the jobscript index, the jobscript-block index, and the block-action index.
438
+ Usually, these are integers, but in the case of strings, they will correspond to shell
439
+ environment variables.
440
+ """