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.
Files changed (115) hide show
  1. hpcflow/__pyinstaller/hook-hpcflow.py +8 -6
  2. hpcflow/_version.py +1 -1
  3. hpcflow/app.py +1 -0
  4. hpcflow/data/scripts/main_script_test_hdf5_in_obj.py +1 -1
  5. hpcflow/data/scripts/main_script_test_hdf5_out_obj.py +1 -1
  6. hpcflow/sdk/__init__.py +21 -15
  7. hpcflow/sdk/app.py +2133 -770
  8. hpcflow/sdk/cli.py +281 -250
  9. hpcflow/sdk/cli_common.py +6 -2
  10. hpcflow/sdk/config/__init__.py +1 -1
  11. hpcflow/sdk/config/callbacks.py +77 -42
  12. hpcflow/sdk/config/cli.py +126 -103
  13. hpcflow/sdk/config/config.py +578 -311
  14. hpcflow/sdk/config/config_file.py +131 -95
  15. hpcflow/sdk/config/errors.py +112 -85
  16. hpcflow/sdk/config/types.py +145 -0
  17. hpcflow/sdk/core/actions.py +1054 -994
  18. hpcflow/sdk/core/app_aware.py +24 -0
  19. hpcflow/sdk/core/cache.py +81 -63
  20. hpcflow/sdk/core/command_files.py +275 -185
  21. hpcflow/sdk/core/commands.py +111 -107
  22. hpcflow/sdk/core/element.py +724 -503
  23. hpcflow/sdk/core/enums.py +192 -0
  24. hpcflow/sdk/core/environment.py +74 -93
  25. hpcflow/sdk/core/errors.py +398 -51
  26. hpcflow/sdk/core/json_like.py +540 -272
  27. hpcflow/sdk/core/loop.py +380 -334
  28. hpcflow/sdk/core/loop_cache.py +160 -43
  29. hpcflow/sdk/core/object_list.py +370 -207
  30. hpcflow/sdk/core/parameters.py +728 -600
  31. hpcflow/sdk/core/rule.py +59 -41
  32. hpcflow/sdk/core/run_dir_files.py +33 -22
  33. hpcflow/sdk/core/task.py +1546 -1325
  34. hpcflow/sdk/core/task_schema.py +240 -196
  35. hpcflow/sdk/core/test_utils.py +126 -88
  36. hpcflow/sdk/core/types.py +387 -0
  37. hpcflow/sdk/core/utils.py +410 -305
  38. hpcflow/sdk/core/validation.py +82 -9
  39. hpcflow/sdk/core/workflow.py +1192 -1028
  40. hpcflow/sdk/core/zarr_io.py +98 -137
  41. hpcflow/sdk/demo/cli.py +46 -33
  42. hpcflow/sdk/helper/cli.py +18 -16
  43. hpcflow/sdk/helper/helper.py +75 -63
  44. hpcflow/sdk/helper/watcher.py +61 -28
  45. hpcflow/sdk/log.py +83 -59
  46. hpcflow/sdk/persistence/__init__.py +8 -31
  47. hpcflow/sdk/persistence/base.py +988 -586
  48. hpcflow/sdk/persistence/defaults.py +6 -0
  49. hpcflow/sdk/persistence/discovery.py +38 -0
  50. hpcflow/sdk/persistence/json.py +408 -153
  51. hpcflow/sdk/persistence/pending.py +158 -123
  52. hpcflow/sdk/persistence/store_resource.py +37 -22
  53. hpcflow/sdk/persistence/types.py +307 -0
  54. hpcflow/sdk/persistence/utils.py +14 -11
  55. hpcflow/sdk/persistence/zarr.py +477 -420
  56. hpcflow/sdk/runtime.py +44 -41
  57. hpcflow/sdk/submission/{jobscript_info.py → enums.py} +39 -12
  58. hpcflow/sdk/submission/jobscript.py +444 -404
  59. hpcflow/sdk/submission/schedulers/__init__.py +133 -40
  60. hpcflow/sdk/submission/schedulers/direct.py +97 -71
  61. hpcflow/sdk/submission/schedulers/sge.py +132 -126
  62. hpcflow/sdk/submission/schedulers/slurm.py +263 -268
  63. hpcflow/sdk/submission/schedulers/utils.py +7 -2
  64. hpcflow/sdk/submission/shells/__init__.py +14 -15
  65. hpcflow/sdk/submission/shells/base.py +102 -29
  66. hpcflow/sdk/submission/shells/bash.py +72 -55
  67. hpcflow/sdk/submission/shells/os_version.py +31 -30
  68. hpcflow/sdk/submission/shells/powershell.py +37 -29
  69. hpcflow/sdk/submission/submission.py +203 -257
  70. hpcflow/sdk/submission/types.py +143 -0
  71. hpcflow/sdk/typing.py +163 -12
  72. hpcflow/tests/conftest.py +8 -6
  73. hpcflow/tests/schedulers/slurm/test_slurm_submission.py +5 -2
  74. hpcflow/tests/scripts/test_main_scripts.py +60 -30
  75. hpcflow/tests/shells/wsl/test_wsl_submission.py +6 -4
  76. hpcflow/tests/unit/test_action.py +86 -75
  77. hpcflow/tests/unit/test_action_rule.py +9 -4
  78. hpcflow/tests/unit/test_app.py +13 -6
  79. hpcflow/tests/unit/test_cli.py +1 -1
  80. hpcflow/tests/unit/test_command.py +71 -54
  81. hpcflow/tests/unit/test_config.py +20 -15
  82. hpcflow/tests/unit/test_config_file.py +21 -18
  83. hpcflow/tests/unit/test_element.py +58 -62
  84. hpcflow/tests/unit/test_element_iteration.py +3 -1
  85. hpcflow/tests/unit/test_element_set.py +29 -19
  86. hpcflow/tests/unit/test_group.py +4 -2
  87. hpcflow/tests/unit/test_input_source.py +116 -93
  88. hpcflow/tests/unit/test_input_value.py +29 -24
  89. hpcflow/tests/unit/test_json_like.py +44 -35
  90. hpcflow/tests/unit/test_loop.py +65 -58
  91. hpcflow/tests/unit/test_object_list.py +17 -12
  92. hpcflow/tests/unit/test_parameter.py +16 -7
  93. hpcflow/tests/unit/test_persistence.py +48 -35
  94. hpcflow/tests/unit/test_resources.py +20 -18
  95. hpcflow/tests/unit/test_run.py +8 -3
  96. hpcflow/tests/unit/test_runtime.py +2 -1
  97. hpcflow/tests/unit/test_schema_input.py +23 -15
  98. hpcflow/tests/unit/test_shell.py +3 -2
  99. hpcflow/tests/unit/test_slurm.py +8 -7
  100. hpcflow/tests/unit/test_submission.py +39 -19
  101. hpcflow/tests/unit/test_task.py +352 -247
  102. hpcflow/tests/unit/test_task_schema.py +33 -20
  103. hpcflow/tests/unit/test_utils.py +9 -11
  104. hpcflow/tests/unit/test_value_sequence.py +15 -12
  105. hpcflow/tests/unit/test_workflow.py +114 -83
  106. hpcflow/tests/unit/test_workflow_template.py +0 -1
  107. hpcflow/tests/workflows/test_jobscript.py +2 -1
  108. hpcflow/tests/workflows/test_workflows.py +18 -13
  109. {hpcflow_new2-0.2.0a189.dist-info → hpcflow_new2-0.2.0a190.dist-info}/METADATA +2 -1
  110. hpcflow_new2-0.2.0a190.dist-info/RECORD +165 -0
  111. hpcflow/sdk/core/parallel.py +0 -21
  112. hpcflow_new2-0.2.0a189.dist-info/RECORD +0 -158
  113. {hpcflow_new2-0.2.0a189.dist-info → hpcflow_new2-0.2.0a190.dist-info}/LICENSE +0 -0
  114. {hpcflow_new2-0.2.0a189.dist-info → hpcflow_new2-0.2.0a190.dist-info}/WHEEL +0 -0
  115. {hpcflow_new2-0.2.0a189.dist-info → hpcflow_new2-0.2.0a190.dist-info}/entry_points.txt +0 -0
