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
hpcflow/sdk/core/workflow.py
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
"""
|
2
|
+
Main workflow model.
|
3
|
+
"""
|
4
|
+
|
1
5
|
from __future__ import annotations
|
2
6
|
from collections import defaultdict
|
3
7
|
from contextlib import contextmanager
|
@@ -90,20 +94,32 @@ class WorkflowTemplate(JSONLike):
|
|
90
94
|
|
91
95
|
Parameters
|
92
96
|
----------
|
93
|
-
name
|
97
|
+
name:
|
94
98
|
A string name for the workflow. By default this name will be used in combination
|
95
99
|
with a date-time stamp when generating a persistent workflow from the template.
|
96
|
-
tasks
|
100
|
+
tasks: list[~hpcflow.app.Task]
|
97
101
|
A list of Task objects to include in the workflow.
|
98
|
-
loops
|
102
|
+
loops: list[~hpcflow.app.Loop]
|
99
103
|
A list of Loop objects to include in the workflow.
|
100
|
-
|
104
|
+
workflow:
|
105
|
+
The associated concrete workflow.
|
106
|
+
resources: dict[str, dict] | list[~hpcflow.app.ResourceSpec] | ~hpcflow.app.ResourceList
|
101
107
|
Template-level resources to apply to all tasks as default values. This can be a
|
102
108
|
dict that maps action scopes to resources (e.g. `{{"any": {{"num_cores": 2}}}}`)
|
103
109
|
or a list of `ResourceSpec` objects, or a `ResourceList` object.
|
104
|
-
|
110
|
+
environments:
|
111
|
+
The execution environments to use.
|
112
|
+
env_presets:
|
113
|
+
The environment presets to use.
|
114
|
+
source_file:
|
115
|
+
The file this was derived from.
|
116
|
+
store_kwargs:
|
117
|
+
Additional arguments to pass to the persistent data store constructor.
|
118
|
+
merge_resources:
|
105
119
|
If True, merge template-level `resources` into element set resources. If False,
|
106
120
|
template-level resources are ignored.
|
121
|
+
merge_envs:
|
122
|
+
Whether to merge the environemtns into task resources.
|
107
123
|
"""
|
108
124
|
|
109
125
|
_app_attr = "app"
|
@@ -129,17 +145,29 @@ class WorkflowTemplate(JSONLike):
|
|
129
145
|
),
|
130
146
|
)
|
131
147
|
|
148
|
+
#: A string name for the workflow.
|
132
149
|
name: str
|
150
|
+
#: Documentation information.
|
133
151
|
doc: Optional[Union[List[str], str]] = field(repr=False, default=None)
|
152
|
+
#: A list of Task objects to include in the workflow.
|
134
153
|
tasks: Optional[List[app.Task]] = field(default_factory=lambda: [])
|
154
|
+
#: A list of Loop objects to include in the workflow.
|
135
155
|
loops: Optional[List[app.Loop]] = field(default_factory=lambda: [])
|
156
|
+
#: The associated concrete workflow.
|
136
157
|
workflow: Optional[app.Workflow] = None
|
158
|
+
#: Template-level resources to apply to all tasks as default values.
|
137
159
|
resources: Optional[Dict[str, Dict]] = None
|
160
|
+
#: The execution environments to use.
|
138
161
|
environments: Optional[Dict[str, Dict[str, Any]]] = None
|
162
|
+
#: The environment presets to use.
|
139
163
|
env_presets: Optional[Union[str, List[str]]] = None
|
164
|
+
#: The file this was derived from.
|
140
165
|
source_file: Optional[str] = field(default=None, compare=False)
|
166
|
+
#: Additional arguments to pass to the persistent data store constructor.
|
141
167
|
store_kwargs: Optional[Dict] = field(default_factory=lambda: {})
|
168
|
+
#: Whether to merge template-level `resources` into element set resources.
|
142
169
|
merge_resources: Optional[bool] = True
|
170
|
+
#: Whether to merge the environemtns into task resources.
|
143
171
|
merge_envs: Optional[bool] = True
|
144
172
|
|
145
173
|
def __post_init__(self):
|
@@ -455,6 +483,8 @@ class WorkflowTemplate(JSONLike):
|
|
455
483
|
|
456
484
|
def resolve_fsspec(path: PathLike, **kwargs) -> Tuple[Any, str, str]:
|
457
485
|
"""
|
486
|
+
Decide how to handle a particular virtual path.
|
487
|
+
|
458
488
|
Parameters
|
459
489
|
----------
|
460
490
|
kwargs
|
@@ -486,6 +516,23 @@ def resolve_fsspec(path: PathLike, **kwargs) -> Tuple[Any, str, str]:
|
|
486
516
|
|
487
517
|
|
488
518
|
class Workflow:
|
519
|
+
"""
|
520
|
+
A concrete workflow.
|
521
|
+
|
522
|
+
Parameters
|
523
|
+
----------
|
524
|
+
workflow_ref:
|
525
|
+
Either the path to a persistent workflow, or an integer that will interpreted
|
526
|
+
as the local ID of a workflow submission, as reported by the app `show`
|
527
|
+
command.
|
528
|
+
store_fmt:
|
529
|
+
The format of persistent store to use. Used to select the store manager class.
|
530
|
+
fs_kwargs:
|
531
|
+
Additional arguments to pass when resolving a virtual workflow reference.
|
532
|
+
kwargs:
|
533
|
+
For compatibility during pre-stable development phase.
|
534
|
+
"""
|
535
|
+
|
489
536
|
_app_attr = "app"
|
490
537
|
_default_ts_fmt = r"%Y-%m-%d %H:%M:%S.%f"
|
491
538
|
_default_ts_name_fmt = r"%Y-%m-%d_%H%M%S"
|
@@ -499,17 +546,6 @@ class Workflow:
|
|
499
546
|
fs_kwargs: Optional[Dict] = None,
|
500
547
|
**kwargs,
|
501
548
|
):
|
502
|
-
"""
|
503
|
-
Parameters
|
504
|
-
----------
|
505
|
-
workflow_ref
|
506
|
-
Either the path to a persistent workflow, or an integer that will interpreted
|
507
|
-
as the local ID of a workflow submission, as reported by the app `show`
|
508
|
-
command.
|
509
|
-
kwargs
|
510
|
-
For compatibility during pre-stable development phase.
|
511
|
-
"""
|
512
|
-
|
513
549
|
if isinstance(workflow_ref, int):
|
514
550
|
path = self.app._get_workflow_path_from_local_ID(workflow_ref)
|
515
551
|
else:
|
@@ -546,15 +582,19 @@ class Workflow:
|
|
546
582
|
|
547
583
|
@property
|
548
584
|
def name(self):
|
549
|
-
"""
|
550
|
-
|
585
|
+
"""
|
586
|
+
The name of the workflow.
|
587
|
+
|
588
|
+
The workflow name may be different from the template name, as it includes the
|
589
|
+
creation date-timestamp if generated.
|
590
|
+
"""
|
551
591
|
if not self._name:
|
552
592
|
self._name = self._store.get_name()
|
553
593
|
return self._name
|
554
594
|
|
555
595
|
@property
|
556
596
|
def url(self):
|
557
|
-
"""
|
597
|
+
"""An fsspec URL for this workflow."""
|
558
598
|
if self._store.fs.protocol == "zip":
|
559
599
|
return self._store.fs.of.path
|
560
600
|
elif self._store.fs.protocol == "file":
|
@@ -564,10 +604,16 @@ class Workflow:
|
|
564
604
|
|
565
605
|
@property
|
566
606
|
def store_format(self):
|
607
|
+
"""
|
608
|
+
The format of the workflow's persistent store.
|
609
|
+
"""
|
567
610
|
return self._store._name
|
568
611
|
|
569
612
|
@property
|
570
613
|
def num_tasks(self) -> int:
|
614
|
+
"""
|
615
|
+
The number of tasks in the workflow.
|
616
|
+
"""
|
571
617
|
return len(self.tasks)
|
572
618
|
|
573
619
|
@classmethod
|
@@ -588,28 +634,28 @@ class Workflow:
|
|
588
634
|
|
589
635
|
Parameters
|
590
636
|
----------
|
591
|
-
template
|
637
|
+
template:
|
592
638
|
The WorkflowTemplate object to make persistent.
|
593
|
-
path
|
639
|
+
path:
|
594
640
|
The directory in which the workflow will be generated. The current directory
|
595
641
|
if not specified.
|
596
|
-
name
|
642
|
+
name:
|
597
643
|
The name of the workflow. If specified, the workflow directory will be `path`
|
598
644
|
joined with `name`. If not specified the `WorkflowTemplate` name will be used,
|
599
645
|
in combination with a date-timestamp.
|
600
|
-
overwrite
|
646
|
+
overwrite:
|
601
647
|
If True and the workflow directory (`path` + `name`) already exists, the
|
602
648
|
existing directory will be overwritten.
|
603
|
-
store
|
649
|
+
store:
|
604
650
|
The persistent store to use for this workflow.
|
605
|
-
ts_fmt
|
651
|
+
ts_fmt:
|
606
652
|
The datetime format to use for storing datetimes. Datetimes are always stored
|
607
653
|
in UTC (because Numpy does not store time zone info), so this should not
|
608
654
|
include a time zone name.
|
609
|
-
ts_name_fmt
|
655
|
+
ts_name_fmt:
|
610
656
|
The datetime format to use when generating the workflow name, where it
|
611
657
|
includes a timestamp.
|
612
|
-
store_kwargs
|
658
|
+
store_kwargs:
|
613
659
|
Keyword arguments to pass to the store's `write_empty_workflow` method.
|
614
660
|
"""
|
615
661
|
if status:
|
@@ -673,30 +719,30 @@ class Workflow:
|
|
673
719
|
|
674
720
|
Parameters
|
675
721
|
----------
|
676
|
-
YAML_path
|
722
|
+
YAML_path:
|
677
723
|
The path to a workflow template in the YAML file format.
|
678
|
-
path
|
724
|
+
path:
|
679
725
|
The directory in which the workflow will be generated. The current directory
|
680
726
|
if not specified.
|
681
|
-
name
|
727
|
+
name:
|
682
728
|
The name of the workflow. If specified, the workflow directory will be `path`
|
683
729
|
joined with `name`. If not specified the `WorkflowTemplate` name will be used,
|
684
730
|
in combination with a date-timestamp.
|
685
|
-
overwrite
|
731
|
+
overwrite:
|
686
732
|
If True and the workflow directory (`path` + `name`) already exists, the
|
687
733
|
existing directory will be overwritten.
|
688
|
-
store
|
734
|
+
store:
|
689
735
|
The persistent store to use for this workflow.
|
690
|
-
ts_fmt
|
736
|
+
ts_fmt:
|
691
737
|
The datetime format to use for storing datetimes. Datetimes are always stored
|
692
738
|
in UTC (because Numpy does not store time zone info), so this should not
|
693
739
|
include a time zone name.
|
694
|
-
ts_name_fmt
|
740
|
+
ts_name_fmt:
|
695
741
|
The datetime format to use when generating the workflow name, where it
|
696
742
|
includes a timestamp.
|
697
|
-
store_kwargs
|
743
|
+
store_kwargs:
|
698
744
|
Keyword arguments to pass to the store's `write_empty_workflow` method.
|
699
|
-
variables
|
745
|
+
variables:
|
700
746
|
String variables to substitute in the file given by `YAML_path`.
|
701
747
|
"""
|
702
748
|
template = cls.app.WorkflowTemplate.from_YAML_file(
|
@@ -731,30 +777,30 @@ class Workflow:
|
|
731
777
|
|
732
778
|
Parameters
|
733
779
|
----------
|
734
|
-
YAML_str
|
780
|
+
YAML_str:
|
735
781
|
The YAML string containing a workflow template parametrisation.
|
736
|
-
path
|
782
|
+
path:
|
737
783
|
The directory in which the workflow will be generated. The current directory
|
738
784
|
if not specified.
|
739
|
-
name
|
785
|
+
name:
|
740
786
|
The name of the workflow. If specified, the workflow directory will be `path`
|
741
787
|
joined with `name`. If not specified the `WorkflowTemplate` name will be used,
|
742
788
|
in combination with a date-timestamp.
|
743
|
-
overwrite
|
789
|
+
overwrite:
|
744
790
|
If True and the workflow directory (`path` + `name`) already exists, the
|
745
791
|
existing directory will be overwritten.
|
746
|
-
store
|
792
|
+
store:
|
747
793
|
The persistent store to use for this workflow.
|
748
|
-
ts_fmt
|
794
|
+
ts_fmt:
|
749
795
|
The datetime format to use for storing datetimes. Datetimes are always stored
|
750
796
|
in UTC (because Numpy does not store time zone info), so this should not
|
751
797
|
include a time zone name.
|
752
|
-
ts_name_fmt
|
798
|
+
ts_name_fmt:
|
753
799
|
The datetime format to use when generating the workflow name, where it
|
754
800
|
includes a timestamp.
|
755
|
-
store_kwargs
|
801
|
+
store_kwargs:
|
756
802
|
Keyword arguments to pass to the store's `write_empty_workflow` method.
|
757
|
-
variables
|
803
|
+
variables:
|
758
804
|
String variables to substitute in the string `YAML_str`.
|
759
805
|
"""
|
760
806
|
template = cls.app.WorkflowTemplate.from_YAML_string(
|
@@ -790,30 +836,30 @@ class Workflow:
|
|
790
836
|
|
791
837
|
Parameters
|
792
838
|
----------
|
793
|
-
JSON_path
|
839
|
+
JSON_path:
|
794
840
|
The path to a workflow template in the JSON file format.
|
795
|
-
path
|
841
|
+
path:
|
796
842
|
The directory in which the workflow will be generated. The current directory
|
797
843
|
if not specified.
|
798
|
-
name
|
844
|
+
name:
|
799
845
|
The name of the workflow. If specified, the workflow directory will be `path`
|
800
846
|
joined with `name`. If not specified the `WorkflowTemplate` name will be used,
|
801
847
|
in combination with a date-timestamp.
|
802
|
-
overwrite
|
848
|
+
overwrite:
|
803
849
|
If True and the workflow directory (`path` + `name`) already exists, the
|
804
850
|
existing directory will be overwritten.
|
805
|
-
store
|
851
|
+
store:
|
806
852
|
The persistent store to use for this workflow.
|
807
|
-
ts_fmt
|
853
|
+
ts_fmt:
|
808
854
|
The datetime format to use for storing datetimes. Datetimes are always stored
|
809
855
|
in UTC (because Numpy does not store time zone info), so this should not
|
810
856
|
include a time zone name.
|
811
|
-
ts_name_fmt
|
857
|
+
ts_name_fmt:
|
812
858
|
The datetime format to use when generating the workflow name, where it
|
813
859
|
includes a timestamp.
|
814
|
-
store_kwargs
|
860
|
+
store_kwargs:
|
815
861
|
Keyword arguments to pass to the store's `write_empty_workflow` method.
|
816
|
-
variables
|
862
|
+
variables:
|
817
863
|
String variables to substitute in the file given by `JSON_path`.
|
818
864
|
"""
|
819
865
|
template = cls.app.WorkflowTemplate.from_JSON_file(
|
@@ -850,30 +896,30 @@ class Workflow:
|
|
850
896
|
|
851
897
|
Parameters
|
852
898
|
----------
|
853
|
-
JSON_str
|
899
|
+
JSON_str:
|
854
900
|
The JSON string containing a workflow template parametrisation.
|
855
|
-
path
|
901
|
+
path:
|
856
902
|
The directory in which the workflow will be generated. The current directory
|
857
903
|
if not specified.
|
858
|
-
name
|
904
|
+
name:
|
859
905
|
The name of the workflow. If specified, the workflow directory will be `path`
|
860
906
|
joined with `name`. If not specified the `WorkflowTemplate` name will be used,
|
861
907
|
in combination with a date-timestamp.
|
862
|
-
overwrite
|
908
|
+
overwrite:
|
863
909
|
If True and the workflow directory (`path` + `name`) already exists, the
|
864
910
|
existing directory will be overwritten.
|
865
|
-
store
|
911
|
+
store:
|
866
912
|
The persistent store to use for this workflow.
|
867
|
-
ts_fmt
|
913
|
+
ts_fmt:
|
868
914
|
The datetime format to use for storing datetimes. Datetimes are always stored
|
869
915
|
in UTC (because Numpy does not store time zone info), so this should not
|
870
916
|
include a time zone name.
|
871
|
-
ts_name_fmt
|
917
|
+
ts_name_fmt:
|
872
918
|
The datetime format to use when generating the workflow name, where it
|
873
919
|
includes a timestamp.
|
874
|
-
store_kwargs
|
920
|
+
store_kwargs:
|
875
921
|
Keyword arguments to pass to the store's `write_empty_workflow` method.
|
876
|
-
variables
|
922
|
+
variables:
|
877
923
|
String variables to substitute in the string `JSON_str`.
|
878
924
|
"""
|
879
925
|
template = cls.app.WorkflowTemplate.from_JSON_string(
|
@@ -912,34 +958,34 @@ class Workflow:
|
|
912
958
|
|
913
959
|
Parameters
|
914
960
|
----------
|
915
|
-
template_path
|
961
|
+
template_path:
|
916
962
|
The path to a template file in YAML or JSON format, and with a ".yml",
|
917
963
|
".yaml", or ".json" extension.
|
918
|
-
template_format
|
964
|
+
template_format:
|
919
965
|
If specified, one of "json" or "yaml". This forces parsing from a particular
|
920
966
|
format regardless of the file extension.
|
921
|
-
path
|
967
|
+
path:
|
922
968
|
The directory in which the workflow will be generated. The current directory
|
923
969
|
if not specified.
|
924
|
-
name
|
970
|
+
name:
|
925
971
|
The name of the workflow. If specified, the workflow directory will be `path`
|
926
972
|
joined with `name`. If not specified the `WorkflowTemplate` name will be used,
|
927
973
|
in combination with a date-timestamp.
|
928
|
-
overwrite
|
974
|
+
overwrite:
|
929
975
|
If True and the workflow directory (`path` + `name`) already exists, the
|
930
976
|
existing directory will be overwritten.
|
931
|
-
store
|
977
|
+
store:
|
932
978
|
The persistent store to use for this workflow.
|
933
|
-
ts_fmt
|
979
|
+
ts_fmt:
|
934
980
|
The datetime format to use for storing datetimes. Datetimes are always stored
|
935
981
|
in UTC (because Numpy does not store time zone info), so this should not
|
936
982
|
include a time zone name.
|
937
|
-
ts_name_fmt
|
983
|
+
ts_name_fmt:
|
938
984
|
The datetime format to use when generating the workflow name, where it
|
939
985
|
includes a timestamp.
|
940
|
-
store_kwargs
|
986
|
+
store_kwargs:
|
941
987
|
Keyword arguments to pass to the store's `write_empty_workflow` method.
|
942
|
-
variables
|
988
|
+
variables:
|
943
989
|
String variables to substitute in the file given by `template_path`.
|
944
990
|
"""
|
945
991
|
try:
|
@@ -984,37 +1030,37 @@ class Workflow:
|
|
984
1030
|
|
985
1031
|
Parameters
|
986
1032
|
----------
|
987
|
-
template_name
|
1033
|
+
template_name:
|
988
1034
|
Name of the new workflow template, from which the new workflow will be
|
989
1035
|
generated.
|
990
|
-
tasks
|
1036
|
+
tasks:
|
991
1037
|
List of Task objects to add to the new workflow.
|
992
|
-
loops
|
1038
|
+
loops:
|
993
1039
|
List of Loop objects to add to the new workflow.
|
994
|
-
resources
|
1040
|
+
resources:
|
995
1041
|
Mapping of action scopes to resource requirements, to be applied to all
|
996
1042
|
element sets in the workflow. `resources` specified in an element set take
|
997
1043
|
precedence of those defined here for the whole workflow.
|
998
|
-
path
|
1044
|
+
path:
|
999
1045
|
The directory in which the workflow will be generated. The current directory
|
1000
1046
|
if not specified.
|
1001
|
-
workflow_name
|
1047
|
+
workflow_name:
|
1002
1048
|
The name of the workflow. If specified, the workflow directory will be `path`
|
1003
1049
|
joined with `name`. If not specified `template_name` will be used, in
|
1004
1050
|
combination with a date-timestamp.
|
1005
|
-
overwrite
|
1051
|
+
overwrite:
|
1006
1052
|
If True and the workflow directory (`path` + `name`) already exists, the
|
1007
1053
|
existing directory will be overwritten.
|
1008
|
-
store
|
1054
|
+
store:
|
1009
1055
|
The persistent store to use for this workflow.
|
1010
|
-
ts_fmt
|
1056
|
+
ts_fmt:
|
1011
1057
|
The datetime format to use for storing datetimes. Datetimes are always stored
|
1012
1058
|
in UTC (because Numpy does not store time zone info), so this should not
|
1013
1059
|
include a time zone name.
|
1014
|
-
ts_name_fmt
|
1060
|
+
ts_name_fmt:
|
1015
1061
|
The datetime format to use when generating the workflow name, where it
|
1016
1062
|
includes a timestamp.
|
1017
|
-
store_kwargs
|
1063
|
+
store_kwargs:
|
1018
1064
|
Keyword arguments to pass to the store's `write_empty_workflow` method.
|
1019
1065
|
"""
|
1020
1066
|
template = cls.app.WorkflowTemplate(
|
@@ -1080,6 +1126,9 @@ class Workflow:
|
|
1080
1126
|
new_wk_task._add_elements(element_sets=task.element_sets)
|
1081
1127
|
|
1082
1128
|
def add_task(self, task: app.Task, new_index: Optional[int] = None) -> None:
|
1129
|
+
"""
|
1130
|
+
Add a task to this workflow.
|
1131
|
+
"""
|
1083
1132
|
with self._store.cached_load():
|
1084
1133
|
with self.batch_update():
|
1085
1134
|
self._add_task(task, new_index=new_index)
|
@@ -1186,6 +1235,9 @@ class Workflow:
|
|
1186
1235
|
|
1187
1236
|
@property
|
1188
1237
|
def creation_info(self):
|
1238
|
+
"""
|
1239
|
+
The creation descriptor for the workflow.
|
1240
|
+
"""
|
1189
1241
|
if not self._creation_info:
|
1190
1242
|
info = self._store.get_creation_info()
|
1191
1243
|
info["create_time"] = (
|
@@ -1198,22 +1250,34 @@ class Workflow:
|
|
1198
1250
|
|
1199
1251
|
@property
|
1200
1252
|
def id_(self):
|
1253
|
+
"""
|
1254
|
+
The ID of this workflow.
|
1255
|
+
"""
|
1201
1256
|
return self.creation_info["id"]
|
1202
1257
|
|
1203
1258
|
@property
|
1204
1259
|
def ts_fmt(self):
|
1260
|
+
"""
|
1261
|
+
The timestamp format.
|
1262
|
+
"""
|
1205
1263
|
if not self._ts_fmt:
|
1206
1264
|
self._ts_fmt = self._store.get_ts_fmt()
|
1207
1265
|
return self._ts_fmt
|
1208
1266
|
|
1209
1267
|
@property
|
1210
1268
|
def ts_name_fmt(self):
|
1269
|
+
"""
|
1270
|
+
The timestamp format for names.
|
1271
|
+
"""
|
1211
1272
|
if not self._ts_name_fmt:
|
1212
1273
|
self._ts_name_fmt = self._store.get_ts_name_fmt()
|
1213
1274
|
return self._ts_name_fmt
|
1214
1275
|
|
1215
1276
|
@property
|
1216
1277
|
def template_components(self) -> Dict:
|
1278
|
+
"""
|
1279
|
+
The template components used for this workflow.
|
1280
|
+
"""
|
1217
1281
|
if self._template_components is None:
|
1218
1282
|
with self._store.cached_load():
|
1219
1283
|
tc_js = self._store.get_template_components()
|
@@ -1222,6 +1286,9 @@ class Workflow:
|
|
1222
1286
|
|
1223
1287
|
@property
|
1224
1288
|
def template(self) -> app.WorkflowTemplate:
|
1289
|
+
"""
|
1290
|
+
The template that this workflow was made from.
|
1291
|
+
"""
|
1225
1292
|
if self._template is None:
|
1226
1293
|
with self._store.cached_load():
|
1227
1294
|
temp_js = self._store.get_template()
|
@@ -1240,6 +1307,9 @@ class Workflow:
|
|
1240
1307
|
|
1241
1308
|
@property
|
1242
1309
|
def tasks(self) -> app.WorkflowTaskList:
|
1310
|
+
"""
|
1311
|
+
The tasks in this workflow.
|
1312
|
+
"""
|
1243
1313
|
if self._tasks is None:
|
1244
1314
|
with self._store.cached_load():
|
1245
1315
|
all_tasks = self._store.get_tasks()
|
@@ -1258,6 +1328,9 @@ class Workflow:
|
|
1258
1328
|
|
1259
1329
|
@property
|
1260
1330
|
def loops(self) -> app.WorkflowLoopList:
|
1331
|
+
"""
|
1332
|
+
The loops in this workflow.
|
1333
|
+
"""
|
1261
1334
|
if self._loops is None:
|
1262
1335
|
with self._store.cached_load():
|
1263
1336
|
wk_loops = []
|
@@ -1279,6 +1352,9 @@ class Workflow:
|
|
1279
1352
|
|
1280
1353
|
@property
|
1281
1354
|
def submissions(self) -> List[app.Submission]:
|
1355
|
+
"""
|
1356
|
+
The job submissions done by this workflow.
|
1357
|
+
"""
|
1282
1358
|
if self._submissions is None:
|
1283
1359
|
self.app.persistence_logger.debug("loading workflow submissions")
|
1284
1360
|
with self._store.cached_load():
|
@@ -1293,42 +1369,66 @@ class Workflow:
|
|
1293
1369
|
|
1294
1370
|
@property
|
1295
1371
|
def num_added_tasks(self) -> int:
|
1372
|
+
"""
|
1373
|
+
The total number of added tasks.
|
1374
|
+
"""
|
1296
1375
|
return self._store._get_num_total_added_tasks()
|
1297
1376
|
|
1298
1377
|
@TimeIt.decorator
|
1299
1378
|
def get_store_EARs(self, id_lst: Iterable[int]) -> List[AnySEAR]:
|
1379
|
+
"""
|
1380
|
+
Get the persistent element action runs.
|
1381
|
+
"""
|
1300
1382
|
return self._store.get_EARs(id_lst)
|
1301
1383
|
|
1302
1384
|
@TimeIt.decorator
|
1303
1385
|
def get_store_element_iterations(
|
1304
1386
|
self, id_lst: Iterable[int]
|
1305
1387
|
) -> List[AnySElementIter]:
|
1388
|
+
"""
|
1389
|
+
Get the persistent element iterations.
|
1390
|
+
"""
|
1306
1391
|
return self._store.get_element_iterations(id_lst)
|
1307
1392
|
|
1308
1393
|
@TimeIt.decorator
|
1309
1394
|
def get_store_elements(self, id_lst: Iterable[int]) -> List[AnySElement]:
|
1395
|
+
"""
|
1396
|
+
Get the persistent elements.
|
1397
|
+
"""
|
1310
1398
|
return self._store.get_elements(id_lst)
|
1311
1399
|
|
1312
1400
|
@TimeIt.decorator
|
1313
1401
|
def get_store_tasks(self, id_lst: Iterable[int]) -> List[AnySTask]:
|
1402
|
+
"""
|
1403
|
+
Get the persistent tasks.
|
1404
|
+
"""
|
1314
1405
|
return self._store.get_tasks_by_IDs(id_lst)
|
1315
1406
|
|
1316
1407
|
def get_element_iteration_IDs_from_EAR_IDs(self, id_lst: Iterable[int]) -> List[int]:
|
1408
|
+
"""
|
1409
|
+
Get the element iteration IDs of EARs.
|
1410
|
+
"""
|
1317
1411
|
return [i.elem_iter_ID for i in self.get_store_EARs(id_lst)]
|
1318
1412
|
|
1319
1413
|
def get_element_IDs_from_EAR_IDs(self, id_lst: Iterable[int]) -> List[int]:
|
1414
|
+
"""
|
1415
|
+
Get the element IDs of EARs.
|
1416
|
+
"""
|
1320
1417
|
iter_IDs = self.get_element_iteration_IDs_from_EAR_IDs(id_lst)
|
1321
1418
|
return [i.element_ID for i in self.get_store_element_iterations(iter_IDs)]
|
1322
1419
|
|
1323
1420
|
def get_task_IDs_from_element_IDs(self, id_lst: Iterable[int]) -> List[int]:
|
1421
|
+
"""
|
1422
|
+
Get the task IDs of elements.
|
1423
|
+
"""
|
1324
1424
|
return [i.task_ID for i in self.get_store_elements(id_lst)]
|
1325
1425
|
|
1326
1426
|
def get_EAR_IDs_of_tasks(self, id_lst: int) -> List[int]:
|
1327
|
-
"""Get EAR IDs belonging to multiple tasks"""
|
1427
|
+
"""Get EAR IDs belonging to multiple tasks."""
|
1328
1428
|
return [i.id_ for i in self.get_EARs_of_tasks(id_lst)]
|
1329
1429
|
|
1330
1430
|
def get_EARs_of_tasks(self, id_lst: Iterable[int]) -> List[app.ElementActionRun]:
|
1331
|
-
"""Get EARs belonging to multiple
|
1431
|
+
"""Get EARs belonging to multiple task.s"""
|
1332
1432
|
EARs = []
|
1333
1433
|
for i in id_lst:
|
1334
1434
|
task = self.tasks.get(insert_ID=i)
|
@@ -1341,7 +1441,7 @@ class Workflow:
|
|
1341
1441
|
def get_element_iterations_of_tasks(
|
1342
1442
|
self, id_lst: Iterable[int]
|
1343
1443
|
) -> List[app.ElementIteration]:
|
1344
|
-
"""Get element iterations belonging to multiple tasks"""
|
1444
|
+
"""Get element iterations belonging to multiple tasks."""
|
1345
1445
|
iters = []
|
1346
1446
|
for i in id_lst:
|
1347
1447
|
task = self.tasks.get(insert_ID=i)
|
@@ -1431,7 +1531,7 @@ class Workflow:
|
|
1431
1531
|
|
1432
1532
|
@TimeIt.decorator
|
1433
1533
|
def get_EARs_from_IDs(self, id_lst: Iterable[int]) -> List[app.ElementActionRun]:
|
1434
|
-
"""
|
1534
|
+
"""Get element action run objects from a list of IDs."""
|
1435
1535
|
self.app.persistence_logger.debug(f"get_EARs_from_IDs: id_lst={id_lst!r}")
|
1436
1536
|
|
1437
1537
|
store_EARs = self._store.get_EARs(id_lst)
|
@@ -1490,14 +1590,23 @@ class Workflow:
|
|
1490
1590
|
|
1491
1591
|
@TimeIt.decorator
|
1492
1592
|
def get_all_elements(self) -> List[app.Element]:
|
1593
|
+
"""
|
1594
|
+
Get all elements in the workflow.
|
1595
|
+
"""
|
1493
1596
|
return self.get_elements_from_IDs(range(self.num_elements))
|
1494
1597
|
|
1495
1598
|
@TimeIt.decorator
|
1496
1599
|
def get_all_element_iterations(self) -> List[app.ElementIteration]:
|
1600
|
+
"""
|
1601
|
+
Get all iterations in the workflow.
|
1602
|
+
"""
|
1497
1603
|
return self.get_element_iterations_from_IDs(range(self.num_element_iterations))
|
1498
1604
|
|
1499
1605
|
@TimeIt.decorator
|
1500
1606
|
def get_all_EARs(self) -> List[app.ElementActionRun]:
|
1607
|
+
"""
|
1608
|
+
Get all runs in the workflow.
|
1609
|
+
"""
|
1501
1610
|
return self.get_EARs_from_IDs(range(self.num_EARs))
|
1502
1611
|
|
1503
1612
|
@contextmanager
|
@@ -1705,6 +1814,8 @@ class Workflow:
|
|
1705
1814
|
include_rechunk_backups=False,
|
1706
1815
|
) -> str:
|
1707
1816
|
"""
|
1817
|
+
Convert the workflow to a zipped form.
|
1818
|
+
|
1708
1819
|
Parameters
|
1709
1820
|
----------
|
1710
1821
|
path:
|
@@ -1722,6 +1833,8 @@ class Workflow:
|
|
1722
1833
|
|
1723
1834
|
def unzip(self, path=".", log=None) -> str:
|
1724
1835
|
"""
|
1836
|
+
Convert the workflow to an unzipped form.
|
1837
|
+
|
1725
1838
|
Parameters
|
1726
1839
|
----------
|
1727
1840
|
path:
|
@@ -1736,6 +1849,9 @@ class Workflow:
|
|
1736
1849
|
return self._store.copy(path)
|
1737
1850
|
|
1738
1851
|
def delete(self):
|
1852
|
+
"""
|
1853
|
+
Delete the persistent data.
|
1854
|
+
"""
|
1739
1855
|
self._store.delete()
|
1740
1856
|
|
1741
1857
|
def _delete_no_confirm(self):
|
@@ -1744,22 +1860,37 @@ class Workflow:
|
|
1744
1860
|
def get_parameters(
|
1745
1861
|
self, id_lst: Iterable[int], **kwargs: Dict
|
1746
1862
|
) -> List[AnySParameter]:
|
1863
|
+
"""
|
1864
|
+
Get parameters known to the workflow.
|
1865
|
+
"""
|
1747
1866
|
return self._store.get_parameters(id_lst, **kwargs)
|
1748
1867
|
|
1749
1868
|
@TimeIt.decorator
|
1750
1869
|
def get_parameter_sources(self, id_lst: Iterable[int]) -> List[Dict]:
|
1870
|
+
"""
|
1871
|
+
Get parameter sources known to the workflow.
|
1872
|
+
"""
|
1751
1873
|
return self._store.get_parameter_sources(id_lst)
|
1752
1874
|
|
1753
1875
|
@TimeIt.decorator
|
1754
1876
|
def get_parameter_set_statuses(self, id_lst: Iterable[int]) -> List[bool]:
|
1877
|
+
"""
|
1878
|
+
Get whether some parameters are set.
|
1879
|
+
"""
|
1755
1880
|
return self._store.get_parameter_set_statuses(id_lst)
|
1756
1881
|
|
1757
1882
|
@TimeIt.decorator
|
1758
1883
|
def get_parameter(self, index: int, **kwargs: Dict) -> AnySParameter:
|
1884
|
+
"""
|
1885
|
+
Get a single parameter.
|
1886
|
+
"""
|
1759
1887
|
return self.get_parameters([index], **kwargs)[0]
|
1760
1888
|
|
1761
1889
|
@TimeIt.decorator
|
1762
1890
|
def get_parameter_data(self, index: int, **kwargs: Dict) -> Any:
|
1891
|
+
"""
|
1892
|
+
Get the data relating to a parameter.
|
1893
|
+
"""
|
1763
1894
|
param = self.get_parameter(index, **kwargs)
|
1764
1895
|
if param.data is not None:
|
1765
1896
|
return param.data
|
@@ -1768,22 +1899,28 @@ class Workflow:
|
|
1768
1899
|
|
1769
1900
|
@TimeIt.decorator
|
1770
1901
|
def get_parameter_source(self, index: int) -> Dict:
|
1902
|
+
"""
|
1903
|
+
Get the source of a particular parameter.
|
1904
|
+
"""
|
1771
1905
|
return self.get_parameter_sources([index])[0]
|
1772
1906
|
|
1773
1907
|
@TimeIt.decorator
|
1774
1908
|
def is_parameter_set(self, index: int) -> bool:
|
1909
|
+
"""
|
1910
|
+
Test if a particular parameter is set.
|
1911
|
+
"""
|
1775
1912
|
return self.get_parameter_set_statuses([index])[0]
|
1776
1913
|
|
1777
1914
|
@TimeIt.decorator
|
1778
1915
|
def get_all_parameters(self, **kwargs: Dict) -> List[AnySParameter]:
|
1779
|
-
"""Retrieve all
|
1916
|
+
"""Retrieve all persistent parameters."""
|
1780
1917
|
num_params = self._store._get_num_total_parameters()
|
1781
1918
|
id_lst = list(range(num_params))
|
1782
1919
|
return self._store.get_parameters(id_lst, **kwargs)
|
1783
1920
|
|
1784
1921
|
@TimeIt.decorator
|
1785
1922
|
def get_all_parameter_sources(self, **kwargs: Dict) -> List[Dict]:
|
1786
|
-
"""Retrieve all
|
1923
|
+
"""Retrieve all persistent parameters sources."""
|
1787
1924
|
num_params = self._store._get_num_total_parameters()
|
1788
1925
|
id_lst = list(range(num_params))
|
1789
1926
|
return self._store.get_parameter_sources(id_lst, **kwargs)
|
@@ -1797,6 +1934,9 @@ class Workflow:
|
|
1797
1934
|
def check_parameters_exist(
|
1798
1935
|
self, id_lst: Union[int, List[int]]
|
1799
1936
|
) -> Union[bool, List[bool]]:
|
1937
|
+
"""
|
1938
|
+
Check if parameters exist.
|
1939
|
+
"""
|
1800
1940
|
is_multi = True
|
1801
1941
|
if isinstance(id_lst, int):
|
1802
1942
|
is_multi = False
|
@@ -1858,7 +1998,7 @@ class Workflow:
|
|
1858
1998
|
|
1859
1999
|
Parameters
|
1860
2000
|
----------
|
1861
|
-
map_to_insert_ID : bool
|
2001
|
+
map_to_insert_ID : bool
|
1862
2002
|
If True, return a dict whose values are task insert IDs, otherwise return a
|
1863
2003
|
list.
|
1864
2004
|
|
@@ -1922,48 +2062,81 @@ class Workflow:
|
|
1922
2062
|
|
1923
2063
|
@property
|
1924
2064
|
def num_tasks(self):
|
2065
|
+
"""
|
2066
|
+
The total number of tasks.
|
2067
|
+
"""
|
1925
2068
|
return self._store._get_num_total_tasks()
|
1926
2069
|
|
1927
2070
|
@property
|
1928
2071
|
def num_submissions(self):
|
2072
|
+
"""
|
2073
|
+
The total number of job submissions.
|
2074
|
+
"""
|
1929
2075
|
return self._store._get_num_total_submissions()
|
1930
2076
|
|
1931
2077
|
@property
|
1932
2078
|
def num_elements(self):
|
2079
|
+
"""
|
2080
|
+
The total number of elements.
|
2081
|
+
"""
|
1933
2082
|
return self._store._get_num_total_elements()
|
1934
2083
|
|
1935
2084
|
@property
|
1936
2085
|
def num_element_iterations(self):
|
2086
|
+
"""
|
2087
|
+
The total number of element iterations.
|
2088
|
+
"""
|
1937
2089
|
return self._store._get_num_total_elem_iters()
|
1938
2090
|
|
1939
2091
|
@property
|
1940
2092
|
@TimeIt.decorator
|
1941
2093
|
def num_EARs(self):
|
2094
|
+
"""
|
2095
|
+
The total number of element action runs.
|
2096
|
+
"""
|
1942
2097
|
return self._store._get_num_total_EARs()
|
1943
2098
|
|
1944
2099
|
@property
|
1945
2100
|
def num_loops(self) -> int:
|
2101
|
+
"""
|
2102
|
+
The total number of loops.
|
2103
|
+
"""
|
1946
2104
|
return self._store._get_num_total_loops()
|
1947
2105
|
|
1948
2106
|
@property
|
1949
2107
|
def artifacts_path(self):
|
2108
|
+
"""
|
2109
|
+
Path to artifacts of the workflow (temporary files, etc).
|
2110
|
+
"""
|
1950
2111
|
# TODO: allow customisation of artifacts path at submission and resources level
|
1951
2112
|
return Path(self.path) / "artifacts"
|
1952
2113
|
|
1953
2114
|
@property
|
1954
2115
|
def input_files_path(self):
|
2116
|
+
"""
|
2117
|
+
Path to input files for the workflow.
|
2118
|
+
"""
|
1955
2119
|
return self.artifacts_path / self._input_files_dir_name
|
1956
2120
|
|
1957
2121
|
@property
|
1958
2122
|
def submissions_path(self):
|
2123
|
+
"""
|
2124
|
+
Path to submission data for ths workflow.
|
2125
|
+
"""
|
1959
2126
|
return self.artifacts_path / "submissions"
|
1960
2127
|
|
1961
2128
|
@property
|
1962
2129
|
def task_artifacts_path(self):
|
2130
|
+
"""
|
2131
|
+
Path to artifacts of tasks.
|
2132
|
+
"""
|
1963
2133
|
return self.artifacts_path / "tasks"
|
1964
2134
|
|
1965
2135
|
@property
|
1966
2136
|
def execution_path(self):
|
2137
|
+
"""
|
2138
|
+
Path to working directory path for executing.
|
2139
|
+
"""
|
1967
2140
|
return Path(self.path) / self._exec_dir_name
|
1968
2141
|
|
1969
2142
|
@TimeIt.decorator
|
@@ -1972,6 +2145,9 @@ class Workflow:
|
|
1972
2145
|
task: app.Task,
|
1973
2146
|
idx_lst: Optional[List[int]] = None,
|
1974
2147
|
) -> List[app.Element]:
|
2148
|
+
"""
|
2149
|
+
Get the elements of a task.
|
2150
|
+
"""
|
1975
2151
|
return [
|
1976
2152
|
self.app.Element(task=task, **{k: v for k, v in i.items() if k != "task_ID"})
|
1977
2153
|
for i in self._store.get_task_elements(task.insert_ID, idx_lst)
|
@@ -2107,8 +2283,10 @@ class Workflow:
|
|
2107
2283
|
self._store.set_EAR_end(EAR_ID, exit_code, success)
|
2108
2284
|
|
2109
2285
|
def set_EAR_skip(self, EAR_ID: int) -> None:
|
2110
|
-
"""
|
2111
|
-
|
2286
|
+
"""
|
2287
|
+
Record that an EAR is to be skipped due to an upstream failure or loop
|
2288
|
+
termination condition being met.
|
2289
|
+
"""
|
2112
2290
|
with self._store.cached_load():
|
2113
2291
|
with self.batch_update():
|
2114
2292
|
self._store.set_EAR_skip(EAR_ID)
|
@@ -2122,6 +2300,9 @@ class Workflow:
|
|
2122
2300
|
def set_parameter_value(
|
2123
2301
|
self, param_id: int, value: Any, commit: bool = False
|
2124
2302
|
) -> None:
|
2303
|
+
"""
|
2304
|
+
Set the value of a parameter.
|
2305
|
+
"""
|
2125
2306
|
with self._store.cached_load():
|
2126
2307
|
with self.batch_update():
|
2127
2308
|
self._store.set_parameter_value(param_id, value)
|
@@ -2131,18 +2312,28 @@ class Workflow:
|
|
2131
2312
|
self._store._pending.commit_all()
|
2132
2313
|
|
2133
2314
|
def set_EARs_initialised(self, iter_ID: int):
|
2134
|
-
"""
|
2315
|
+
"""
|
2316
|
+
Set :py:attr:`~hpcflow.app.ElementIteration.EARs_initialised` to True for the
|
2317
|
+
specified iteration.
|
2318
|
+
"""
|
2135
2319
|
with self._store.cached_load():
|
2136
2320
|
with self.batch_update():
|
2137
2321
|
self._store.set_EARs_initialised(iter_ID)
|
2138
2322
|
|
2139
2323
|
def elements(self) -> Iterator[app.Element]:
|
2324
|
+
"""
|
2325
|
+
Get the elements of the workflow's tasks.
|
2326
|
+
"""
|
2140
2327
|
for task in self.tasks:
|
2141
2328
|
for element in task.elements[:]:
|
2142
2329
|
yield element
|
2143
2330
|
|
2144
2331
|
@TimeIt.decorator
|
2145
2332
|
def get_iteration_task_pathway(self, ret_iter_IDs=False, ret_data_idx=False):
|
2333
|
+
"""
|
2334
|
+
Get the iteration task pathway.
|
2335
|
+
"""
|
2336
|
+
# FIXME: I don't understand this concept, alas.
|
2146
2337
|
pathway = []
|
2147
2338
|
for task in self.tasks:
|
2148
2339
|
pathway.append((task.insert_ID, {}))
|
@@ -2574,6 +2765,9 @@ class Workflow:
|
|
2574
2765
|
def add_submission(
|
2575
2766
|
self, tasks: Optional[List[int]] = None, JS_parallelism: Optional[bool] = None
|
2576
2767
|
) -> app.Submission:
|
2768
|
+
"""
|
2769
|
+
Add a job submission to this workflow.
|
2770
|
+
"""
|
2577
2771
|
with self._store.cached_load():
|
2578
2772
|
with self.batch_update():
|
2579
2773
|
return self._add_submission(tasks, JS_parallelism)
|
@@ -2617,6 +2811,9 @@ class Workflow:
|
|
2617
2811
|
def resolve_jobscripts(
|
2618
2812
|
self, tasks: Optional[List[int]] = None
|
2619
2813
|
) -> List[app.Jobscript]:
|
2814
|
+
"""
|
2815
|
+
Resolve this workflow to a set of job scripts to run.
|
2816
|
+
"""
|
2620
2817
|
js, element_deps = self._resolve_singular_jobscripts(tasks)
|
2621
2818
|
js_deps = resolve_jobscript_dependencies(js, element_deps)
|
2622
2819
|
|
@@ -2824,6 +3021,9 @@ class Workflow:
|
|
2824
3021
|
value: Any,
|
2825
3022
|
EAR_ID: int,
|
2826
3023
|
):
|
3024
|
+
"""
|
3025
|
+
Save a parameter where an EAR can find it.
|
3026
|
+
"""
|
2827
3027
|
self.app.logger.info(f"save parameter {name!r} for EAR_ID {EAR_ID}.")
|
2828
3028
|
self.app.logger.debug(f"save parameter {name!r} value is {value!r}.")
|
2829
3029
|
with self._store.cached_load():
|
@@ -2833,6 +3033,10 @@ class Workflow:
|
|
2833
3033
|
self.set_parameter_value(param_id, value)
|
2834
3034
|
|
2835
3035
|
def show_all_EAR_statuses(self):
|
3036
|
+
"""
|
3037
|
+
Print a description of the status of every element action run in
|
3038
|
+
the workflow.
|
3039
|
+
"""
|
2836
3040
|
print(
|
2837
3041
|
f"{'task':8s} {'element':8s} {'iteration':8s} {'action':8s} "
|
2838
3042
|
f"{'run':8s} {'sub.':8s} {'exitcode':8s} {'success':8s} {'skip':8s}"
|
@@ -2893,6 +3097,9 @@ class Workflow:
|
|
2893
3097
|
)
|
2894
3098
|
|
2895
3099
|
def get_all_submission_run_IDs(self) -> List[int]:
|
3100
|
+
"""
|
3101
|
+
Get the run IDs of all submissions.
|
3102
|
+
"""
|
2896
3103
|
self.app.persistence_logger.debug("Workflow.get_all_submission_run_IDs")
|
2897
3104
|
id_lst = []
|
2898
3105
|
for sub in self.submissions:
|
@@ -2918,6 +3125,9 @@ class Workflow:
|
|
2918
3125
|
self.set_EAR_skip(run_ID)
|
2919
3126
|
|
2920
3127
|
def get_loop_map(self, id_lst: Optional[List[int]] = None):
|
3128
|
+
"""
|
3129
|
+
Get a description of what is going on with looping.
|
3130
|
+
"""
|
2921
3131
|
# TODO: test this works across multiple jobscripts
|
2922
3132
|
self.app.persistence_logger.debug("Workflow.get_loop_map")
|
2923
3133
|
if id_lst is None:
|
@@ -2962,6 +3172,9 @@ class Workflow:
|
|
2962
3172
|
backup: Optional[bool] = True,
|
2963
3173
|
status: Optional[bool] = True,
|
2964
3174
|
):
|
3175
|
+
"""
|
3176
|
+
Reorganise the stored data chunks for EARs to be more efficient.
|
3177
|
+
"""
|
2965
3178
|
self._store.rechunk_runs(chunk_size=chunk_size, backup=backup, status=status)
|
2966
3179
|
|
2967
3180
|
def rechunk_parameter_base(
|
@@ -2970,6 +3183,9 @@ class Workflow:
|
|
2970
3183
|
backup: Optional[bool] = True,
|
2971
3184
|
status: Optional[bool] = True,
|
2972
3185
|
):
|
3186
|
+
"""
|
3187
|
+
Reorganise the stored data chunks for parameterss to be more efficient.
|
3188
|
+
"""
|
2973
3189
|
self._store.rechunk_parameter_base(
|
2974
3190
|
chunk_size=chunk_size, backup=backup, status=status
|
2975
3191
|
)
|
@@ -2980,13 +3196,17 @@ class Workflow:
|
|
2980
3196
|
backup: Optional[bool] = True,
|
2981
3197
|
status: Optional[bool] = True,
|
2982
3198
|
):
|
2983
|
-
"""
|
3199
|
+
"""
|
3200
|
+
Rechunk metadata/runs and parameters/base arrays, making them more efficient.
|
3201
|
+
"""
|
2984
3202
|
self.rechunk_runs(chunk_size=chunk_size, backup=backup, status=status)
|
2985
3203
|
self.rechunk_parameter_base(chunk_size=chunk_size, backup=backup, status=status)
|
2986
3204
|
|
2987
3205
|
|
2988
3206
|
@dataclass
|
2989
3207
|
class WorkflowBlueprint:
|
2990
|
-
"""Pre-built workflow templates that are simpler to
|
3208
|
+
"""Pre-built workflow templates that are simpler to parameterise.
|
3209
|
+
(For example, fitting workflows.)"""
|
2991
3210
|
|
3211
|
+
#: The template inside this blueprint.
|
2992
3212
|
workflow_template: WorkflowTemplate
|