hpcflow-new2 0.2.0a178__py3-none-any.whl → 0.2.0a180__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/_version.py +1 -1
- hpcflow/data/demo_data_manifest/__init__.py +3 -0
- hpcflow/sdk/__init__.py +4 -1
- hpcflow/sdk/app.py +160 -15
- hpcflow/sdk/cli.py +14 -0
- hpcflow/sdk/cli_common.py +83 -0
- hpcflow/sdk/config/__init__.py +4 -0
- hpcflow/sdk/config/callbacks.py +25 -2
- hpcflow/sdk/config/cli.py +4 -1
- hpcflow/sdk/config/config.py +188 -14
- hpcflow/sdk/config/config_file.py +91 -3
- hpcflow/sdk/config/errors.py +33 -0
- hpcflow/sdk/core/__init__.py +2 -0
- hpcflow/sdk/core/actions.py +492 -35
- hpcflow/sdk/core/cache.py +22 -0
- hpcflow/sdk/core/command_files.py +221 -5
- hpcflow/sdk/core/commands.py +57 -0
- hpcflow/sdk/core/element.py +407 -8
- hpcflow/sdk/core/environment.py +92 -0
- hpcflow/sdk/core/errors.py +245 -61
- hpcflow/sdk/core/json_like.py +72 -14
- hpcflow/sdk/core/loop.py +122 -21
- hpcflow/sdk/core/loop_cache.py +34 -9
- hpcflow/sdk/core/object_list.py +172 -26
- hpcflow/sdk/core/parallel.py +14 -0
- hpcflow/sdk/core/parameters.py +478 -25
- hpcflow/sdk/core/rule.py +31 -1
- hpcflow/sdk/core/run_dir_files.py +12 -2
- hpcflow/sdk/core/task.py +407 -80
- hpcflow/sdk/core/task_schema.py +70 -9
- hpcflow/sdk/core/test_utils.py +35 -0
- hpcflow/sdk/core/utils.py +101 -4
- hpcflow/sdk/core/validation.py +13 -1
- hpcflow/sdk/core/workflow.py +316 -96
- hpcflow/sdk/core/zarr_io.py +23 -0
- hpcflow/sdk/data/__init__.py +13 -0
- hpcflow/sdk/demo/__init__.py +3 -0
- hpcflow/sdk/helper/__init__.py +3 -0
- hpcflow/sdk/helper/cli.py +9 -0
- hpcflow/sdk/helper/helper.py +28 -0
- hpcflow/sdk/helper/watcher.py +33 -0
- hpcflow/sdk/log.py +40 -0
- hpcflow/sdk/persistence/__init__.py +14 -4
- hpcflow/sdk/persistence/base.py +289 -23
- hpcflow/sdk/persistence/json.py +29 -0
- hpcflow/sdk/persistence/pending.py +217 -107
- hpcflow/sdk/persistence/store_resource.py +58 -2
- hpcflow/sdk/persistence/utils.py +8 -0
- hpcflow/sdk/persistence/zarr.py +68 -1
- hpcflow/sdk/runtime.py +52 -10
- hpcflow/sdk/submission/__init__.py +3 -0
- hpcflow/sdk/submission/jobscript.py +198 -9
- hpcflow/sdk/submission/jobscript_info.py +13 -0
- hpcflow/sdk/submission/schedulers/__init__.py +60 -0
- hpcflow/sdk/submission/schedulers/direct.py +53 -0
- hpcflow/sdk/submission/schedulers/sge.py +45 -7
- hpcflow/sdk/submission/schedulers/slurm.py +45 -8
- hpcflow/sdk/submission/schedulers/utils.py +4 -0
- hpcflow/sdk/submission/shells/__init__.py +11 -1
- hpcflow/sdk/submission/shells/base.py +32 -1
- hpcflow/sdk/submission/shells/bash.py +36 -1
- hpcflow/sdk/submission/shells/os_version.py +18 -6
- hpcflow/sdk/submission/shells/powershell.py +22 -0
- hpcflow/sdk/submission/submission.py +88 -3
- hpcflow/sdk/typing.py +10 -1
- {hpcflow_new2-0.2.0a178.dist-info → hpcflow_new2-0.2.0a180.dist-info}/METADATA +1 -1
- {hpcflow_new2-0.2.0a178.dist-info → hpcflow_new2-0.2.0a180.dist-info}/RECORD +70 -70
- {hpcflow_new2-0.2.0a178.dist-info → hpcflow_new2-0.2.0a180.dist-info}/LICENSE +0 -0
- {hpcflow_new2-0.2.0a178.dist-info → hpcflow_new2-0.2.0a180.dist-info}/WHEEL +0 -0
- {hpcflow_new2-0.2.0a178.dist-info → hpcflow_new2-0.2.0a180.dist-info}/entry_points.txt +0 -0
@@ -1,8 +1,12 @@
|
|
1
|
+
"""
|
2
|
+
Class to hold the state that is waiting to be committed to disk.
|
3
|
+
"""
|
4
|
+
|
1
5
|
from __future__ import annotations
|
2
6
|
|
3
7
|
from collections import defaultdict
|
4
8
|
import contextlib
|
5
|
-
from dataclasses import dataclass, fields
|
9
|
+
from dataclasses import dataclass, field, fields
|
6
10
|
from datetime import datetime
|
7
11
|
|
8
12
|
from typing import Any, Dict, List, Optional, Tuple
|
@@ -15,26 +19,12 @@ class PendingChanges:
|
|
15
19
|
|
16
20
|
Parameters
|
17
21
|
----------
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
Keys are element IDs, and values are iteration IDs to add to that element.
|
25
|
-
add_elem_IDs
|
26
|
-
Keys are task IDs, and values are element IDs to add to that task.
|
27
|
-
add_parameters
|
28
|
-
Keys are parameter indices and values are tuples whose first element is data to
|
29
|
-
add and whose second element is the source dict for the new data.
|
30
|
-
update_param_sources
|
31
|
-
Keys are parameter indices and values are dict parameter sources to merge with
|
32
|
-
existing source of that parameter.
|
33
|
-
set_EAR_starts
|
34
|
-
Keys are EAR IDs and values are tuples of start time, and start dir snapshot.
|
35
|
-
set_EAR_ends
|
36
|
-
Keys are EAR IDs and values are tuples of end time, end dir snapshot, exit
|
37
|
-
code, and success boolean.
|
22
|
+
app: App
|
23
|
+
The main application context.
|
24
|
+
store: PersistentStore
|
25
|
+
The persistent store that owns this object
|
26
|
+
resource_map: CommitResourceMap
|
27
|
+
Map of resources, used when processing commits.
|
38
28
|
"""
|
39
29
|
|
40
30
|
def __init__(self, app, store, resource_map):
|
@@ -42,35 +32,64 @@ class PendingChanges:
|
|
42
32
|
self.store = store
|
43
33
|
self.resource_map = resource_map
|
44
34
|
|
35
|
+
#: Keys are new task IDs.
|
45
36
|
self.add_tasks: Dict[int, AnySTask] = None
|
37
|
+
#: Keys are loop IDs, values are loop descriptors.
|
46
38
|
self.add_loops: Dict[int, Dict] = None
|
39
|
+
#: Keys are submission IDs, values are submission descriptors.
|
47
40
|
self.add_submissions: Dict[int, Dict] = None
|
41
|
+
#: Keys are element IDs.
|
48
42
|
self.add_elements: Dict[int, AnySElement] = None
|
43
|
+
#: Keys are element iteration IDs.
|
49
44
|
self.add_elem_iters: Dict[int, AnySElementIter] = None
|
45
|
+
#: Keys are element action run IDs.
|
50
46
|
self.add_EARs: Dict[int, AnySEAR] = None
|
47
|
+
#: Keys are parameter indices and values are tuples whose first element is data
|
48
|
+
#: to add and whose second element is the source dict for the new data.
|
51
49
|
self.add_parameters: Dict[int, AnySParameter] = None
|
50
|
+
#: Workflow-related files (inputs, outputs) added to the persistent store.
|
52
51
|
self.add_files: List[Dict] = None
|
52
|
+
#: Template components to add.
|
53
53
|
self.add_template_components: Dict[str, Dict[str, Dict]] = None
|
54
|
+
#: Keys are element set IDs, values are descriptors.
|
54
55
|
self.add_element_sets: Dict[int, Dict] = None
|
55
56
|
|
57
|
+
#: Keys are task IDs, and values are element IDs to add to that task.
|
56
58
|
self.add_elem_IDs: Dict[int, List] = None
|
59
|
+
#: Keys are element IDs, and values are iteration IDs to add to that element.
|
57
60
|
self.add_elem_iter_IDs: Dict[int, List] = None
|
61
|
+
#: Keys are element iteration IDs, then EAR action index, and values are EAR IDs.
|
62
|
+
#: This is a list of EAR IDs to add to a given element iteration action.
|
58
63
|
self.add_elem_iter_EAR_IDs: Dict[int, Dict[int, List]] = None
|
64
|
+
#: Submission parts to add.
|
59
65
|
self.add_submission_parts: Dict[int, Dict[str, List[int]]] = None
|
60
66
|
|
67
|
+
#: IDs of EARs to mark as initialised.
|
61
68
|
self.set_EARs_initialised: List[int] = None
|
69
|
+
#: Submission IDs to attach to EARs.
|
62
70
|
self.set_EAR_submission_indices: Dict[int, int] = None
|
71
|
+
#: IDs of EARs to mark as skipped.
|
63
72
|
self.set_EAR_skips: List[int] = None
|
73
|
+
#: Keys are EAR IDs and values are tuples of start time, and start dir snapshot.
|
64
74
|
self.set_EAR_starts: Dict[int, Tuple[datetime, Dict], str] = None
|
75
|
+
#: Keys are EAR IDs and values are tuples of end time, end dir snapshot, exit
|
76
|
+
#: code, and success boolean.
|
65
77
|
self.set_EAR_ends: Dict[int, Tuple[datetime, Dict, int, bool]] = None
|
66
78
|
|
79
|
+
#: Keys are IDs of jobscripts.
|
67
80
|
self.set_js_metadata: Dict[int, Dict[int, Any]] = None
|
68
81
|
|
82
|
+
#: Keys are IDs of parameters to add or modify.
|
69
83
|
self.set_parameters: Dict[int, AnySParameter] = None
|
70
84
|
|
85
|
+
#: Keys are parameter indices and values are dict parameter sources to merge
|
86
|
+
#: with existing source of that parameter.
|
71
87
|
self.update_param_sources: Dict[int, Dict] = None
|
88
|
+
#: Keys are indices of loops, values are descriptions of what to update.
|
72
89
|
self.update_loop_indices: Dict[int, Dict[str, int]] = None
|
90
|
+
#: Keys are indices of loops, values are number of iterations.
|
73
91
|
self.update_loop_num_iters: Dict[int, int] = None
|
92
|
+
#: Keys are indices of loops, values are list of parent names.
|
74
93
|
self.update_loop_parents: Dict[int, List[str]] = None
|
75
94
|
|
76
95
|
self.reset(is_init=True) # set up initial data structures
|
@@ -106,6 +125,9 @@ class PendingChanges:
|
|
106
125
|
)
|
107
126
|
|
108
127
|
def where_pending(self) -> List[str]:
|
128
|
+
"""
|
129
|
+
Get the list of items for which there is some outstanding pending items.
|
130
|
+
"""
|
109
131
|
return [
|
110
132
|
k
|
111
133
|
for k, v in self.__dict__.items()
|
@@ -114,6 +136,9 @@ class PendingChanges:
|
|
114
136
|
|
115
137
|
@property
|
116
138
|
def logger(self):
|
139
|
+
"""
|
140
|
+
The logger.
|
141
|
+
"""
|
117
142
|
return self.app.persistence_logger
|
118
143
|
|
119
144
|
@TimeIt.decorator
|
@@ -149,7 +174,7 @@ class PendingChanges:
|
|
149
174
|
self.add_elem_IDs = {
|
150
175
|
k: v for k, v in self.add_elem_IDs.items() if k not in task_ids
|
151
176
|
}
|
152
|
-
self.
|
177
|
+
self._clear_add_tasks()
|
153
178
|
|
154
179
|
@TimeIt.decorator
|
155
180
|
def commit_loops(self) -> None:
|
@@ -170,7 +195,7 @@ class PendingChanges:
|
|
170
195
|
k: v for k, v in self.update_loop_parents.items() if k not in loop_ids
|
171
196
|
}
|
172
197
|
|
173
|
-
self.
|
198
|
+
self._clear_add_loops()
|
174
199
|
|
175
200
|
@TimeIt.decorator
|
176
201
|
def commit_submissions(self) -> None:
|
@@ -183,17 +208,23 @@ class PendingChanges:
|
|
183
208
|
f"commit: adding pending submissions with indices {sub_ids!r}"
|
184
209
|
)
|
185
210
|
self.store._append_submissions(subs)
|
186
|
-
self.
|
211
|
+
self._clear_add_submissions()
|
187
212
|
|
188
213
|
@TimeIt.decorator
|
189
214
|
def commit_submission_parts(self) -> None:
|
215
|
+
"""
|
216
|
+
Commit pending submission parts to disk.
|
217
|
+
"""
|
190
218
|
if self.add_submission_parts:
|
191
219
|
self.logger.debug(f"commit: adding pending submission parts")
|
192
220
|
self.store._append_submission_parts(self.add_submission_parts)
|
193
|
-
self.
|
221
|
+
self._clear_add_submission_parts()
|
194
222
|
|
195
223
|
@TimeIt.decorator
|
196
224
|
def commit_elem_IDs(self) -> None:
|
225
|
+
"""
|
226
|
+
Commit pending element ID updates to disk.
|
227
|
+
"""
|
197
228
|
# TODO: could be batched up?
|
198
229
|
for task_ID, elem_IDs in self.add_elem_IDs.items():
|
199
230
|
self.logger.debug(
|
@@ -201,10 +232,13 @@ class PendingChanges:
|
|
201
232
|
)
|
202
233
|
self.store._append_task_element_IDs(task_ID, elem_IDs)
|
203
234
|
self.store.task_cache.pop(task_ID, None) # invalidate cache
|
204
|
-
self.
|
235
|
+
self._clear_add_elem_IDs()
|
205
236
|
|
206
237
|
@TimeIt.decorator
|
207
238
|
def commit_elements(self) -> None:
|
239
|
+
"""
|
240
|
+
Commit pending elements to disk.
|
241
|
+
"""
|
208
242
|
if self.add_elements:
|
209
243
|
elems = self.store.get_elements(self.add_elements)
|
210
244
|
elem_ids = list(self.add_elements.keys())
|
@@ -214,18 +248,24 @@ class PendingChanges:
|
|
214
248
|
self.add_elem_iter_IDs = {
|
215
249
|
k: v for k, v in self.add_elem_iter_IDs.items() if k not in elem_ids
|
216
250
|
}
|
217
|
-
self.
|
251
|
+
self._clear_add_elements()
|
218
252
|
|
219
253
|
@TimeIt.decorator
|
220
254
|
def commit_element_sets(self) -> None:
|
255
|
+
"""
|
256
|
+
Commit pending element sets to disk.
|
257
|
+
"""
|
221
258
|
# TODO: could be batched up?
|
222
259
|
for task_id, es_js in self.add_element_sets.items():
|
223
260
|
self.logger.debug(f"commit: adding pending element sets.")
|
224
261
|
self.store._append_element_sets(task_id, es_js)
|
225
|
-
self.
|
262
|
+
self._clear_add_element_sets()
|
226
263
|
|
227
264
|
@TimeIt.decorator
|
228
265
|
def commit_elem_iter_IDs(self) -> None:
|
266
|
+
"""
|
267
|
+
Commit pending element iteration ID updates to disk.
|
268
|
+
"""
|
229
269
|
# TODO: could be batched up?
|
230
270
|
for elem_ID, iter_IDs in self.add_elem_iter_IDs.items():
|
231
271
|
self.logger.debug(
|
@@ -234,10 +274,13 @@ class PendingChanges:
|
|
234
274
|
)
|
235
275
|
self.store._append_elem_iter_IDs(elem_ID, iter_IDs)
|
236
276
|
self.store.element_cache.pop(elem_ID, None) # invalidate cache
|
237
|
-
self.
|
277
|
+
self._clear_add_elem_iter_IDs()
|
238
278
|
|
239
279
|
@TimeIt.decorator
|
240
280
|
def commit_elem_iters(self) -> None:
|
281
|
+
"""
|
282
|
+
Commit pending element iterations to disk.
|
283
|
+
"""
|
241
284
|
if self.add_elem_iters:
|
242
285
|
iters = self.store.get_element_iterations(self.add_elem_iters.keys())
|
243
286
|
iter_ids = list(self.add_elem_iters.keys())
|
@@ -253,10 +296,13 @@ class PendingChanges:
|
|
253
296
|
self.set_EARs_initialised = [
|
254
297
|
i for i in self.set_EARs_initialised if i not in iter_ids
|
255
298
|
]
|
256
|
-
self.
|
299
|
+
self._clear_add_elem_iters()
|
257
300
|
|
258
301
|
@TimeIt.decorator
|
259
302
|
def commit_elem_iter_EAR_IDs(self) -> None:
|
303
|
+
"""
|
304
|
+
Commit pending element action run ID updates to disk.
|
305
|
+
"""
|
260
306
|
# TODO: could be batched up?
|
261
307
|
for iter_ID, act_EAR_IDs in self.add_elem_iter_EAR_IDs.items():
|
262
308
|
self.logger.debug(
|
@@ -266,10 +312,13 @@ class PendingChanges:
|
|
266
312
|
for act_idx, EAR_IDs in act_EAR_IDs.items():
|
267
313
|
self.store._append_elem_iter_EAR_IDs(iter_ID, act_idx, EAR_IDs)
|
268
314
|
self.store.element_iter_cache.pop(iter_ID, None) # invalidate cache
|
269
|
-
self.
|
315
|
+
self._clear_add_elem_iter_EAR_IDs()
|
270
316
|
|
271
317
|
@TimeIt.decorator
|
272
318
|
def commit_EARs(self) -> None:
|
319
|
+
"""
|
320
|
+
Commit pending element action runs to disk.
|
321
|
+
"""
|
273
322
|
if self.add_EARs:
|
274
323
|
EARs = self.store.get_EARs(self.add_EARs)
|
275
324
|
EAR_ids = list(self.add_EARs.keys())
|
@@ -291,10 +340,13 @@ class PendingChanges:
|
|
291
340
|
k: v for k, v in self.set_EAR_ends.items() if k not in EAR_ids
|
292
341
|
}
|
293
342
|
|
294
|
-
self.
|
343
|
+
self._clear_add_EARs()
|
295
344
|
|
296
345
|
@TimeIt.decorator
|
297
346
|
def commit_EARs_initialised(self) -> None:
|
347
|
+
"""
|
348
|
+
Commit pending element action run init state updates to disk.
|
349
|
+
"""
|
298
350
|
if self.set_EARs_initialised:
|
299
351
|
iter_ids = self.set_EARs_initialised
|
300
352
|
self.logger.debug(
|
@@ -305,10 +357,13 @@ class PendingChanges:
|
|
305
357
|
for i in iter_ids:
|
306
358
|
self.store._update_elem_iter_EARs_initialised(i)
|
307
359
|
self.store.element_iter_cache.pop(i, None) # invalidate cache
|
308
|
-
self.
|
360
|
+
self._clear_set_EARs_initialised()
|
309
361
|
|
310
362
|
@TimeIt.decorator
|
311
363
|
def commit_EAR_submission_indices(self) -> None:
|
364
|
+
"""
|
365
|
+
Commit pending element action run submission index updates to disk.
|
366
|
+
"""
|
312
367
|
if self.set_EAR_submission_indices:
|
313
368
|
self.logger.debug(
|
314
369
|
f"commit: updating submission indices: "
|
@@ -317,10 +372,13 @@ class PendingChanges:
|
|
317
372
|
self.store._update_EAR_submission_indices(self.set_EAR_submission_indices)
|
318
373
|
for EAR_ID_i in self.set_EAR_submission_indices.keys():
|
319
374
|
self.store.EAR_cache.pop(EAR_ID_i, None) # invalidate cache
|
320
|
-
self.
|
375
|
+
self._clear_set_EAR_submission_indices()
|
321
376
|
|
322
377
|
@TimeIt.decorator
|
323
378
|
def commit_EAR_starts(self) -> None:
|
379
|
+
"""
|
380
|
+
Commit pending element action run start information to disk.
|
381
|
+
"""
|
324
382
|
# TODO: could be batched up?
|
325
383
|
for EAR_id, (time, snap, hostname) in self.set_EAR_starts.items():
|
326
384
|
self.logger.debug(
|
@@ -329,10 +387,13 @@ class PendingChanges:
|
|
329
387
|
)
|
330
388
|
self.store._update_EAR_start(EAR_id, time, snap, hostname)
|
331
389
|
self.store.EAR_cache.pop(EAR_id, None) # invalidate cache
|
332
|
-
self.
|
390
|
+
self._clear_set_EAR_starts()
|
333
391
|
|
334
392
|
@TimeIt.decorator
|
335
393
|
def commit_EAR_ends(self) -> None:
|
394
|
+
"""
|
395
|
+
Commit pending element action run finish information to disk.
|
396
|
+
"""
|
336
397
|
# TODO: could be batched up?
|
337
398
|
for EAR_id, (time, snap, ext, suc) in self.set_EAR_ends.items():
|
338
399
|
self.logger.debug(
|
@@ -341,25 +402,31 @@ class PendingChanges:
|
|
341
402
|
)
|
342
403
|
self.store._update_EAR_end(EAR_id, time, snap, ext, suc)
|
343
404
|
self.store.EAR_cache.pop(EAR_id, None) # invalidate cache
|
344
|
-
self.
|
405
|
+
self._clear_set_EAR_ends()
|
345
406
|
|
346
407
|
@TimeIt.decorator
|
347
408
|
def commit_EAR_skips(self) -> None:
|
409
|
+
"""
|
410
|
+
Commit pending element action skip flags to disk.
|
411
|
+
"""
|
348
412
|
# TODO: could be batched up?
|
349
413
|
for EAR_id in self.set_EAR_skips:
|
350
414
|
self.logger.debug(f"commit: setting EAR ID {EAR_id!r} as skipped.")
|
351
415
|
self.store._update_EAR_skip(EAR_id)
|
352
416
|
self.store.EAR_cache.pop(EAR_id, None) # invalidate cache
|
353
|
-
self.
|
417
|
+
self._clear_set_EAR_skips()
|
354
418
|
|
355
419
|
@TimeIt.decorator
|
356
420
|
def commit_js_metadata(self) -> None:
|
421
|
+
"""
|
422
|
+
Commit pending jobscript metadata changes to disk.
|
423
|
+
"""
|
357
424
|
if self.set_js_metadata:
|
358
425
|
self.logger.debug(
|
359
426
|
f"commit: setting jobscript metadata: {self.set_js_metadata!r}"
|
360
427
|
)
|
361
428
|
self.store._update_js_metadata(self.set_js_metadata)
|
362
|
-
self.
|
429
|
+
self._clear_set_js_metadata()
|
363
430
|
|
364
431
|
@TimeIt.decorator
|
365
432
|
def commit_parameters(self) -> None:
|
@@ -369,7 +436,7 @@ class PendingChanges:
|
|
369
436
|
param_ids = list(self.add_parameters.keys())
|
370
437
|
self.logger.debug(f"commit: adding pending parameters IDs: {param_ids!r}")
|
371
438
|
self.store._append_parameters(params)
|
372
|
-
self.
|
439
|
+
self._clear_add_parameters()
|
373
440
|
|
374
441
|
if self.set_parameters:
|
375
442
|
param_ids = list(self.set_parameters.keys())
|
@@ -378,7 +445,7 @@ class PendingChanges:
|
|
378
445
|
for id_i in param_ids:
|
379
446
|
self.store.parameter_cache.pop(id_i, None)
|
380
447
|
|
381
|
-
self.
|
448
|
+
self._clear_set_parameters()
|
382
449
|
|
383
450
|
@TimeIt.decorator
|
384
451
|
def commit_files(self) -> None:
|
@@ -386,14 +453,17 @@ class PendingChanges:
|
|
386
453
|
if self.add_files:
|
387
454
|
self.logger.debug(f"commit: adding pending files to the files directory.")
|
388
455
|
self.store._append_files(self.add_files)
|
389
|
-
self.
|
456
|
+
self._clear_add_files()
|
390
457
|
|
391
458
|
@TimeIt.decorator
|
392
459
|
def commit_template_components(self) -> None:
|
460
|
+
"""
|
461
|
+
Commit pending template components to disk.
|
462
|
+
"""
|
393
463
|
if self.add_template_components:
|
394
464
|
self.logger.debug(f"commit: adding template components.")
|
395
465
|
self.store._update_template_components(self.store.get_template_components())
|
396
|
-
self.
|
466
|
+
self._clear_add_template_components()
|
397
467
|
|
398
468
|
@TimeIt.decorator
|
399
469
|
def commit_param_sources(self) -> None:
|
@@ -404,7 +474,7 @@ class PendingChanges:
|
|
404
474
|
self.store._update_parameter_sources(self.update_param_sources)
|
405
475
|
for id_i in param_ids:
|
406
476
|
self.store.param_sources_cache.pop(id_i, None) # invalidate cache
|
407
|
-
self.
|
477
|
+
self._clear_update_param_sources()
|
408
478
|
|
409
479
|
@TimeIt.decorator
|
410
480
|
def commit_loop_indices(self) -> None:
|
@@ -417,7 +487,7 @@ class PendingChanges:
|
|
417
487
|
)
|
418
488
|
self.store._update_loop_index(iter_ID, loop_idx)
|
419
489
|
self.store.element_iter_cache.pop(iter_ID, None) # invalidate cache
|
420
|
-
self.
|
490
|
+
self._clear_update_loop_indices()
|
421
491
|
|
422
492
|
@TimeIt.decorator
|
423
493
|
def commit_loop_num_iters(self) -> None:
|
@@ -427,7 +497,7 @@ class PendingChanges:
|
|
427
497
|
f"commit: updating loop {index!r} number of iterations to {num_iters!r}."
|
428
498
|
)
|
429
499
|
self.store._update_loop_num_iters(index, num_iters)
|
430
|
-
self.
|
500
|
+
self._clear_update_loop_num_iters()
|
431
501
|
|
432
502
|
@TimeIt.decorator
|
433
503
|
def commit_loop_parents(self) -> None:
|
@@ -435,81 +505,81 @@ class PendingChanges:
|
|
435
505
|
for index, parents in self.update_loop_parents.items():
|
436
506
|
self.logger.debug(f"commit: updating loop {index!r} parents to {parents!r}.")
|
437
507
|
self.store._update_loop_parents(index, parents)
|
438
|
-
self.
|
508
|
+
self._clear_update_loop_parents()
|
439
509
|
|
440
|
-
def
|
510
|
+
def _clear_add_tasks(self):
|
441
511
|
self.add_tasks = {}
|
442
512
|
|
443
|
-
def
|
513
|
+
def _clear_add_loops(self):
|
444
514
|
self.add_loops = {}
|
445
515
|
|
446
|
-
def
|
516
|
+
def _clear_add_submissions(self):
|
447
517
|
self.add_submissions = {}
|
448
518
|
|
449
|
-
def
|
519
|
+
def _clear_add_submission_parts(self):
|
450
520
|
self.add_submission_parts = defaultdict(dict)
|
451
521
|
|
452
|
-
def
|
522
|
+
def _clear_add_elements(self):
|
453
523
|
self.add_elements = {}
|
454
524
|
|
455
|
-
def
|
525
|
+
def _clear_add_element_sets(self):
|
456
526
|
self.add_element_sets = defaultdict(list)
|
457
527
|
|
458
|
-
def
|
528
|
+
def _clear_add_elem_iters(self):
|
459
529
|
self.add_elem_iters = {}
|
460
530
|
|
461
|
-
def
|
531
|
+
def _clear_add_EARs(self):
|
462
532
|
self.add_EARs = {}
|
463
533
|
|
464
|
-
def
|
534
|
+
def _clear_add_elem_IDs(self):
|
465
535
|
self.add_elem_IDs = defaultdict(list)
|
466
536
|
|
467
|
-
def
|
537
|
+
def _clear_add_elem_iter_IDs(self):
|
468
538
|
self.add_elem_iter_IDs = defaultdict(list)
|
469
539
|
|
470
|
-
def
|
540
|
+
def _clear_add_elem_iter_EAR_IDs(self):
|
471
541
|
self.add_elem_iter_EAR_IDs = defaultdict(lambda: defaultdict(list))
|
472
542
|
|
473
|
-
def
|
543
|
+
def _clear_set_EARs_initialised(self):
|
474
544
|
self.set_EARs_initialised = []
|
475
545
|
|
476
|
-
def
|
546
|
+
def _clear_set_EAR_submission_indices(self):
|
477
547
|
self.set_EAR_submission_indices = {}
|
478
548
|
|
479
|
-
def
|
549
|
+
def _clear_set_EAR_starts(self):
|
480
550
|
self.set_EAR_starts = {}
|
481
551
|
|
482
|
-
def
|
552
|
+
def _clear_set_EAR_ends(self):
|
483
553
|
self.set_EAR_ends = {}
|
484
554
|
|
485
|
-
def
|
555
|
+
def _clear_set_EAR_skips(self):
|
486
556
|
self.set_EAR_skips = []
|
487
557
|
|
488
|
-
def
|
558
|
+
def _clear_set_js_metadata(self):
|
489
559
|
self.set_js_metadata = defaultdict(lambda: defaultdict(dict))
|
490
560
|
|
491
|
-
def
|
561
|
+
def _clear_add_parameters(self):
|
492
562
|
self.add_parameters = {}
|
493
563
|
|
494
|
-
def
|
564
|
+
def _clear_add_files(self):
|
495
565
|
self.add_files = []
|
496
566
|
|
497
|
-
def
|
567
|
+
def _clear_add_template_components(self):
|
498
568
|
self.add_template_components = defaultdict(dict)
|
499
569
|
|
500
|
-
def
|
570
|
+
def _clear_set_parameters(self):
|
501
571
|
self.set_parameters = {}
|
502
572
|
|
503
|
-
def
|
573
|
+
def _clear_update_param_sources(self):
|
504
574
|
self.update_param_sources = {}
|
505
575
|
|
506
|
-
def
|
576
|
+
def _clear_update_loop_indices(self):
|
507
577
|
self.update_loop_indices = defaultdict(dict)
|
508
578
|
|
509
|
-
def
|
579
|
+
def _clear_update_loop_num_iters(self):
|
510
580
|
self.update_loop_num_iters = {}
|
511
581
|
|
512
|
-
def
|
582
|
+
def _clear_update_loop_parents(self):
|
513
583
|
self.update_loop_parents = {}
|
514
584
|
|
515
585
|
def reset(self, is_init=False) -> None:
|
@@ -522,87 +592,127 @@ class PendingChanges:
|
|
522
592
|
if not is_init:
|
523
593
|
self.logger.info("resetting pending changes.")
|
524
594
|
|
525
|
-
self.
|
526
|
-
self.
|
527
|
-
self.
|
528
|
-
self.
|
529
|
-
self.
|
530
|
-
self.
|
531
|
-
self.
|
532
|
-
self.
|
595
|
+
self._clear_add_tasks()
|
596
|
+
self._clear_add_loops()
|
597
|
+
self._clear_add_submissions()
|
598
|
+
self._clear_add_submission_parts()
|
599
|
+
self._clear_add_elements()
|
600
|
+
self._clear_add_element_sets()
|
601
|
+
self._clear_add_elem_iters()
|
602
|
+
self._clear_add_EARs()
|
533
603
|
|
534
|
-
self.
|
535
|
-
self.
|
536
|
-
self.
|
537
|
-
self.
|
604
|
+
self._clear_set_EARs_initialised()
|
605
|
+
self._clear_add_elem_IDs()
|
606
|
+
self._clear_add_elem_iter_IDs()
|
607
|
+
self._clear_add_elem_iter_EAR_IDs()
|
538
608
|
|
539
|
-
self.
|
540
|
-
self.
|
541
|
-
self.
|
609
|
+
self._clear_add_parameters()
|
610
|
+
self._clear_add_files()
|
611
|
+
self._clear_add_template_components()
|
542
612
|
|
543
|
-
self.
|
544
|
-
self.
|
545
|
-
self.
|
546
|
-
self.
|
613
|
+
self._clear_set_EAR_submission_indices()
|
614
|
+
self._clear_set_EAR_starts()
|
615
|
+
self._clear_set_EAR_ends()
|
616
|
+
self._clear_set_EAR_skips()
|
547
617
|
|
548
|
-
self.
|
549
|
-
self.
|
618
|
+
self._clear_set_js_metadata()
|
619
|
+
self._clear_set_parameters()
|
550
620
|
|
551
|
-
self.
|
552
|
-
self.
|
553
|
-
self.
|
554
|
-
self.
|
621
|
+
self._clear_update_param_sources()
|
622
|
+
self._clear_update_loop_indices()
|
623
|
+
self._clear_update_loop_num_iters()
|
624
|
+
self._clear_update_loop_parents()
|
555
625
|
|
556
626
|
|
557
627
|
@dataclass
|
558
628
|
class CommitResourceMap:
|
559
|
-
"""
|
560
|
-
|
629
|
+
"""
|
630
|
+
Map of :py:class:`PendingChanges` commit method names to store resource labels,
|
631
|
+
representing the store resources required by each ``commit_*`` method, for a given
|
632
|
+
:py:class:`~.PersistentStore`.
|
561
633
|
|
562
|
-
When
|
563
|
-
"update" mode, for each
|
634
|
+
When :py:meth:`PendingChanges.commit_all` is called, the resources specified will be
|
635
|
+
opened in "update" mode, for each ``commit_*`` method.
|
564
636
|
|
637
|
+
Notes
|
638
|
+
-----
|
639
|
+
Normally only of interest to implementations of persistent stores.
|
565
640
|
"""
|
566
641
|
|
642
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_tasks`.
|
567
643
|
commit_tasks: Optional[Tuple[str]] = tuple()
|
644
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_loops`.
|
568
645
|
commit_loops: Optional[Tuple[str]] = tuple()
|
646
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_submissions`.
|
569
647
|
commit_submissions: Optional[Tuple[str]] = tuple()
|
648
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_submission_parts`.
|
570
649
|
commit_submission_parts: Optional[Tuple[str]] = tuple()
|
650
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_elem_IDs`.
|
571
651
|
commit_elem_IDs: Optional[Tuple[str]] = tuple()
|
652
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_elements`.
|
572
653
|
commit_elements: Optional[Tuple[str]] = tuple()
|
654
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_element_sets`.
|
573
655
|
commit_element_sets: Optional[Tuple[str]] = tuple()
|
656
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_elem_iter_IDs`.
|
574
657
|
commit_elem_iter_IDs: Optional[Tuple[str]] = tuple()
|
658
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_elem_iters`.
|
575
659
|
commit_elem_iters: Optional[Tuple[str]] = tuple()
|
660
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_elem_iter_EAR_IDs`.
|
576
661
|
commit_elem_iter_EAR_IDs: Optional[Tuple[str]] = tuple()
|
662
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_EARs_initialised`.
|
577
663
|
commit_EARs_initialised: Optional[Tuple[str]] = tuple()
|
664
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_EARs`.
|
578
665
|
commit_EARs: Optional[Tuple[str]] = tuple()
|
666
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_EAR_submission_indices`.
|
579
667
|
commit_EAR_submission_indices: Optional[Tuple[str]] = tuple()
|
668
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_EAR_skips`.
|
580
669
|
commit_EAR_skips: Optional[Tuple[str]] = tuple()
|
670
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_EAR_starts`.
|
581
671
|
commit_EAR_starts: Optional[Tuple[str]] = tuple()
|
672
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_EAR_ends`.
|
582
673
|
commit_EAR_ends: Optional[Tuple[str]] = tuple()
|
674
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_js_metadata`.
|
583
675
|
commit_js_metadata: Optional[Tuple[str]] = tuple()
|
676
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_parameters`.
|
584
677
|
commit_parameters: Optional[Tuple[str]] = tuple()
|
678
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_files`.
|
585
679
|
commit_files: Optional[Tuple[str]] = tuple()
|
680
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_template_components`.
|
586
681
|
commit_template_components: Optional[Tuple[str]] = tuple()
|
682
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_param_sources`.
|
587
683
|
commit_param_sources: Optional[Tuple[str]] = tuple()
|
684
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_loop_indices`.
|
588
685
|
commit_loop_indices: Optional[Tuple[str]] = tuple()
|
686
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_loop_num_iters`.
|
589
687
|
commit_loop_num_iters: Optional[Tuple[str]] = tuple()
|
688
|
+
#: Resources for :py:meth:`~.PendingChanges.commit_loop_parents`.
|
590
689
|
commit_loop_parents: Optional[Tuple[str]] = tuple()
|
690
|
+
#: A dict whose keys are tuples of resource labels and whose values are lists
|
691
|
+
#: of :py:class:`PendingChanges` commit method names that require those resources.
|
692
|
+
#:
|
693
|
+
#: This grouping allows us to batch up commit methods by resource requirements,
|
694
|
+
#: which in turn means we can potentially minimise, e.g., the number of network
|
695
|
+
#: requests.
|
696
|
+
groups: Dict[Tuple[str], List[str]] = field(init=False, repr=False, compare=False)
|
591
697
|
|
592
698
|
def __post_init__(self):
|
593
|
-
self.groups = self.
|
699
|
+
self.groups = self._group_by_resource()
|
594
700
|
|
595
|
-
def
|
596
|
-
"""
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
in turn means we can potentially minimise e.g. the number of network requests.
|
701
|
+
def _group_by_resource(self) -> Dict[Tuple[str], List[str]]:
|
702
|
+
"""
|
703
|
+
Get a dict whose keys are tuples of resource labels and whose values are
|
704
|
+
lists of :py:class:`PendingChanges` commit method names that require those
|
705
|
+
resource.
|
601
706
|
|
707
|
+
This grouping allows us to batch up commit methods by resource requirements,
|
708
|
+
which in turn means we can potentially minimise e.g. the number of network
|
709
|
+
requests.
|
602
710
|
"""
|
603
711
|
groups = {}
|
604
712
|
cur_res_group = None
|
605
713
|
for fld in fields(self):
|
714
|
+
if not fld.name.startswith("commit_"):
|
715
|
+
continue
|
606
716
|
res_labels = getattr(self, fld.name)
|
607
717
|
|
608
718
|
if not cur_res_group:
|