@@ -1,4 +1,7 @@
1
+ from __future__ import annotations
2
+ from pathlib import Path
1
3
  from textwrap import dedent
4
+ from typing import Any, TYPE_CHECKING
2
5
  import pytest
3
6
  from hpcflow.app import app as hf
4
7
  from hpcflow.sdk.core.errors import UnsetParameterDataError
@@ -8,14 +11,15 @@ from hpcflow.sdk.core.test_utils import (
8
11
  P1_sub_parameter_cls as P1_sub,
9
12
  )
10
13
 
14
+ if TYPE_CHECKING:
15
+ from hpcflow.sdk.core.workflow import Workflow
16
+
11
17
 
12
18
  @pytest.fixture
13
- def workflow_w1(null_config, tmp_path):
19
+ def workflow_w1(null_config, tmp_path: Path) -> Workflow:
14
20
  s1, s2 = make_schemas(
15
- [
16
- [{"p1": None}, ("p2",), "t1"],
17
- [{"p2": None}, (), "t2"],
18
- ]
21
+ ({"p1": None}, ("p2",), "t1"),
22
+ ({"p2": None}, (), "t2"),
19
23
  )
20
24
 
21
25
  t1 = hf.Task(
@@ -28,38 +32,30 @@ def workflow_w1(null_config, tmp_path):
28
32
  return hf.Workflow.from_template(wkt, path=tmp_path)
29
33
 
30
34
 
31
- def test_element_task_dependencies(workflow_w1):
35
+ def test_element_task_dependencies(workflow_w1: Workflow):
32
36
  assert workflow_w1.tasks.t2.elements[0].get_task_dependencies(as_objects=True) == [
33
37
  workflow_w1.tasks.t1
34
38
  ]
35
39
 
36
40
 
37
- def test_element_dependent_tasks(workflow_w1):
41
+ def test_element_dependent_tasks(workflow_w1: Workflow):
38
42
  assert workflow_w1.tasks.t1.elements[0].get_dependent_tasks(as_objects=True) == [
39
43
  workflow_w1.tasks.t2
40
44
  ]
41
45
 
42
46
 
43
- def test_element_element_dependencies(workflow_w1):
44
- assert all(
45
- (
46
- workflow_w1.tasks.t2.elements[0].get_element_dependencies() == [0],
47
- workflow_w1.tasks.t2.elements[1].get_element_dependencies() == [1],
48
- )
49
- )
47
+ def test_element_element_dependencies(workflow_w1: Workflow):
48
+ assert workflow_w1.tasks.t2.elements[0].get_element_dependencies() == {0}
49
+ assert workflow_w1.tasks.t2.elements[1].get_element_dependencies() == {1}
50
50
 
51
51
 
52
- def test_element_dependent_elements(workflow_w1):
53
- assert all(
54
- (
55
- workflow_w1.tasks.t1.elements[0].get_dependent_elements() == [2],
56
- workflow_w1.tasks.t1.elements[1].get_dependent_elements() == [3],
57
- )
58
- )
52
+ def test_element_dependent_elements(workflow_w1: Workflow):
53
+ assert workflow_w1.tasks.t1.elements[0].get_dependent_elements() == {2}
54
+ assert workflow_w1.tasks.t1.elements[1].get_dependent_elements() == {3}
59
55
 
60
56
 
61
57
  def test_equivalence_single_labelled_schema_input_element_get_label_and_non_label(
62
- new_null_config, tmp_path
58
+ new_null_config, tmp_path: Path
63
59
  ):
64
60
  s1 = hf.TaskSchema(
65
61
  objective="t1",
@@ -83,7 +79,7 @@ def test_equivalence_single_labelled_schema_input_element_get_label_and_non_labe
83
79
  )
84
80
 
85
81
 
86
- def test_element_dependencies_inputs_only_schema(new_null_config, tmp_path):
82
+ def test_element_dependencies_inputs_only_schema(new_null_config, tmp_path: Path):
87
83
  s1 = hf.TaskSchema(
88
84
  objective="t1",
89
85
  inputs=[hf.SchemaInput(parameter=hf.Parameter("p1"))],
@@ -115,12 +111,12 @@ def test_element_dependencies_inputs_only_schema(new_null_config, tmp_path):
115
111
  path=tmp_path,
116
112
  template_name="wk0",
117
113
  )
118
- assert wk.tasks.t1.elements[0].get_dependent_elements() == [1]
119
- assert wk.tasks.t2.elements[0].get_element_dependencies() == [0]
120
- assert wk.tasks.t2.elements[0].get_EAR_dependencies() == [0]
114
+ assert wk.tasks.t1.elements[0].get_dependent_elements() == {1}
115
+ assert wk.tasks.t2.elements[0].get_element_dependencies() == {0}
116
+ assert wk.tasks.t2.elements[0].get_EAR_dependencies() == {0}
121
117
 
122
118
 
123
- def test_element_get_empty_path_single_labelled_input(null_config, tmp_path):
119
+ def test_element_get_empty_path_single_labelled_input(null_config, tmp_path: Path):
124
120
  p1_val = 101
125
121
  label = "my_label"
126
122
  s1 = hf.TaskSchema(
@@ -138,7 +134,7 @@ def test_element_get_empty_path_single_labelled_input(null_config, tmp_path):
138
134
  }
139
135
 
140
136
 
141
- def test_element_get_labelled_non_labelled_equivalence(null_config, tmp_path):
137
+ def test_element_get_labelled_non_labelled_equivalence(null_config, tmp_path: Path):
142
138
  p1_val = 101
143
139
  label = "my_label"
144
140
  s1 = hf.TaskSchema(
@@ -156,7 +152,7 @@ def test_element_get_labelled_non_labelled_equivalence(null_config, tmp_path):
156
152
 
157
153
 
158
154
  @pytest.fixture
159
- def element_get_wk(null_config, tmp_path):
155
+ def element_get_wk(null_config, tmp_path: Path) -> Workflow:
160
156
  s1 = hf.TaskSchema(
161
157
  objective="t1",
162
158
  inputs=[hf.SchemaInput(parameter="p1"), hf.SchemaInput(parameter="p1c")],
@@ -191,62 +187,62 @@ def element_get_wk(null_config, tmp_path):
191
187
  return wk
192
188
 
193
189
 
194
- def test_element_get_simple(element_get_wk):
190
+ def test_element_get_simple(element_get_wk: Workflow):
195
191
  assert element_get_wk.tasks.t1.elements[0].get("inputs.p1") == 100
196
192
  assert element_get_wk.tasks.t1.elements[1].get("inputs.p1") == 100
197
193
 
198
194
 
199
- def test_element_get_obj(element_get_wk):
195
+ def test_element_get_obj(element_get_wk: Workflow):
200
196
  obj_0 = P1(a=20, sub_param=P1_sub(e=5))
201
197
  obj_1 = P1(a=30, sub_param=P1_sub(e=5))
202
198
  assert element_get_wk.tasks.t1.elements[0].get("inputs.p1c") == obj_0
203
199
  assert element_get_wk.tasks.t1.elements[1].get("inputs.p1c") == obj_1
204
200
 
205
201
 
206
- def test_element_get_sub_obj(element_get_wk):
202
+ def test_element_get_sub_obj(element_get_wk: Workflow):
207
203
  sub_obj = P1_sub(e=5)
208
204
  assert element_get_wk.tasks.t1.elements[0].get("inputs.p1c.sub_param") == sub_obj
209
205
  assert element_get_wk.tasks.t1.elements[1].get("inputs.p1c.sub_param") == sub_obj
210
206
 
211
207
 
212
- def test_element_get_sub_obj_attr(element_get_wk):
208
+ def test_element_get_sub_obj_attr(element_get_wk: Workflow):
213
209
  assert element_get_wk.tasks.t1.elements[0].get("inputs.p1c.sub_param.e") == 5
214
210
  assert element_get_wk.tasks.t1.elements[1].get("inputs.p1c.sub_param.e") == 5
215
211
 
216
212
 
217
- def test_element_get_sub_obj_property(element_get_wk):
213
+ def test_element_get_sub_obj_property(element_get_wk: Workflow):
218
214
  assert element_get_wk.tasks.t1.elements[0].get("inputs.p1c.sub_param.twice_e") == 10
219
215
  assert element_get_wk.tasks.t1.elements[1].get("inputs.p1c.sub_param.twice_e") == 10
220
216
 
221
217
 
222
- def test_element_get_obj_no_raise_missing_attr(element_get_wk):
218
+ def test_element_get_obj_no_raise_missing_attr(element_get_wk: Workflow):
223
219
  assert element_get_wk.tasks.t1.elements[0].get("inputs.p1c.b") is None
224
220
 
225
221
 
226
- def test_element_get_obj_raise_missing_attr(element_get_wk):
222
+ def test_element_get_obj_raise_missing_attr(element_get_wk: Workflow):
227
223
  with pytest.raises(ValueError):
228
224
  element_get_wk.tasks.t1.elements[0].get("inputs.p1c.b", raise_on_missing=True)
229
225
 
230
226
 
231
- def test_element_get_obj_raise_missing_nested_attr(element_get_wk):
227
+ def test_element_get_obj_raise_missing_nested_attr(element_get_wk: Workflow):
232
228
  with pytest.raises(ValueError):
233
229
  element_get_wk.tasks.t1.elements[0].get("inputs.p1c.a.b", raise_on_missing=True)
234
230
 
235
231
 
236
- def test_element_get_raise_missing_root(element_get_wk):
232
+ def test_element_get_raise_missing_root(element_get_wk: Workflow):
237
233
  with pytest.raises(ValueError):
238
234
  element_get_wk.tasks.t1.elements[0].get("blah", raise_on_missing=True)
239
235
 
240
236
 
241
- def test_element_get_no_raise_missing_root(element_get_wk):
237
+ def test_element_get_no_raise_missing_root(element_get_wk: Workflow):
242
238
  assert element_get_wk.tasks.t1.elements[0].get("blah") is None
243
239
 
244
240
 
245
- def test_element_get_expected_default(element_get_wk):
241
+ def test_element_get_expected_default(element_get_wk: Workflow):
246
242
  assert element_get_wk.tasks.t1.elements[0].get("blah", default={}) == {}
247
243
 
248
244
 
249
- def test_element_get_part_unset(null_config, tmp_path):
245
+ def test_element_get_part_unset(null_config, tmp_path: Path):
250
246
  s1 = hf.TaskSchema(
251
247
  objective="t1",
252
248
  inputs=[hf.SchemaInput(parameter="p1")],
@@ -299,7 +295,7 @@ def test_element_get_part_unset(null_config, tmp_path):
299
295
  wk.tasks.t2.elements[0].get("inputs.p2", raise_on_unset=True)
300
296
 
301
297
 
302
- def test_element_get_unset_object(null_config, tmp_path):
298
+ def test_element_get_unset_object(null_config, tmp_path: Path):
303
299
  s1 = hf.TaskSchema(
304
300
  objective="t1",
305
301
  inputs=[hf.SchemaInput(parameter="p1")],
@@ -328,7 +324,7 @@ def test_element_get_unset_object(null_config, tmp_path):
328
324
  assert wk.tasks.t1.elements[0].get("outputs.p1c") == None
329
325
 
330
326
 
331
- def test_element_get_unset_sub_object(null_config, tmp_path):
327
+ def test_element_get_unset_sub_object(null_config, tmp_path: Path):
332
328
  s1 = hf.TaskSchema(
333
329
  objective="t1",
334
330
  inputs=[hf.SchemaInput(parameter="p1")],
@@ -357,7 +353,7 @@ def test_element_get_unset_sub_object(null_config, tmp_path):
357
353
  assert wk.tasks.t1.elements[0].get("outputs.p1c.sub_param") == None
358
354
 
359
355
 
360
- def test_element_get_unset_object_group(null_config, tmp_path):
356
+ def test_element_get_unset_object_group(null_config, tmp_path: Path):
361
357
  s1 = hf.TaskSchema(
362
358
  objective="t1",
363
359
  inputs=[hf.SchemaInput(parameter="p1c")],
@@ -397,7 +393,7 @@ def test_element_get_unset_object_group(null_config, tmp_path):
397
393
  assert wk.tasks.t2.elements[0].get("inputs.p1c") == [None, None]
398
394
 
399
395
 
400
- def test_element_get_unset_sub_object_group(null_config, tmp_path):
396
+ def test_element_get_unset_sub_object_group(null_config, tmp_path: Path):
401
397
  s1 = hf.TaskSchema(
402
398
  objective="t1",
403
399
  inputs=[hf.SchemaInput(parameter="p1c")],
@@ -437,7 +433,7 @@ def test_element_get_unset_sub_object_group(null_config, tmp_path):
437
433
  assert wk.tasks.t2.elements[0].get("inputs.p1c.sub_param") == [None, None]
438
434
 
439
435
 
440
- def test_iter(new_null_config, tmp_path):
436
+ def test_iter(new_null_config, tmp_path: Path):
441
437
  wkt = hf.WorkflowTemplate(
442
438
  name="test",
443
439
  tasks=[
@@ -452,7 +448,7 @@ def test_iter(new_null_config, tmp_path):
452
448
  assert elem_i.index == idx
453
449
 
454
450
 
455
- def test_slice(new_null_config, tmp_path):
451
+ def test_slice(new_null_config, tmp_path: Path):
456
452
  wkt = hf.WorkflowTemplate(
457
453
  name="test",
458
454
  tasks=[
@@ -469,7 +465,7 @@ def test_slice(new_null_config, tmp_path):
469
465
  assert elems[1].index == 2
470
466
 
471
467
 
472
- def test_element_get_with_list_index_sequence(null_config, tmp_path):
468
+ def test_element_get_with_list_index_sequence(null_config, tmp_path: Path):
473
469
  wkt_yaml = dedent(
474
470
  """\
475
471
  name: test_list_idx_sequence
@@ -487,7 +483,7 @@ def test_element_get_with_list_index_sequence(null_config, tmp_path):
487
483
  assert wk.tasks[0].elements[0].get("inputs.p1") == [9, 1]
488
484
 
489
485
 
490
- def test_element_get_with_list_index_sequence_two_parts(null_config, tmp_path):
486
+ def test_element_get_with_list_index_sequence_two_parts(null_config, tmp_path: Path):
491
487
  wkt_yaml = dedent(
492
488
  """\
493
489
  name: test_list_idx_sequence
@@ -515,7 +511,7 @@ def test_element_get_with_list_index_sequence_two_parts(null_config, tmp_path):
515
511
  ]
516
512
 
517
513
 
518
- def test_element_get_group_sequence(null_config, tmp_path):
514
+ def test_element_get_group_sequence(null_config, tmp_path: Path):
519
515
  wkt_yaml = dedent(
520
516
  """\
521
517
  name: test_list_idx_sequence
@@ -553,7 +549,7 @@ def test_element_get_group_sequence(null_config, tmp_path):
553
549
  ]
554
550
 
555
551
 
556
- def test_element_get_group_sequence_obj(new_null_config, tmp_path):
552
+ def test_element_get_group_sequence_obj(new_null_config, tmp_path: Path):
557
553
  wkt_yaml = dedent(
558
554
  """\
559
555
  name: test_list_idx_sequence
@@ -607,29 +603,28 @@ def test_element_get_group_sequence_obj(new_null_config, tmp_path):
607
603
  ]
608
604
 
609
605
 
610
- def test_element_resources_get_jobscript_hash_equal_empty():
606
+ def test_element_resources_get_jobscript_hash_equal_empty() -> None:
611
607
  assert (
612
608
  hf.ElementResources().get_jobscript_hash()
613
609
  == hf.ElementResources().get_jobscript_hash()
614
610
  )
615
611
 
616
612
 
617
- def test_element_resources_get_jobscript_hash_unequal_num_cores():
613
+ def test_element_resources_get_jobscript_hash_unequal_num_cores() -> None:
618
614
  assert (
619
615
  hf.ElementResources(num_cores=1).get_jobscript_hash()
620
616
  != hf.ElementResources(num_cores=2).get_jobscript_hash()
621
617
  )
622
618
 
623
619
 
624
- def test_element_resources_get_jobscript_hash_equal_num_cores():
620
+ def test_element_resources_get_jobscript_hash_equal_num_cores() -> None:
625
621
  assert (
626
622
  hf.ElementResources(num_cores=1).get_jobscript_hash()
627
623
  == hf.ElementResources(num_cores=1).get_jobscript_hash()
628
624
  )
629
625
 
630
626
 
631
- def test_element_resources_get_jobscript_hash_unequal_scheduler_args_empty():
632
-
627
+ def test_element_resources_get_jobscript_hash_unequal_scheduler_args_empty() -> None:
633
628
  assert (
634
629
  hf.ElementResources().get_jobscript_hash()
635
630
  != hf.ElementResources(
@@ -638,16 +633,16 @@ def test_element_resources_get_jobscript_hash_unequal_scheduler_args_empty():
638
633
  )
639
634
 
640
635
 
641
- def test_element_resources_get_jobscript_hash_equal_non_truthy_scheduler_args():
642
-
636
+ def test_element_resources_get_jobscript_hash_equal_non_truthy_scheduler_args() -> None:
643
637
  assert (
644
638
  hf.ElementResources().get_jobscript_hash()
645
639
  == hf.ElementResources(scheduler_args={}).get_jobscript_hash()
646
640
  )
647
641
 
648
642
 
649
- def test_element_resources_get_jobscript_hash_unequal_scheduler_args_diff_options():
650
-
643
+ def test_element_resources_get_jobscript_hash_unequal_scheduler_args_diff_options() -> (
644
+ None
645
+ ):
651
646
  assert (
652
647
  hf.ElementResources(
653
648
  scheduler_args={"options": {"--time": "02:00:00"}}
@@ -658,8 +653,9 @@ def test_element_resources_get_jobscript_hash_unequal_scheduler_args_diff_option
658
653
  )
659
654
 
660
655
 
661
- def test_element_resources_get_jobscript_hash_unequal_scheduler_args_same_options():
662
-
656
+ def test_element_resources_get_jobscript_hash_unequal_scheduler_args_same_options() -> (
657
+ None
658
+ ):
663
659
  assert (
664
660
  hf.ElementResources(
665
661
  scheduler_args={"options": {"--time": "02:00:00"}}
@@ -1,9 +1,11 @@
1
+ from __future__ import annotations
2
+ from pathlib import Path
1
3
  import pytest
2
4
  from hpcflow.app import app as hf
3
5
 
4
6
 
5
7
  @pytest.mark.parametrize("store", ["json", "zarr"])
6
- def test_decode(null_config, tmp_path, store):
8
+ def test_decode(null_config, tmp_path: Path, store: str):
7
9
  s1 = hf.TaskSchema(
8
10
  objective="t1",
9
11
  inputs=[hf.SchemaInput(parameter=hf.Parameter("p1"))],
@@ -1,31 +1,41 @@
1
+ from __future__ import annotations
2
+ from typing import TYPE_CHECKING
1
3
  import pytest
2
4
  from hpcflow.app import app as hf
3
5
  from hpcflow.sdk.core.errors import MalformedNestingOrderPath
4
6
 
7
+ if TYPE_CHECKING:
8
+ from pathlib import Path
9
+ from hpcflow.sdk.core.parameters import Parameter
10
+ from hpcflow.sdk.core.types import ResourceSpecArgs
11
+ from hpcflow.sdk.core.workflow import Workflow
12
+
5
13
 
6
14
  @pytest.fixture
7
- def null_config(tmp_path):
15
+ def null_config(tmp_path: Path):
8
16
  if not hf.is_config_loaded:
9
17
  hf.load_config(config_dir=tmp_path)
10
18
 
11
19
 
12
20
  @pytest.fixture
13
- def param_p1():
21
+ def param_p1() -> Parameter:
14
22
  return hf.Parameter("p1")
15
23
 
16
24
 
17
25
  @pytest.fixture
18
- def param_p2():
26
+ def param_p2() -> Parameter:
19
27
  return hf.Parameter("p2")
20
28
 
21
29
 
22
30
  @pytest.fixture
23
- def param_p3():
31
+ def param_p3() -> Parameter:
24
32
  return hf.Parameter("p3")
25
33
 
26
34
 
27
35
  @pytest.fixture
28
- def workflow_w1(null_config, tmp_path, param_p1, param_p2):
36
+ def workflow_w1(
37
+ null_config, tmp_path: Path, param_p1: Parameter, param_p2: Parameter
38
+ ) -> Workflow:
29
39
  s1 = hf.TaskSchema("t1", actions=[], inputs=[param_p1], outputs=[param_p2])
30
40
  s2 = hf.TaskSchema("t2", actions=[], inputs=[param_p2])
31
41
 
@@ -40,45 +50,45 @@ def workflow_w1(null_config, tmp_path, param_p1, param_p2):
40
50
 
41
51
 
42
52
  @pytest.fixture
43
- def workflow_w2(workflow_w1):
53
+ def workflow_w2(workflow_w1: Workflow) -> Workflow:
44
54
  """Add another element set to the second task."""
45
55
  workflow_w1.tasks.t2.add_elements(nesting_order={"inputs.p2": 1})
46
56
  return workflow_w1
47
57
 
48
58
 
49
- def test_resources_init_equivalence_dict_list_of_obj():
59
+ def test_resources_init_equivalence_dict_list_of_obj() -> None:
50
60
  es1 = hf.ElementSet(resources={"any": {"num_cores": 1}})
51
61
  es2 = hf.ElementSet(resources=[hf.ResourceSpec(scope="any", num_cores=1)])
52
62
  assert es1 == es2
53
63
 
54
64
 
55
- def test_resources_init_equivalence_list_list_of_obj():
56
- res_1_kwargs = {"scope": "any", "num_cores": 1}
65
+ def test_resources_init_equivalence_list_list_of_obj() -> None:
66
+ res_1_kwargs: ResourceSpecArgs = {"scope": "any", "num_cores": 1}
57
67
  es1 = hf.ElementSet(resources=[res_1_kwargs])
58
68
  es2 = hf.ElementSet(resources=[hf.ResourceSpec(**res_1_kwargs)])
59
69
  assert es1 == es2
60
70
 
61
71
 
62
- def test_resources_init_equivalence_list_of_obj_resource_list_obj():
63
- res_1_kwargs = {"scope": "any", "num_cores": 1}
72
+ def test_resources_init_equivalence_list_of_obj_resource_list_obj() -> None:
73
+ res_1_kwargs: ResourceSpecArgs = {"scope": "any", "num_cores": 1}
64
74
  es1 = hf.ElementSet(resources=[hf.ResourceSpec(**res_1_kwargs)])
65
75
  es2 = hf.ElementSet(resources=hf.ResourceList([hf.ResourceSpec(**res_1_kwargs)]))
66
76
  assert es1 == es2
67
77
 
68
78
 
69
- def test_repeats_single_int_equivalence(null_config):
79
+ def test_repeats_single_int_equivalence(null_config) -> None:
70
80
  es1 = hf.ElementSet(repeats=2)
71
81
  es2 = hf.ElementSet(repeats=[{"name": "", "number": 2, "nesting_order": 0}])
72
82
  assert es1 == es2
73
83
 
74
84
 
75
- def test_merge_envs(null_config):
85
+ def test_merge_envs(null_config) -> None:
76
86
  envs = {"my_env": {"version": "1.0"}}
77
87
  es = hf.ElementSet(environments=envs)
78
88
  assert es.resources.get(scope=hf.ActionScope.any()).environments == envs
79
89
 
80
90
 
81
- def test_merge_envs_existing_any_resources(null_config):
91
+ def test_merge_envs_existing_any_resources(null_config) -> None:
82
92
  envs = {"my_env": {"version": "1.0"}}
83
93
  num_cores = 2
84
94
  es = hf.ElementSet(resources={"any": {"num_cores": num_cores}}, environments=envs)
@@ -86,28 +96,28 @@ def test_merge_envs_existing_any_resources(null_config):
86
96
  assert es.resources.get(scope=hf.ActionScope.any()).num_cores == num_cores
87
97
 
88
98
 
89
- def test_merge_envs_resource_envs_precedence(null_config):
99
+ def test_merge_envs_resource_envs_precedence(null_config) -> None:
90
100
  envs = {"my_env": {"version": "1.0"}}
91
101
  res_envs = {"other_env": {"version": "2.0"}}
92
102
  es = hf.ElementSet(resources={"any": {"environments": res_envs}}, environments=envs)
93
103
  assert es.resources.get(scope=hf.ActionScope.any()).environments == res_envs
94
104
 
95
105
 
96
- def test_merge_envs_no_envs_with_resource_envs(null_config):
106
+ def test_merge_envs_no_envs_with_resource_envs(null_config) -> None:
97
107
  envs = {"my_env": {"version": "1.0"}}
98
108
  es = hf.ElementSet(resources={"any": {"environments": envs}})
99
109
  assert es.resources.get(scope=hf.ActionScope.any()).environments == envs
100
110
 
101
111
 
102
- def test_raise_env_and_envs_specified(null_config):
112
+ def test_raise_env_and_envs_specified(null_config) -> None:
103
113
  with pytest.raises(ValueError):
104
114
  hf.ElementSet(env_preset="my_preset", environments={"my_env": {"version": 1}})
105
115
 
106
116
 
107
- def test_nesting_order_paths_raise(null_config):
117
+ def test_nesting_order_paths_raise(null_config) -> None:
108
118
  with pytest.raises(MalformedNestingOrderPath):
109
119
  hf.ElementSet(nesting_order={"bad_path.p1": 1})
110
120
 
111
121
 
112
- def test_nesting_order_paths_no_raise(null_config):
122
+ def test_nesting_order_paths_no_raise(null_config) -> None:
113
123
  hf.ElementSet(nesting_order={"inputs.p1": 1, "resources.any": 2, "repeats": 3})
@@ -1,9 +1,11 @@
1
+ from __future__ import annotations
2
+ from pathlib import Path
1
3
  import pytest
2
4
  from hpcflow.app import app as hf
3
5
  from hpcflow.sdk.core.errors import MissingElementGroup
4
6
 
5
7
 
6
- def test_group_simple(null_config, tmp_path):
8
+ def test_group_simple(null_config, tmp_path: Path):
7
9
  s1 = hf.TaskSchema(
8
10
  objective="t1",
9
11
  inputs=[hf.SchemaInput("p1")],
@@ -48,7 +50,7 @@ def test_group_simple(null_config, tmp_path):
48
50
  assert len(wk.tasks.t2.elements[0].get_data_idx("inputs.p2")["inputs.p2"]) == 3
49
51
 
50
52
 
51
- def test_group_raise_no_elements(null_config, tmp_path):
53
+ def test_group_raise_no_elements(null_config, tmp_path: Path):
52
54
  s1 = hf.TaskSchema(
53
55
  objective="t1",
54
56
  inputs=[hf.SchemaInput("p1")],