hpcflow-new2 0.2.0a189__py3-none-any.whl → 0.2.0a190__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 +8 -6
- hpcflow/_version.py +1 -1
- hpcflow/app.py +1 -0
- hpcflow/data/scripts/main_script_test_hdf5_in_obj.py +1 -1
- hpcflow/data/scripts/main_script_test_hdf5_out_obj.py +1 -1
- hpcflow/sdk/__init__.py +21 -15
- hpcflow/sdk/app.py +2133 -770
- hpcflow/sdk/cli.py +281 -250
- hpcflow/sdk/cli_common.py +6 -2
- hpcflow/sdk/config/__init__.py +1 -1
- hpcflow/sdk/config/callbacks.py +77 -42
- hpcflow/sdk/config/cli.py +126 -103
- hpcflow/sdk/config/config.py +578 -311
- hpcflow/sdk/config/config_file.py +131 -95
- hpcflow/sdk/config/errors.py +112 -85
- hpcflow/sdk/config/types.py +145 -0
- hpcflow/sdk/core/actions.py +1054 -994
- hpcflow/sdk/core/app_aware.py +24 -0
- hpcflow/sdk/core/cache.py +81 -63
- hpcflow/sdk/core/command_files.py +275 -185
- hpcflow/sdk/core/commands.py +111 -107
- hpcflow/sdk/core/element.py +724 -503
- hpcflow/sdk/core/enums.py +192 -0
- hpcflow/sdk/core/environment.py +74 -93
- hpcflow/sdk/core/errors.py +398 -51
- hpcflow/sdk/core/json_like.py +540 -272
- hpcflow/sdk/core/loop.py +380 -334
- hpcflow/sdk/core/loop_cache.py +160 -43
- hpcflow/sdk/core/object_list.py +370 -207
- hpcflow/sdk/core/parameters.py +728 -600
- hpcflow/sdk/core/rule.py +59 -41
- hpcflow/sdk/core/run_dir_files.py +33 -22
- hpcflow/sdk/core/task.py +1546 -1325
- hpcflow/sdk/core/task_schema.py +240 -196
- hpcflow/sdk/core/test_utils.py +126 -88
- hpcflow/sdk/core/types.py +387 -0
- hpcflow/sdk/core/utils.py +410 -305
- hpcflow/sdk/core/validation.py +82 -9
- hpcflow/sdk/core/workflow.py +1192 -1028
- hpcflow/sdk/core/zarr_io.py +98 -137
- hpcflow/sdk/demo/cli.py +46 -33
- hpcflow/sdk/helper/cli.py +18 -16
- hpcflow/sdk/helper/helper.py +75 -63
- hpcflow/sdk/helper/watcher.py +61 -28
- hpcflow/sdk/log.py +83 -59
- hpcflow/sdk/persistence/__init__.py +8 -31
- hpcflow/sdk/persistence/base.py +988 -586
- hpcflow/sdk/persistence/defaults.py +6 -0
- hpcflow/sdk/persistence/discovery.py +38 -0
- hpcflow/sdk/persistence/json.py +408 -153
- hpcflow/sdk/persistence/pending.py +158 -123
- hpcflow/sdk/persistence/store_resource.py +37 -22
- hpcflow/sdk/persistence/types.py +307 -0
- hpcflow/sdk/persistence/utils.py +14 -11
- hpcflow/sdk/persistence/zarr.py +477 -420
- hpcflow/sdk/runtime.py +44 -41
- hpcflow/sdk/submission/{jobscript_info.py → enums.py} +39 -12
- hpcflow/sdk/submission/jobscript.py +444 -404
- hpcflow/sdk/submission/schedulers/__init__.py +133 -40
- hpcflow/sdk/submission/schedulers/direct.py +97 -71
- hpcflow/sdk/submission/schedulers/sge.py +132 -126
- hpcflow/sdk/submission/schedulers/slurm.py +263 -268
- hpcflow/sdk/submission/schedulers/utils.py +7 -2
- hpcflow/sdk/submission/shells/__init__.py +14 -15
- hpcflow/sdk/submission/shells/base.py +102 -29
- hpcflow/sdk/submission/shells/bash.py +72 -55
- hpcflow/sdk/submission/shells/os_version.py +31 -30
- hpcflow/sdk/submission/shells/powershell.py +37 -29
- hpcflow/sdk/submission/submission.py +203 -257
- hpcflow/sdk/submission/types.py +143 -0
- hpcflow/sdk/typing.py +163 -12
- hpcflow/tests/conftest.py +8 -6
- hpcflow/tests/schedulers/slurm/test_slurm_submission.py +5 -2
- hpcflow/tests/scripts/test_main_scripts.py +60 -30
- hpcflow/tests/shells/wsl/test_wsl_submission.py +6 -4
- hpcflow/tests/unit/test_action.py +86 -75
- hpcflow/tests/unit/test_action_rule.py +9 -4
- hpcflow/tests/unit/test_app.py +13 -6
- hpcflow/tests/unit/test_cli.py +1 -1
- hpcflow/tests/unit/test_command.py +71 -54
- hpcflow/tests/unit/test_config.py +20 -15
- hpcflow/tests/unit/test_config_file.py +21 -18
- hpcflow/tests/unit/test_element.py +58 -62
- hpcflow/tests/unit/test_element_iteration.py +3 -1
- hpcflow/tests/unit/test_element_set.py +29 -19
- hpcflow/tests/unit/test_group.py +4 -2
- hpcflow/tests/unit/test_input_source.py +116 -93
- hpcflow/tests/unit/test_input_value.py +29 -24
- hpcflow/tests/unit/test_json_like.py +44 -35
- hpcflow/tests/unit/test_loop.py +65 -58
- hpcflow/tests/unit/test_object_list.py +17 -12
- hpcflow/tests/unit/test_parameter.py +16 -7
- hpcflow/tests/unit/test_persistence.py +48 -35
- hpcflow/tests/unit/test_resources.py +20 -18
- hpcflow/tests/unit/test_run.py +8 -3
- hpcflow/tests/unit/test_runtime.py +2 -1
- hpcflow/tests/unit/test_schema_input.py +23 -15
- hpcflow/tests/unit/test_shell.py +3 -2
- hpcflow/tests/unit/test_slurm.py +8 -7
- hpcflow/tests/unit/test_submission.py +39 -19
- hpcflow/tests/unit/test_task.py +352 -247
- hpcflow/tests/unit/test_task_schema.py +33 -20
- hpcflow/tests/unit/test_utils.py +9 -11
- hpcflow/tests/unit/test_value_sequence.py +15 -12
- hpcflow/tests/unit/test_workflow.py +114 -83
- hpcflow/tests/unit/test_workflow_template.py +0 -1
- hpcflow/tests/workflows/test_jobscript.py +2 -1
- hpcflow/tests/workflows/test_workflows.py +18 -13
- {hpcflow_new2-0.2.0a189.dist-info → hpcflow_new2-0.2.0a190.dist-info}/METADATA +2 -1
- hpcflow_new2-0.2.0a190.dist-info/RECORD +165 -0
- hpcflow/sdk/core/parallel.py +0 -21
- hpcflow_new2-0.2.0a189.dist-info/RECORD +0 -158
- {hpcflow_new2-0.2.0a189.dist-info → hpcflow_new2-0.2.0a190.dist-info}/LICENSE +0 -0
- {hpcflow_new2-0.2.0a189.dist-info → hpcflow_new2-0.2.0a190.dist-info}/WHEEL +0 -0
- {hpcflow_new2-0.2.0a189.dist-info → hpcflow_new2-0.2.0a190.dist-info}/entry_points.txt +0 -0
hpcflow/sdk/core/test_utils.py
CHANGED
@@ -2,19 +2,43 @@
|
|
2
2
|
Utilities for making data to use in testing.
|
3
3
|
"""
|
4
4
|
|
5
|
+
from __future__ import annotations
|
5
6
|
from dataclasses import dataclass
|
6
|
-
from importlib import resources
|
7
7
|
from pathlib import Path
|
8
|
-
from typing import
|
8
|
+
from typing import Any, ClassVar, TYPE_CHECKING
|
9
9
|
from hpcflow.app import app as hf
|
10
10
|
from hpcflow.sdk.core.parameters import ParameterValue
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
from hpcflow.sdk.core.utils import get_file_context
|
12
|
+
from hpcflow.sdk.typing import hydrate
|
13
|
+
|
14
|
+
if TYPE_CHECKING:
|
15
|
+
from collections.abc import Iterable, Mapping
|
16
|
+
from typing_extensions import TypeAlias
|
17
|
+
from h5py import Group as HDFSGroup # type: ignore
|
18
|
+
from .actions import Action
|
19
|
+
from .element import ElementGroup
|
20
|
+
from .loop import Loop
|
21
|
+
from .parameters import InputSource, Parameter
|
22
|
+
from .task import Task
|
23
|
+
from .task_schema import TaskSchema
|
24
|
+
from .types import Resources
|
25
|
+
from .workflow import Workflow, WorkflowTemplate
|
26
|
+
from ..app import BaseApp
|
27
|
+
from ..typing import PathLike
|
28
|
+
# mypy: disable-error-code="no-untyped-def"
|
29
|
+
|
30
|
+
#: A string or a tuple of strings.
|
31
|
+
Strs: TypeAlias = "str | tuple[str, ...]"
|
32
|
+
|
33
|
+
|
34
|
+
def make_schemas(
|
35
|
+
*ins_outs: tuple[dict[str, Any], tuple[str, ...]]
|
36
|
+
| tuple[dict[str, Any], tuple[str, ...], str]
|
37
|
+
) -> list[TaskSchema]:
|
14
38
|
"""
|
15
39
|
Construct a collection of schemas.
|
16
40
|
"""
|
17
|
-
out = []
|
41
|
+
out: list[TaskSchema] = []
|
18
42
|
for idx, info in enumerate(ins_outs):
|
19
43
|
if len(info) == 2:
|
20
44
|
(ins_i, outs_i) = info
|
@@ -40,7 +64,7 @@ def make_schemas(ins_outs, ret_list=False):
|
|
40
64
|
for out_i in outs_i[2:]
|
41
65
|
]
|
42
66
|
cmd = hf.Command(
|
43
|
-
" ".join(f"echo $((<<parameter:{i}>> + 100))" for i in ins_i
|
67
|
+
" ".join(f"echo $((<<parameter:{i}>> + 100))" for i in ins_i),
|
44
68
|
stdout=stdout,
|
45
69
|
stderr=stderr,
|
46
70
|
)
|
@@ -55,15 +79,13 @@ def make_schemas(ins_outs, ret_list=False):
|
|
55
79
|
objective=obj,
|
56
80
|
actions=[act_i],
|
57
81
|
inputs=[hf.SchemaInput(k, default_value=v) for k, v in ins_i.items()],
|
58
|
-
outputs=[hf.SchemaOutput(k) for k in outs_i],
|
82
|
+
outputs=[hf.SchemaOutput(hf.Parameter(k)) for k in outs_i],
|
59
83
|
)
|
60
84
|
)
|
61
|
-
if len(ins_outs) == 1 and not ret_list:
|
62
|
-
out = out[0]
|
63
85
|
return out
|
64
86
|
|
65
87
|
|
66
|
-
def make_parameters(num):
|
88
|
+
def make_parameters(num: int) -> list[Parameter]:
|
67
89
|
"""
|
68
90
|
Construct a sequence of parameters.
|
69
91
|
"""
|
@@ -71,9 +93,9 @@ def make_parameters(num):
|
|
71
93
|
|
72
94
|
|
73
95
|
def make_actions(
|
74
|
-
ins_outs:
|
75
|
-
env="env1",
|
76
|
-
) ->
|
96
|
+
ins_outs: list[tuple[Strs, str] | tuple[Strs, str, str]],
|
97
|
+
env: str = "env1",
|
98
|
+
) -> list[Action]:
|
77
99
|
"""
|
78
100
|
Construct a collection of actions.
|
79
101
|
"""
|
@@ -82,7 +104,7 @@ def make_actions(
|
|
82
104
|
for ins_outs_i in ins_outs:
|
83
105
|
if len(ins_outs_i) == 2:
|
84
106
|
ins, out = ins_outs_i
|
85
|
-
err = None
|
107
|
+
err: str | None = None
|
86
108
|
else:
|
87
109
|
ins, out, err = ins_outs_i
|
88
110
|
if not isinstance(ins, tuple):
|
@@ -103,14 +125,19 @@ def make_actions(
|
|
103
125
|
|
104
126
|
|
105
127
|
def make_tasks(
|
106
|
-
schemas_spec
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
)
|
128
|
+
schemas_spec: Iterable[
|
129
|
+
tuple[dict[str, Any], tuple[str, ...]]
|
130
|
+
| tuple[dict[str, Any], tuple[str, ...], str]
|
131
|
+
],
|
132
|
+
local_inputs: dict[int, Iterable[str]] | None = None,
|
133
|
+
local_sequences: (
|
134
|
+
dict[int, Iterable[tuple[str, int, int | float | None]]] | None
|
135
|
+
) = None,
|
136
|
+
local_resources: dict[int, dict[str, dict]] | None = None,
|
137
|
+
nesting_orders: dict[int, dict[str, float]] | None = None,
|
138
|
+
input_sources: dict[int, dict[str, list[InputSource]]] | None = None,
|
139
|
+
groups: dict[int, Iterable[ElementGroup]] | None = None,
|
140
|
+
) -> list[Task]:
|
114
141
|
"""
|
115
142
|
Construct a sequence of tasks.
|
116
143
|
"""
|
@@ -120,12 +147,12 @@ def make_tasks(
|
|
120
147
|
nesting_orders = nesting_orders or {}
|
121
148
|
input_sources = input_sources or {}
|
122
149
|
groups = groups or {}
|
123
|
-
schemas = make_schemas(schemas_spec
|
124
|
-
tasks = []
|
150
|
+
schemas = make_schemas(*schemas_spec)
|
151
|
+
tasks: list[Task] = []
|
125
152
|
for s_idx, s in enumerate(schemas):
|
126
153
|
inputs = [
|
127
154
|
hf.InputValue(hf.Parameter(i), value=int(i[1:]) * 100)
|
128
|
-
for i in local_inputs.get(s_idx,
|
155
|
+
for i in local_inputs.get(s_idx, ())
|
129
156
|
]
|
130
157
|
seqs = [
|
131
158
|
hf.ValueSequence(
|
@@ -133,7 +160,7 @@ def make_tasks(
|
|
133
160
|
values=[(int(i[0].split(".")[1][1:]) * 100) + j for j in range(i[1])],
|
134
161
|
nesting_order=i[2],
|
135
162
|
)
|
136
|
-
for i in local_sequences.get(s_idx,
|
163
|
+
for i in local_sequences.get(s_idx, ())
|
137
164
|
]
|
138
165
|
res = {k: v for k, v in local_resources.get(s_idx, {}).items()}
|
139
166
|
task = hf.Task(
|
@@ -143,27 +170,32 @@ def make_tasks(
|
|
143
170
|
resources=res,
|
144
171
|
nesting_order=nesting_orders.get(s_idx, {}),
|
145
172
|
input_sources=input_sources.get(s_idx, None),
|
146
|
-
groups=groups.get(s_idx),
|
173
|
+
groups=list(groups.get(s_idx, ())),
|
147
174
|
)
|
148
175
|
tasks.append(task)
|
149
176
|
return tasks
|
150
177
|
|
151
178
|
|
152
179
|
def make_workflow(
|
153
|
-
schemas_spec
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
180
|
+
schemas_spec: Iterable[
|
181
|
+
tuple[dict[str, Any], tuple[str, ...]]
|
182
|
+
| tuple[dict[str, Any], tuple[str, ...], str]
|
183
|
+
],
|
184
|
+
path: PathLike,
|
185
|
+
local_inputs: dict[int, Iterable[str]] | None = None,
|
186
|
+
local_sequences: (
|
187
|
+
dict[int, Iterable[tuple[str, int, int | float | None]]] | None
|
188
|
+
) = None,
|
189
|
+
local_resources: dict[int, dict[str, dict]] | None = None,
|
190
|
+
nesting_orders: dict[int, dict[str, float]] | None = None,
|
191
|
+
input_sources: dict[int, dict[str, list[InputSource]]] | None = None,
|
192
|
+
resources: Resources = None,
|
193
|
+
loops: list[Loop] | None = None,
|
194
|
+
groups: dict[int, Iterable[ElementGroup]] | None = None,
|
195
|
+
name: str = "w1",
|
196
|
+
overwrite: bool = False,
|
197
|
+
store: str = "zarr",
|
198
|
+
) -> Workflow:
|
167
199
|
"""
|
168
200
|
Construct a workflow.
|
169
201
|
"""
|
@@ -176,13 +208,12 @@ def make_workflow(
|
|
176
208
|
input_sources=input_sources,
|
177
209
|
groups=groups,
|
178
210
|
)
|
179
|
-
template = {
|
211
|
+
template: Mapping[str, Any] = {
|
180
212
|
"name": name,
|
181
213
|
"tasks": tasks,
|
182
214
|
"resources": resources,
|
215
|
+
**({"loops": loops} if loops else {}),
|
183
216
|
}
|
184
|
-
if loops:
|
185
|
-
template["loops"] = loops
|
186
217
|
wk = hf.Workflow.from_template(
|
187
218
|
hf.WorkflowTemplate(**template),
|
188
219
|
path=path,
|
@@ -194,36 +225,40 @@ def make_workflow(
|
|
194
225
|
|
195
226
|
|
196
227
|
def make_test_data_YAML_workflow(
|
197
|
-
workflow_name
|
198
|
-
|
228
|
+
workflow_name: str,
|
229
|
+
path: PathLike,
|
230
|
+
app: BaseApp | None = None,
|
231
|
+
pkg: str = "hpcflow.tests.data",
|
232
|
+
**kwargs,
|
233
|
+
) -> Workflow:
|
199
234
|
"""Generate a workflow whose template file is defined in the test data directory."""
|
200
|
-
app =
|
201
|
-
|
202
|
-
|
203
|
-
with script_ctx as file_path:
|
235
|
+
app = app or hf
|
236
|
+
with get_file_context(pkg, workflow_name) as file_path:
|
204
237
|
return app.Workflow.from_YAML_file(YAML_path=file_path, path=path, **kwargs)
|
205
238
|
|
206
239
|
|
207
240
|
def make_test_data_YAML_workflow_template(
|
208
|
-
workflow_name
|
209
|
-
|
241
|
+
workflow_name: str,
|
242
|
+
app: BaseApp | None = None,
|
243
|
+
pkg: str = "hpcflow.tests.data",
|
244
|
+
**kwargs,
|
245
|
+
) -> WorkflowTemplate:
|
210
246
|
"""Generate a workflow template whose file is defined in the test data directory."""
|
211
|
-
app =
|
212
|
-
|
213
|
-
|
214
|
-
with script_ctx as file_path:
|
247
|
+
app = app or hf
|
248
|
+
with get_file_context(pkg, workflow_name) as file_path:
|
215
249
|
return app.WorkflowTemplate.from_file(path=file_path, **kwargs)
|
216
250
|
|
217
251
|
|
218
252
|
@dataclass
|
253
|
+
@hydrate
|
219
254
|
class P1_sub_parameter_cls(ParameterValue):
|
220
255
|
"""
|
221
256
|
Parameter value handler: ``p1_sub``
|
222
257
|
"""
|
223
258
|
|
224
|
-
_typ = "p1_sub"
|
259
|
+
_typ: ClassVar[str] = "p1_sub"
|
225
260
|
|
226
|
-
e: int
|
261
|
+
e: int = 0
|
227
262
|
|
228
263
|
def CLI_format(self) -> str:
|
229
264
|
return str(self.e)
|
@@ -232,25 +267,27 @@ class P1_sub_parameter_cls(ParameterValue):
|
|
232
267
|
def twice_e(self):
|
233
268
|
return self.e * 2
|
234
269
|
|
235
|
-
def prepare_JSON_dump(self) ->
|
270
|
+
def prepare_JSON_dump(self) -> dict[str, Any]:
|
236
271
|
return {"e": self.e}
|
237
272
|
|
238
|
-
def dump_to_HDF5_group(self, group):
|
273
|
+
def dump_to_HDF5_group(self, group: HDFSGroup):
|
239
274
|
group.attrs["e"] = self.e
|
240
275
|
|
241
276
|
|
242
277
|
@dataclass
|
278
|
+
@hydrate
|
243
279
|
class P1_sub_parameter_cls_2(ParameterValue):
|
244
280
|
"""
|
245
281
|
Parameter value handler: ``p1_sub_2``
|
246
282
|
"""
|
247
283
|
|
248
|
-
_typ = "p1_sub_2"
|
284
|
+
_typ: ClassVar[str] = "p1_sub_2"
|
249
285
|
|
250
|
-
f: int
|
286
|
+
f: int = 0
|
251
287
|
|
252
288
|
|
253
289
|
@dataclass
|
290
|
+
@hydrate
|
254
291
|
class P1_parameter_cls(ParameterValue):
|
255
292
|
"""
|
256
293
|
Parameter value handler: ``p1c``
|
@@ -260,12 +297,15 @@ class P1_parameter_cls(ParameterValue):
|
|
260
297
|
This is a composite value handler.
|
261
298
|
"""
|
262
299
|
|
263
|
-
_typ = "p1c"
|
264
|
-
_sub_parameters
|
300
|
+
_typ: ClassVar[str] = "p1c"
|
301
|
+
_sub_parameters: ClassVar[dict[str, str]] = {
|
302
|
+
"sub_param": "p1_sub",
|
303
|
+
"sub_param_2": "p1_sub_2",
|
304
|
+
}
|
265
305
|
|
266
|
-
a: int
|
267
|
-
d:
|
268
|
-
sub_param:
|
306
|
+
a: int = 0
|
307
|
+
d: int | None = None
|
308
|
+
sub_param: P1_sub_parameter_cls | None = None
|
269
309
|
|
270
310
|
def __post_init__(self):
|
271
311
|
if self.sub_param is not None and not isinstance(
|
@@ -274,22 +314,22 @@ class P1_parameter_cls(ParameterValue):
|
|
274
314
|
self.sub_param = P1_sub_parameter_cls(**self.sub_param)
|
275
315
|
|
276
316
|
@classmethod
|
277
|
-
def from_data(cls, b, c):
|
317
|
+
def from_data(cls, b: int, c: int):
|
278
318
|
return cls(a=b + c)
|
279
319
|
|
280
320
|
@classmethod
|
281
|
-
def from_file(cls, path):
|
321
|
+
def from_file(cls, path: str):
|
282
322
|
with Path(path).open("rt") as fh:
|
283
323
|
lns = fh.readlines()
|
284
324
|
a = int(lns[0])
|
285
325
|
return cls(a=a)
|
286
326
|
|
287
327
|
@property
|
288
|
-
def twice_a(self):
|
328
|
+
def twice_a(self) -> int:
|
289
329
|
return self.a * 2
|
290
330
|
|
291
331
|
@property
|
292
|
-
def sub_param_prop(self):
|
332
|
+
def sub_param_prop(self) -> P1_sub_parameter_cls:
|
293
333
|
return P1_sub_parameter_cls(e=4 * self.a)
|
294
334
|
|
295
335
|
def CLI_format(self) -> str:
|
@@ -297,20 +337,18 @@ class P1_parameter_cls(ParameterValue):
|
|
297
337
|
|
298
338
|
@staticmethod
|
299
339
|
def CLI_format_group(*objs) -> str:
|
300
|
-
|
340
|
+
return ""
|
301
341
|
|
302
342
|
@staticmethod
|
303
343
|
def sum(*objs, **kwargs) -> str:
|
304
344
|
return str(sum(i.a for i in objs))
|
305
345
|
|
306
|
-
def custom_CLI_format(
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
sub = 0 if sub is None else int(sub)
|
311
|
-
return str(self.a + add - sub)
|
346
|
+
def custom_CLI_format(self, add: str | None = None, sub: str | None = None) -> str:
|
347
|
+
add_i = 4 if add is None else int(add)
|
348
|
+
sub_i = 0 if sub is None else int(sub)
|
349
|
+
return str(self.a + add_i - sub_i)
|
312
350
|
|
313
|
-
def custom_CLI_format_prep(self, reps:
|
351
|
+
def custom_CLI_format_prep(self, reps: str | None = None) -> list[int]:
|
314
352
|
"""Used for testing custom object CLI formatting.
|
315
353
|
|
316
354
|
For example, with a command like this:
|
@@ -318,11 +356,11 @@ class P1_parameter_cls(ParameterValue):
|
|
318
356
|
`<<join[delim=","](parameter:p1c.custom_CLI_format_prep(reps=4))>>`.
|
319
357
|
|
320
358
|
"""
|
321
|
-
|
322
|
-
return [self.a] *
|
359
|
+
reps_int = 1 if reps is None else int(reps)
|
360
|
+
return [self.a] * reps_int
|
323
361
|
|
324
362
|
@classmethod
|
325
|
-
def CLI_parse(cls, a_str: str, double:
|
363
|
+
def CLI_parse(cls, a_str: str, double: str = "", e: str | None = None):
|
326
364
|
a = int(a_str)
|
327
365
|
if double.lower() == "true":
|
328
366
|
a *= 2
|
@@ -332,25 +370,25 @@ class P1_parameter_cls(ParameterValue):
|
|
332
370
|
sub_param = None
|
333
371
|
return cls(a=a, sub_param=sub_param)
|
334
372
|
|
335
|
-
def prepare_JSON_dump(self) ->
|
373
|
+
def prepare_JSON_dump(self) -> dict[str, Any]:
|
336
374
|
sub_param_js = self.sub_param.prepare_JSON_dump() if self.sub_param else None
|
337
375
|
return {"a": self.a, "d": self.d, "sub_param": sub_param_js}
|
338
376
|
|
339
|
-
def dump_to_HDF5_group(self, group):
|
377
|
+
def dump_to_HDF5_group(self, group: HDFSGroup):
|
340
378
|
group.attrs["a"] = self.a
|
341
379
|
if self.d is not None:
|
342
380
|
group.attrs["d"] = self.d
|
343
381
|
if self.sub_param:
|
344
|
-
sub_group = group.
|
382
|
+
sub_group = group.create_group("sub_param")
|
345
383
|
self.sub_param.dump_to_HDF5_group(sub_group)
|
346
384
|
|
347
385
|
@classmethod
|
348
|
-
def save_from_JSON(cls, data, param_id: int, workflow):
|
386
|
+
def save_from_JSON(cls, data: dict, param_id: int | list[int], workflow: Workflow):
|
349
387
|
obj = cls(**data) # TODO: pass sub-param
|
350
388
|
workflow.set_parameter_value(param_id=param_id, value=obj, commit=True)
|
351
389
|
|
352
390
|
@classmethod
|
353
|
-
def save_from_HDF5_group(cls, group, param_id: int, workflow):
|
391
|
+
def save_from_HDF5_group(cls, group: HDFSGroup, param_id: int, workflow: Workflow):
|
354
392
|
a = group.attrs["a"].item()
|
355
393
|
if "d" in group.attrs:
|
356
394
|
d = group.attrs["d"].item()
|