hpcflow-new2 0.2.0a162__py3-none-any.whl → 0.2.0a163__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 (34) hide show
  1. hpcflow/_version.py +1 -1
  2. hpcflow/data/scripts/main_script_test_direct_in_direct_out_env_spec.py +7 -0
  3. hpcflow/sdk/app.py +29 -42
  4. hpcflow/sdk/cli.py +1 -1
  5. hpcflow/sdk/core/actions.py +63 -14
  6. hpcflow/sdk/core/command_files.py +6 -4
  7. hpcflow/sdk/core/commands.py +7 -0
  8. hpcflow/sdk/core/element.py +39 -8
  9. hpcflow/sdk/core/errors.py +16 -0
  10. hpcflow/sdk/core/object_list.py +26 -14
  11. hpcflow/sdk/core/parameters.py +21 -3
  12. hpcflow/sdk/core/task.py +107 -2
  13. hpcflow/sdk/core/task_schema.py +16 -1
  14. hpcflow/sdk/core/test_utils.py +5 -2
  15. hpcflow/sdk/core/workflow.py +93 -5
  16. hpcflow/sdk/data/workflow_spec_schema.yaml +14 -58
  17. hpcflow/sdk/demo/cli.py +1 -1
  18. hpcflow/sdk/submission/submission.py +21 -10
  19. hpcflow/tests/scripts/test_main_scripts.py +60 -0
  20. hpcflow/tests/unit/test_action.py +16 -0
  21. hpcflow/tests/unit/test_element.py +27 -25
  22. hpcflow/tests/unit/test_element_set.py +32 -0
  23. hpcflow/tests/unit/test_parameter.py +11 -9
  24. hpcflow/tests/unit/test_resources.py +7 -9
  25. hpcflow/tests/unit/test_schema_input.py +8 -8
  26. hpcflow/tests/unit/test_task.py +26 -27
  27. hpcflow/tests/unit/test_task_schema.py +39 -8
  28. hpcflow/tests/unit/test_value_sequence.py +5 -0
  29. hpcflow/tests/unit/test_workflow.py +4 -9
  30. hpcflow/tests/unit/test_workflow_template.py +122 -1
  31. {hpcflow_new2-0.2.0a162.dist-info → hpcflow_new2-0.2.0a163.dist-info}/METADATA +1 -1
  32. {hpcflow_new2-0.2.0a162.dist-info → hpcflow_new2-0.2.0a163.dist-info}/RECORD +34 -33
  33. {hpcflow_new2-0.2.0a162.dist-info → hpcflow_new2-0.2.0a163.dist-info}/WHEEL +0 -0
  34. {hpcflow_new2-0.2.0a162.dist-info → hpcflow_new2-0.2.0a163.dist-info}/entry_points.txt +0 -0
@@ -519,11 +519,12 @@ def test_element_get_group_sequence(null_config, tmp_path):
519
519
  wkt_yaml = dedent(
520
520
  """\
521
521
  name: test_list_idx_sequence
522
- task_schemas:
523
- - objective: test_group_schema
524
- inputs:
525
- - parameter: p1
526
- group: my_group
522
+ template_components:
523
+ task_schemas:
524
+ - objective: test_group_schema
525
+ inputs:
526
+ - parameter: p1
527
+ group: my_group
527
528
  tasks:
528
529
  - schema: test_t1_ps
529
530
  inputs:
@@ -556,26 +557,27 @@ def test_element_get_group_sequence_obj(new_null_config, tmp_path):
556
557
  wkt_yaml = dedent(
557
558
  """\
558
559
  name: test_list_idx_sequence
559
- task_schemas:
560
- - objective: test_t1_ps_obj
561
- parameter_class_modules: ["hpcflow.sdk.core.test_utils"]
562
- inputs:
563
- - parameter: p1c
564
- outputs:
565
- - parameter: p2
566
- actions:
567
- - environments:
568
- - scope:
569
- type: any
570
- environment: null_env
571
- commands:
572
- - command: Write-Output ((<<parameter:p1c>> + 100))
573
- stdout: <<parameter:p2>>
574
- - objective: test_group_schema
575
- parameter_class_modules: ["hpcflow.sdk.core.test_utils"]
576
- inputs:
577
- - parameter: p1c
578
- group: my_group
560
+ template_components:
561
+ task_schemas:
562
+ - objective: test_t1_ps_obj
563
+ parameter_class_modules: ["hpcflow.sdk.core.test_utils"]
564
+ inputs:
565
+ - parameter: p1c
566
+ outputs:
567
+ - parameter: p2
568
+ actions:
569
+ - environments:
570
+ - scope:
571
+ type: any
572
+ environment: null_env
573
+ commands:
574
+ - command: Write-Output ((<<parameter:p1c>> + 100))
575
+ stdout: <<parameter:p2>>
576
+ - objective: test_group_schema
577
+ parameter_class_modules: ["hpcflow.sdk.core.test_utils"]
578
+ inputs:
579
+ - parameter: p1c
580
+ group: my_group
579
581
 
580
582
  tasks:
581
583
  - schema: test_t1_ps_obj
@@ -69,3 +69,35 @@ def test_repeats_single_int_equivalence(null_config):
69
69
  es1 = hf.ElementSet(repeats=2)
70
70
  es2 = hf.ElementSet(repeats=[{"name": "", "number": 2, "nesting_order": 0}])
71
71
  assert es1 == es2
72
+
73
+
74
+ def test_merge_envs(null_config):
75
+ envs = {"my_env": {"version": "1.0"}}
76
+ es = hf.ElementSet(environments=envs)
77
+ assert es.resources.get(scope=hf.ActionScope.any()).environments == envs
78
+
79
+
80
+ def test_merge_envs_existing_any_resources(null_config):
81
+ envs = {"my_env": {"version": "1.0"}}
82
+ num_cores = 2
83
+ es = hf.ElementSet(resources={"any": {"num_cores": num_cores}}, environments=envs)
84
+ assert es.resources.get(scope=hf.ActionScope.any()).environments == envs
85
+ assert es.resources.get(scope=hf.ActionScope.any()).num_cores == num_cores
86
+
87
+
88
+ def test_merge_envs_resource_envs_precedence(null_config):
89
+ envs = {"my_env": {"version": "1.0"}}
90
+ res_envs = {"other_env": {"version": "2.0"}}
91
+ es = hf.ElementSet(resources={"any": {"environments": res_envs}}, environments=envs)
92
+ assert es.resources.get(scope=hf.ActionScope.any()).environments == res_envs
93
+
94
+
95
+ def test_merge_envs_no_envs_with_resource_envs(null_config):
96
+ envs = {"my_env": {"version": "1.0"}}
97
+ es = hf.ElementSet(resources={"any": {"environments": envs}})
98
+ assert es.resources.get(scope=hf.ActionScope.any()).environments == envs
99
+
100
+
101
+ def test_raise_env_and_envs_specified(null_config):
102
+ with pytest.raises(ValueError):
103
+ hf.ElementSet(env_preset="my_preset", environments={"my_env": {"version": 1}})
@@ -152,11 +152,12 @@ def test_demo_data_substitution_param_value_class_method(new_null_config, tmp_pa
152
152
  yaml_str = dedent(
153
153
  """\
154
154
  name: temp
155
- task_schemas:
156
- - objective: test
157
- inputs:
158
- - parameter: p1c
159
- parameter_class_modules: [hpcflow.sdk.core.test_utils]
155
+ template_components:
156
+ task_schemas:
157
+ - objective: test
158
+ inputs:
159
+ - parameter: p1c
160
+ parameter_class_modules: [hpcflow.sdk.core.test_utils]
160
161
  tasks:
161
162
  - schema: test
162
163
  inputs:
@@ -174,10 +175,11 @@ def test_demo_data_substitution_value_sequence_class_method(new_null_config, tmp
174
175
  yaml_str = dedent(
175
176
  """\
176
177
  name: temp
177
- task_schemas:
178
- - objective: test
179
- inputs:
180
- - parameter: p1
178
+ template_components:
179
+ task_schemas:
180
+ - objective: test
181
+ inputs:
182
+ - parameter: p1
181
183
  tasks:
182
184
  - schema: test
183
185
  sequences:
@@ -29,33 +29,31 @@ def test_resource_list_raise_on_identical_scopes():
29
29
  hf.ResourceList.normalise([{"scope": "any"}, {"scope": "any"}])
30
30
 
31
31
 
32
- def test_merge_template_resources_same_scope():
32
+ def test_merge_other_same_scope():
33
33
  res_lst_1 = hf.ResourceList.from_json_like({"any": {"num_cores": 1}})
34
34
  res_lst_2 = hf.ResourceList.from_json_like({"any": {}})
35
- res_lst_2.merge_template_resources(res_lst_1)
35
+ res_lst_2.merge_other(res_lst_1)
36
36
  assert res_lst_2 == hf.ResourceList.from_json_like({"any": {"num_cores": 1}})
37
37
 
38
38
 
39
- def test_merge_template_resources_same_scope_no_overwrite():
39
+ def test_merge_other_same_scope_no_overwrite():
40
40
  res_lst_1 = hf.ResourceList.from_json_like({"any": {"num_cores": 1}})
41
41
  res_lst_2 = hf.ResourceList.from_json_like({"any": {"num_cores": 2}})
42
- res_lst_2.merge_template_resources(res_lst_1)
42
+ res_lst_2.merge_other(res_lst_1)
43
43
  assert res_lst_2 == hf.ResourceList.from_json_like({"any": {"num_cores": 2}})
44
44
 
45
45
 
46
- def test_merge_template_resources_multi_scope():
46
+ def test_merge_other_multi_scope():
47
47
  res_lst_1 = hf.ResourceList.from_json_like({"any": {"num_cores": 1}})
48
48
  res_lst_2 = hf.ResourceList.from_json_like({"any": {}, "main": {"num_cores": 3}})
49
- res_lst_2.merge_template_resources(res_lst_1)
49
+ res_lst_2.merge_other(res_lst_1)
50
50
  assert res_lst_2 == hf.ResourceList.from_json_like(
51
51
  {"any": {"num_cores": 1}, "main": {"num_cores": 3}}
52
52
  )
53
53
 
54
54
 
55
55
  @pytest.mark.parametrize("store", ["json", "zarr"])
56
- def test_merge_template_resources_persistent_workflow_reload(
57
- null_config, tmp_path, store
58
- ):
56
+ def test_merge_other_persistent_workflow_reload(null_config, tmp_path, store):
59
57
  wkt = hf.WorkflowTemplate(
60
58
  name="test_load",
61
59
  resources={"any": {"num_cores": 2}},
@@ -69,7 +69,7 @@ def test_element_inputs_removes_schema_param_trivial_label(null_config, tmp_path
69
69
  inputs=[hf.SchemaInput(parameter="p1", labels={label: {}})],
70
70
  actions=[
71
71
  hf.Action(
72
- environments=[hf.ActionEnvironment(environment=hf.envs.null_env)],
72
+ environments=[hf.ActionEnvironment("null_env")],
73
73
  commands=[hf.Command(command=f"echo <<parameter:p1[{label}]>>")],
74
74
  ),
75
75
  ],
@@ -118,7 +118,7 @@ def test_element_inputs_does_not_remove_multiple_schema_param_label(
118
118
  inputs=[hf.SchemaInput(parameter="p1", labels={label: {}}, multiple=True)],
119
119
  actions=[
120
120
  hf.Action(
121
- environments=[hf.ActionEnvironment(environment=hf.envs.null_env)],
121
+ environments=[hf.ActionEnvironment("null_env")],
122
122
  commands=[hf.Command(command=f"echo <<parameter:p1[{label}]>>")],
123
123
  ),
124
124
  ],
@@ -153,7 +153,7 @@ def test_get_input_values_for_multiple_schema_input_single_label(null_config, tm
153
153
  ],
154
154
  actions=[
155
155
  hf.Action(
156
- environments=[hf.ActionEnvironment(environment=hf.envs.null_env)],
156
+ environments=[hf.ActionEnvironment("null_env")],
157
157
  commands=[
158
158
  hf.Command(command=f"echo <<parameter:p1[{label}]>> <<parameter:p2>>")
159
159
  ],
@@ -180,7 +180,7 @@ def test_get_input_values_subset(null_config, tmp_path):
180
180
  ],
181
181
  actions=[
182
182
  hf.Action(
183
- environments=[hf.ActionEnvironment(environment=hf.envs.null_env)],
183
+ environments=[hf.ActionEnvironment("null_env")],
184
184
  commands=[hf.Command(command=f"echo <<parameter:p1>> <<parameter:p2>>")],
185
185
  ),
186
186
  ],
@@ -210,7 +210,7 @@ def test_get_input_values_subset_labelled_label_dict_False(null_config, tmp_path
210
210
  ],
211
211
  actions=[
212
212
  hf.Action(
213
- environments=[hf.ActionEnvironment(environment=hf.envs.null_env)],
213
+ environments=[hf.ActionEnvironment("null_env")],
214
214
  commands=[
215
215
  hf.Command(
216
216
  command=f"echo <<parameter:p1[one]>> <<parameter:p2[two]>>"
@@ -244,7 +244,7 @@ def test_get_input_values_subset_labelled_label_dict_True(null_config, tmp_path)
244
244
  ],
245
245
  actions=[
246
246
  hf.Action(
247
- environments=[hf.ActionEnvironment(environment=hf.envs.null_env)],
247
+ environments=[hf.ActionEnvironment("null_env")],
248
248
  commands=[
249
249
  hf.Command(
250
250
  command=f"echo <<parameter:p1[one]>> <<parameter:p2[two]>>"
@@ -276,7 +276,7 @@ def test_get_input_values_for_multiple_schema_input(null_config, tmp_path):
276
276
  ],
277
277
  actions=[
278
278
  hf.Action(
279
- environments=[hf.ActionEnvironment(environment=hf.envs.null_env)],
279
+ environments=[hf.ActionEnvironment("null_env")],
280
280
  commands=[
281
281
  hf.Command(command=f"echo <<parameter:p1[{label}]>> <<parameter:p2>>")
282
282
  ],
@@ -304,7 +304,7 @@ def test_get_input_values_for_multiple_schema_input_with_object(null_config, tmp
304
304
  ],
305
305
  actions=[
306
306
  hf.Action(
307
- environments=[hf.ActionEnvironment(environment=hf.envs.null_env)],
307
+ environments=[hf.ActionEnvironment("null_env")],
308
308
  commands=[
309
309
  hf.Command(
310
310
  command=f"echo <<parameter:p1c[{label}]>> <<parameter:p2>>"
@@ -11,6 +11,7 @@ from hpcflow.sdk.core.errors import (
11
11
  TaskTemplateMultipleInputValues,
12
12
  TaskTemplateMultipleSchemaObjectives,
13
13
  TaskTemplateUnexpectedInput,
14
+ UnknownEnvironmentPresetError,
14
15
  UnsetParameterDataError,
15
16
  )
16
17
  from hpcflow.sdk.core.parameters import NullDefault
@@ -113,13 +114,8 @@ def file_spec_fs1():
113
114
 
114
115
 
115
116
  @pytest.fixture
116
- def env_1():
117
- return hf.Environment(name="env_1")
118
-
119
-
120
- @pytest.fixture
121
- def act_env_1(env_1):
122
- return hf.ActionEnvironment(env_1)
117
+ def act_env_1():
118
+ return hf.ActionEnvironment("env_1")
123
119
 
124
120
 
125
121
  @pytest.fixture
@@ -146,13 +142,8 @@ def workflow_w4(null_config, tmp_path, schema_s3, param_p1):
146
142
 
147
143
 
148
144
  @pytest.fixture
149
- def env_1():
150
- return hf.Environment(name="env_1")
151
-
152
-
153
- @pytest.fixture
154
- def act_env_1(env_1):
155
- return hf.ActionEnvironment(env_1)
145
+ def act_env_1():
146
+ return hf.ActionEnvironment("env_1")
156
147
 
157
148
 
158
149
  @pytest.fixture
@@ -1512,13 +1503,8 @@ def test_add_task_before_no_ref(workflow_w0):
1512
1503
 
1513
1504
 
1514
1505
  @pytest.fixture
1515
- def env_1():
1516
- return hf.Environment(name="env_1")
1517
-
1518
-
1519
- @pytest.fixture
1520
- def act_env_1(env_1):
1521
- return hf.ActionEnvironment(env_1)
1506
+ def act_env_1():
1507
+ return hf.ActionEnvironment("env_1")
1522
1508
 
1523
1509
 
1524
1510
  def test_parameter_two_modifying_actions_expected_data_indices(
@@ -1572,7 +1558,7 @@ def test_conditional_shell_schema_single_initialised_action(null_config, tmp_pat
1572
1558
  outputs=[hf.SchemaInput("p2")],
1573
1559
  actions=[
1574
1560
  hf.Action(
1575
- environments=[hf.ActionEnvironment(environment=hf.envs.null_env)],
1561
+ environments=[hf.ActionEnvironment("null_env")],
1576
1562
  commands=[
1577
1563
  hf.Command(
1578
1564
  command="echo $((<<parameter:p1>> + 100))",
@@ -1582,7 +1568,7 @@ def test_conditional_shell_schema_single_initialised_action(null_config, tmp_pat
1582
1568
  rules=[rules["posix"]],
1583
1569
  ),
1584
1570
  hf.Action(
1585
- environments=[hf.ActionEnvironment(environment=hf.envs.null_env)],
1571
+ environments=[hf.ActionEnvironment("null_env")],
1586
1572
  commands=[
1587
1573
  hf.Command(
1588
1574
  command="Write-Output ((<<parameter:p1>> + 100))",
@@ -1617,7 +1603,7 @@ def test_element_iteration_EARs_initialised_on_make_workflow(
1617
1603
  outputs=[hf.SchemaInput("p2")],
1618
1604
  actions=[
1619
1605
  hf.Action(
1620
- environments=[hf.ActionEnvironment(environment=hf.envs.null_env)],
1606
+ environments=[hf.ActionEnvironment("null_env")],
1621
1607
  commands=[
1622
1608
  hf.Command(
1623
1609
  command="echo $((<<parameter:p1>> + 100))",
@@ -1670,7 +1656,7 @@ def test_element_iteration_EARs_not_initialised_on_make_workflow_due_to_unset(
1670
1656
  outputs=[hf.SchemaInput("p2")],
1671
1657
  actions=[
1672
1658
  hf.Action(
1673
- environments=[hf.ActionEnvironment(environment=hf.envs.null_env)],
1659
+ environments=[hf.ActionEnvironment("null_env")],
1674
1660
  commands=[
1675
1661
  hf.Command(
1676
1662
  command="echo $((<<parameter:p1>> + 100))",
@@ -1686,7 +1672,7 @@ def test_element_iteration_EARs_not_initialised_on_make_workflow_due_to_unset(
1686
1672
  outputs=[hf.SchemaInput("p3")],
1687
1673
  actions=[
1688
1674
  hf.Action(
1689
- environments=[hf.ActionEnvironment(environment=hf.envs.null_env)],
1675
+ environments=[hf.ActionEnvironment("null_env")],
1690
1676
  commands=[
1691
1677
  hf.Command(
1692
1678
  command="echo $((<<parameter:p2>> + 100))",
@@ -1729,7 +1715,7 @@ def test_element_iteration_EARs_initialised_on_make_workflow_with_no_valid_actio
1729
1715
  outputs=[hf.SchemaInput("p2")],
1730
1716
  actions=[
1731
1717
  hf.Action(
1732
- environments=[hf.ActionEnvironment(environment=hf.envs.null_env)],
1718
+ environments=[hf.ActionEnvironment("null_env")],
1733
1719
  commands=[
1734
1720
  hf.Command(
1735
1721
  command="some command that uses <<parameter:p1>>",
@@ -2177,3 +2163,16 @@ def test_labelled_input_values_specified_by_dict(null_config):
2177
2163
  )
2178
2164
  t2 = hf.Task(schema=ts, inputs={"p1[one]": 101})
2179
2165
  assert t1 == t2
2166
+
2167
+
2168
+ def test_raise_UnknownEnvironmentPresetError(null_config):
2169
+ ts = hf.TaskSchema(objective="t1")
2170
+ with pytest.raises(UnknownEnvironmentPresetError):
2171
+ hf.Task(schema=ts, env_preset="my_env_preset")
2172
+
2173
+
2174
+ def test_raise_UnknownEnvironmentPresetError_sequence(null_config):
2175
+ ts = hf.TaskSchema(objective="t1")
2176
+ seq = hf.ValueSequence(path="env_preset", values=["my_env_preset"])
2177
+ with pytest.raises(UnknownEnvironmentPresetError):
2178
+ hf.Task(schema=ts, sequences=[seq])
@@ -1,18 +1,16 @@
1
1
  import pytest
2
2
 
3
3
  from hpcflow.app import app as hf
4
- from hpcflow.sdk.core.errors import InvalidIdentifier
4
+ from hpcflow.sdk.core.errors import (
5
+ EnvironmentPresetUnknownEnvironmentError,
6
+ InvalidIdentifier,
7
+ )
5
8
  from hpcflow.sdk.core.test_utils import make_actions, make_parameters
6
9
 
7
10
 
8
11
  @pytest.fixture
9
- def env_1():
10
- return hf.Environment(name="env_1")
11
-
12
-
13
- @pytest.fixture
14
- def act_env_1(env_1):
15
- return hf.ActionEnvironment(env_1)
12
+ def act_env_1():
13
+ return hf.ActionEnvironment("env_1")
16
14
 
17
15
 
18
16
  @pytest.fixture
@@ -112,3 +110,36 @@ def test_dot_access_object_list_raise_on_bad_access_attr_name():
112
110
  ts = hf.TaskSchema("add_object", actions=[])
113
111
  with pytest.raises(ValueError):
114
112
  hf.TaskSchemasList([ts])
113
+
114
+
115
+ def test_env_preset():
116
+ p1, p2 = make_parameters(2)
117
+ (act_1,) = make_actions([("p1", "p2")], env="env1")
118
+ hf.TaskSchema(
119
+ "t1",
120
+ inputs=[p1],
121
+ outputs=[p2],
122
+ actions=[act_1],
123
+ environment_presets={"my_preset": {"env1": {"version": 1}}},
124
+ )
125
+
126
+
127
+ def test_env_preset_raise_bad_env():
128
+ p1, p2 = make_parameters(2)
129
+ (act_1,) = make_actions([("p1", "p2")], env="env1")
130
+ with pytest.raises(EnvironmentPresetUnknownEnvironmentError):
131
+ hf.TaskSchema(
132
+ "t1",
133
+ inputs=[p1],
134
+ outputs=[p2],
135
+ actions=[act_1],
136
+ environment_presets={"my_preset": {"env2": {"version": 1}}},
137
+ )
138
+
139
+
140
+ def test_env_preset_raise_bad_env_no_actions():
141
+ with pytest.raises(EnvironmentPresetUnknownEnvironmentError):
142
+ hf.TaskSchema(
143
+ "t1",
144
+ environment_presets={"my_preset": {"env1": {"version": 1}}},
145
+ )
@@ -442,3 +442,8 @@ def test_from_rectangle_coord_none(null_config):
442
442
  )
443
443
  seq = hf.ValueSequence.from_rectangle(**kwargs)
444
444
  assert np.allclose(seq.values, [[0, 1], [1, 1], [0, 0], [1, 0]])
445
+
446
+
447
+ def test_environments_sequence_to_resources(null_config):
448
+ seq = hf.ValueSequence(path="environments.my_env.version", values=[1, 2])
449
+ assert seq.path == "resources.any.environments.my_env.version"
@@ -93,13 +93,8 @@ def param_p3(null_config):
93
93
 
94
94
 
95
95
  @pytest.fixture
96
- def env_1(null_config):
97
- return hf.Environment(name="env_1")
98
-
99
-
100
- @pytest.fixture
101
- def act_env_1(null_config, env_1):
102
- return hf.ActionEnvironment(env_1)
96
+ def act_env_1(null_config):
97
+ return hf.ActionEnvironment("env_1")
103
98
 
104
99
 
105
100
  @pytest.fixture
@@ -161,7 +156,7 @@ def schema_s4(
161
156
  inputs=[hf.SchemaInput(parameter=param_p1)],
162
157
  actions=[
163
158
  hf.Action(
164
- environments=[hf.ActionEnvironment(environment=hf.envs.null_env)],
159
+ environments=[hf.ActionEnvironment("null_env")],
165
160
  commands=[hf.Command("Write-Output '<<parameter:p1>>'")],
166
161
  )
167
162
  ],
@@ -178,7 +173,7 @@ def schema_s4c(
178
173
  inputs=[hf.SchemaInput(parameter=param_p1c)],
179
174
  actions=[
180
175
  hf.Action(
181
- environments=[hf.ActionEnvironment(environment=hf.envs.null_env)],
176
+ environments=[hf.ActionEnvironment("null_env")],
182
177
  commands=[hf.Command("Write-Output '<<parameter:p1c>>'")],
183
178
  )
184
179
  ],
@@ -1,5 +1,9 @@
1
+ import pytest
1
2
  from hpcflow.app import app as hf
2
- from hpcflow.sdk.core.test_utils import make_test_data_YAML_workflow_template
3
+ from hpcflow.sdk.core.test_utils import (
4
+ make_schemas,
5
+ make_test_data_YAML_workflow_template,
6
+ )
3
7
 
4
8
 
5
9
  def test_merge_template_level_resources_into_element_set(null_config):
@@ -33,3 +37,120 @@ def test_workflow_template_vars(tmp_path, new_null_config):
33
37
  variables={"N": num_repeats},
34
38
  )
35
39
  assert wkt.tasks[0].element_sets[0].repeats[0]["number"] == num_repeats
40
+
41
+
42
+ def test_env_preset_merge_simple(null_config):
43
+ s1 = hf.TaskSchema(
44
+ objective="s1",
45
+ actions=[hf.Action(environments=[hf.ActionEnvironment("my_env")])],
46
+ environment_presets={"my_env_preset": {"my_env": {"version": 1}}},
47
+ )
48
+ wkt = hf.WorkflowTemplate(
49
+ name="test",
50
+ env_presets="my_env_preset",
51
+ tasks=[hf.Task(schema=s1)],
52
+ )
53
+ assert wkt.tasks[0].element_sets[0].env_preset == "my_env_preset"
54
+ assert wkt.tasks[0].element_sets[0].resources[0].environments == {
55
+ "my_env": {"version": 1}
56
+ }
57
+
58
+
59
+ def test_env_preset_merge_simple_list(null_config):
60
+ s1 = hf.TaskSchema(
61
+ objective="s1",
62
+ actions=[hf.Action(environments=[hf.ActionEnvironment("my_env")])],
63
+ environment_presets={"my_env_preset": {"my_env": {"version": 1}}},
64
+ )
65
+ wkt = hf.WorkflowTemplate(
66
+ name="test",
67
+ env_presets=["my_env_preset", "my_other_env_preset"],
68
+ tasks=[hf.Task(schema=s1)],
69
+ )
70
+ assert wkt.tasks[0].element_sets[0].env_preset == "my_env_preset"
71
+ assert wkt.tasks[0].element_sets[0].resources[0].environments == {
72
+ "my_env": {"version": 1}
73
+ }
74
+
75
+
76
+ def test_env_preset_no_merge_existing_env_preset(null_config):
77
+ s1 = hf.TaskSchema(
78
+ objective="s1",
79
+ actions=[hf.Action(environments=[hf.ActionEnvironment("my_env")])],
80
+ environment_presets={
81
+ "env_preset_1": {"my_env": {"version": 1}},
82
+ "env_preset_2": {"my_env": {"version": 2}},
83
+ },
84
+ )
85
+ wkt = hf.WorkflowTemplate(
86
+ name="test",
87
+ env_presets="env_preset_1",
88
+ tasks=[hf.Task(schema=s1, env_preset="env_preset_2")],
89
+ )
90
+ assert wkt.tasks[0].element_sets[0].env_preset == "env_preset_2"
91
+ assert wkt.tasks[0].element_sets[0].resources[0].environments == {
92
+ "my_env": {"version": 2}
93
+ }
94
+
95
+
96
+ def test_environments_merge_simple(null_config):
97
+ s1 = hf.TaskSchema(
98
+ objective="s1",
99
+ actions=[hf.Action(environments=[hf.ActionEnvironment("my_env")])],
100
+ )
101
+ wkt = hf.WorkflowTemplate(
102
+ name="test",
103
+ environments={"my_env": {"version": 1}, "my_other_env": {"version": 2}},
104
+ tasks=[hf.Task(schema=s1)],
105
+ )
106
+ assert wkt.tasks[0].element_sets[0].environments == {"my_env": {"version": 1}}
107
+ assert wkt.tasks[0].element_sets[0].resources[0].environments == {
108
+ "my_env": {"version": 1}
109
+ }
110
+
111
+
112
+ def test_environments_no_merge_existing_envs(null_config):
113
+ s1 = hf.TaskSchema(
114
+ objective="s1",
115
+ actions=[hf.Action(environments=[hf.ActionEnvironment("my_env")])],
116
+ )
117
+ wkt = hf.WorkflowTemplate(
118
+ name="test",
119
+ environments={"my_env": {"version": 1}, "my_other_env": {"version": 2}},
120
+ tasks=[hf.Task(schema=s1, environments={"my_env": {"version": 2}})],
121
+ )
122
+ assert wkt.tasks[0].element_sets[0].environments == {"my_env": {"version": 2}}
123
+ assert wkt.tasks[0].element_sets[0].resources[0].environments == {
124
+ "my_env": {"version": 2}
125
+ }
126
+
127
+
128
+ def test_raise_on_env_preset_and_environments(null_config):
129
+ with pytest.raises(ValueError):
130
+ wkt = hf.WorkflowTemplate(
131
+ name="test",
132
+ env_presets="my_env_preset",
133
+ environments={"my_env": {"version": 1}},
134
+ )
135
+
136
+
137
+ def test_default_env_preset_used_if_available(null_config):
138
+ """Test that if no env_presets or environments are specified at template-level or task
139
+ level, the default (named as an empty string) env preset is used if available."""
140
+
141
+ s1 = hf.TaskSchema(
142
+ objective="s1",
143
+ actions=[hf.Action(environments=[hf.ActionEnvironment("my_env")])],
144
+ environment_presets={
145
+ "": {"my_env": {"version": 1}},
146
+ "env_preset_1": {"my_env": {"version": 2}},
147
+ },
148
+ )
149
+ wkt = hf.WorkflowTemplate(
150
+ name="test",
151
+ tasks=[hf.Task(schema=s1)],
152
+ )
153
+ assert wkt.tasks[0].element_sets[0].env_preset == ""
154
+ assert wkt.tasks[0].element_sets[0].resources[0].environments == {
155
+ "my_env": {"version": 1}
156
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hpcflow-new2
3
- Version: 0.2.0a162
3
+ Version: 0.2.0a163
4
4
  Summary: Computational workflow management
5
5
  License: MIT
6
6
  Author: aplowman