hpcflow-new2 0.2.0a163__py3-none-any.whl → 0.2.0a166__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/sdk/core/actions.py +24 -7
- hpcflow/sdk/core/commands.py +14 -2
- hpcflow/sdk/core/errors.py +16 -0
- hpcflow/sdk/core/parameters.py +26 -2
- hpcflow/sdk/core/task.py +209 -59
- hpcflow/sdk/core/task_schema.py +1 -1
- hpcflow/sdk/persistence/base.py +6 -0
- hpcflow/sdk/persistence/zarr.py +2 -0
- hpcflow/tests/unit/test_action.py +170 -0
- hpcflow/tests/unit/test_element_set.py +10 -0
- hpcflow/tests/unit/test_input_source.py +601 -1
- hpcflow/tests/unit/test_persistence.py +4 -1
- hpcflow/tests/unit/test_task.py +1 -1
- {hpcflow_new2-0.2.0a163.dist-info → hpcflow_new2-0.2.0a166.dist-info}/METADATA +1 -1
- {hpcflow_new2-0.2.0a163.dist-info → hpcflow_new2-0.2.0a166.dist-info}/RECORD +18 -18
- {hpcflow_new2-0.2.0a163.dist-info → hpcflow_new2-0.2.0a166.dist-info}/WHEEL +0 -0
- {hpcflow_new2-0.2.0a163.dist-info → hpcflow_new2-0.2.0a166.dist-info}/entry_points.txt +0 -0
@@ -618,3 +618,173 @@ def test_ActionEnvironment_env_dict(null_config):
|
|
618
618
|
def test_ActionEnvironment_raises_on_missing_name(null_config):
|
619
619
|
with pytest.raises(ActionEnvironmentMissingNameError):
|
620
620
|
hf.ActionEnvironment(environment={"key": "value"})
|
621
|
+
|
622
|
+
|
623
|
+
def test_rules_allow_runs_initialised(null_config, tmp_path):
|
624
|
+
"""Test rules that do not depend on execution allow for runs to be initialised."""
|
625
|
+
act = hf.Action(
|
626
|
+
script="<<script:path/to/some/script>>",
|
627
|
+
rules=[hf.ActionRule(path="inputs.p1", condition={"value.less_than": 2})],
|
628
|
+
)
|
629
|
+
ts = hf.TaskSchema(
|
630
|
+
objective="ts1",
|
631
|
+
inputs=[hf.SchemaInput("p1")],
|
632
|
+
actions=[act],
|
633
|
+
)
|
634
|
+
t1 = hf.Task(
|
635
|
+
schema=ts, sequences=[hf.ValueSequence(path="inputs.p1", values=[1.5, 2.5])]
|
636
|
+
)
|
637
|
+
wk = hf.Workflow.from_template_data(
|
638
|
+
template_name="test",
|
639
|
+
path=tmp_path,
|
640
|
+
tasks=[t1],
|
641
|
+
)
|
642
|
+
assert wk.tasks[0].elements[0].iterations[0].EARs_initialised
|
643
|
+
assert wk.tasks[0].elements[1].iterations[0].EARs_initialised
|
644
|
+
assert len(wk.tasks[0].elements[0].actions) == 1
|
645
|
+
assert len(wk.tasks[0].elements[1].actions) == 0
|
646
|
+
|
647
|
+
|
648
|
+
def test_rules_prevent_runs_initialised(null_config, tmp_path):
|
649
|
+
"""Test rules that depend on execution prevent initialising runs."""
|
650
|
+
act1 = hf.Action(script="<<script:path/to/some/script>>")
|
651
|
+
act2 = hf.Action(
|
652
|
+
script="<<script:path/to/some/script>>",
|
653
|
+
rules=[hf.ActionRule(path="inputs.p2", condition={"value.less_than": 2})],
|
654
|
+
)
|
655
|
+
ts1 = hf.TaskSchema(
|
656
|
+
objective="ts1",
|
657
|
+
inputs=[hf.SchemaInput("p1")],
|
658
|
+
outputs=[hf.SchemaOutput("p2")],
|
659
|
+
actions=[act1],
|
660
|
+
)
|
661
|
+
ts2 = hf.TaskSchema(
|
662
|
+
objective="ts2",
|
663
|
+
inputs=[hf.SchemaInput("p2")],
|
664
|
+
actions=[act2],
|
665
|
+
)
|
666
|
+
t1 = hf.Task(schema=ts1, inputs={"p1": 1.2})
|
667
|
+
t2 = hf.Task(schema=ts2)
|
668
|
+
wk = hf.Workflow.from_template_data(
|
669
|
+
template_name="test",
|
670
|
+
path=tmp_path,
|
671
|
+
tasks=[t1, t2],
|
672
|
+
)
|
673
|
+
assert wk.tasks[0].elements[0].iterations[0].EARs_initialised
|
674
|
+
assert not wk.tasks[1].elements[0].iterations[0].EARs_initialised
|
675
|
+
|
676
|
+
|
677
|
+
def test_command_rules_allow_runs_initialised(null_config, tmp_path):
|
678
|
+
"""Test command rules that do not depend on execution allow for runs to be
|
679
|
+
initialised."""
|
680
|
+
act = hf.Action(
|
681
|
+
commands=[
|
682
|
+
hf.Command(
|
683
|
+
command='echo "p1=<<parameter:p1>>"',
|
684
|
+
rules=[hf.ActionRule(path="inputs.p1", condition={"value.less_than": 2})],
|
685
|
+
)
|
686
|
+
],
|
687
|
+
)
|
688
|
+
ts = hf.TaskSchema(
|
689
|
+
objective="ts1",
|
690
|
+
inputs=[hf.SchemaInput("p1")],
|
691
|
+
actions=[act],
|
692
|
+
)
|
693
|
+
t1 = hf.Task(
|
694
|
+
schema=ts, sequences=[hf.ValueSequence(path="inputs.p1", values=[1.5, 2.5])]
|
695
|
+
)
|
696
|
+
wk = hf.Workflow.from_template_data(
|
697
|
+
template_name="test",
|
698
|
+
path=tmp_path,
|
699
|
+
tasks=[t1],
|
700
|
+
)
|
701
|
+
assert wk.tasks[0].elements[0].iterations[0].EARs_initialised
|
702
|
+
assert wk.tasks[0].elements[1].iterations[0].EARs_initialised
|
703
|
+
assert len(wk.tasks[0].elements[0].actions) == 1
|
704
|
+
assert len(wk.tasks[0].elements[1].actions) == 1
|
705
|
+
assert len(wk.tasks[0].elements[0].action_runs[0].commands_idx) == 1
|
706
|
+
assert len(wk.tasks[0].elements[1].action_runs[0].commands_idx) == 0
|
707
|
+
|
708
|
+
|
709
|
+
def test_command_rules_prevent_runs_initialised(null_config, tmp_path):
|
710
|
+
"""Test command rules that do depend on execution prevent runs being initialised."""
|
711
|
+
act1 = hf.Action(
|
712
|
+
commands=[
|
713
|
+
hf.Command(command='echo "p1=<<parameter:p1>>"', stdout="<<parameter:p2>>")
|
714
|
+
]
|
715
|
+
)
|
716
|
+
act2 = hf.Action(
|
717
|
+
commands=[
|
718
|
+
hf.Command(
|
719
|
+
command='echo "p1=<<parameter:p2>>"',
|
720
|
+
rules=[hf.ActionRule(path="inputs.p2", condition={"value.less_than": 2})],
|
721
|
+
)
|
722
|
+
],
|
723
|
+
)
|
724
|
+
ts1 = hf.TaskSchema(
|
725
|
+
objective="ts1",
|
726
|
+
inputs=[hf.SchemaInput("p1")],
|
727
|
+
outputs=[hf.SchemaOutput("p2")],
|
728
|
+
actions=[act1],
|
729
|
+
)
|
730
|
+
ts2 = hf.TaskSchema(
|
731
|
+
objective="ts2",
|
732
|
+
inputs=[hf.SchemaInput("p2")],
|
733
|
+
actions=[act2],
|
734
|
+
)
|
735
|
+
t1 = hf.Task(schema=ts1, inputs={"p1": 0})
|
736
|
+
t2 = hf.Task(schema=ts2)
|
737
|
+
wk = hf.Workflow.from_template_data(
|
738
|
+
template_name="test",
|
739
|
+
path=tmp_path,
|
740
|
+
tasks=[t1, t2],
|
741
|
+
)
|
742
|
+
assert wk.tasks[0].elements[0].iterations[0].EARs_initialised
|
743
|
+
assert len(wk.tasks[0].elements[0].action_runs[0].commands_idx) == 1
|
744
|
+
assert not wk.tasks[1].elements[0].iterations[0].EARs_initialised
|
745
|
+
|
746
|
+
|
747
|
+
def test_command_rules_prevent_runs_initialised_with_valid_action_rules(
|
748
|
+
null_config, tmp_path
|
749
|
+
):
|
750
|
+
"""Test command rules that do depend on execution prevent runs being initialised, even
|
751
|
+
when the parent action rules can be tested and are valid."""
|
752
|
+
act1 = hf.Action(
|
753
|
+
commands=[
|
754
|
+
hf.Command(command='echo "p1=<<parameter:p1>>"', stdout="<<parameter:p2>>")
|
755
|
+
]
|
756
|
+
)
|
757
|
+
|
758
|
+
# action rule is testable and valid, but command rule is not testable, so the action
|
759
|
+
# runs should not be initialised:
|
760
|
+
act2 = hf.Action(
|
761
|
+
commands=[
|
762
|
+
hf.Command(
|
763
|
+
command='echo "p1=<<parameter:p1>>; p2=<<parameter:p2>>"',
|
764
|
+
rules=[hf.ActionRule(path="inputs.p2", condition={"value.less_than": 2})],
|
765
|
+
)
|
766
|
+
],
|
767
|
+
rules=[hf.ActionRule(path="inputs.p1", condition={"value.less_than": 2})],
|
768
|
+
)
|
769
|
+
ts1 = hf.TaskSchema(
|
770
|
+
objective="ts1",
|
771
|
+
inputs=[hf.SchemaInput("p1")],
|
772
|
+
outputs=[hf.SchemaOutput("p2")],
|
773
|
+
actions=[act1],
|
774
|
+
)
|
775
|
+
ts2 = hf.TaskSchema(
|
776
|
+
objective="ts2",
|
777
|
+
inputs=[hf.SchemaInput("p1"), hf.SchemaInput("p2")],
|
778
|
+
actions=[act2],
|
779
|
+
)
|
780
|
+
t1 = hf.Task(schema=ts1, inputs={"p1": 0})
|
781
|
+
t2 = hf.Task(schema=ts2)
|
782
|
+
wk = hf.Workflow.from_template_data(
|
783
|
+
template_name="test",
|
784
|
+
path=tmp_path,
|
785
|
+
tasks=[t1, t2],
|
786
|
+
)
|
787
|
+
assert wk.tasks[0].elements[0].iterations[0].EARs_initialised
|
788
|
+
assert len(wk.tasks[0].elements[0].action_runs[0].commands_idx) == 1
|
789
|
+
|
790
|
+
assert not wk.tasks[1].elements[0].iterations[0].EARs_initialised
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import pytest
|
2
2
|
from hpcflow.app import app as hf
|
3
|
+
from hpcflow.sdk.core.errors import MalformedNestingOrderPath
|
3
4
|
|
4
5
|
|
5
6
|
@pytest.fixture
|
@@ -101,3 +102,12 @@ def test_merge_envs_no_envs_with_resource_envs(null_config):
|
|
101
102
|
def test_raise_env_and_envs_specified(null_config):
|
102
103
|
with pytest.raises(ValueError):
|
103
104
|
hf.ElementSet(env_preset="my_preset", environments={"my_env": {"version": 1}})
|
105
|
+
|
106
|
+
|
107
|
+
def test_nesting_order_paths_raise(null_config):
|
108
|
+
with pytest.raises(MalformedNestingOrderPath):
|
109
|
+
hf.ElementSet(nesting_order={"bad_path.p1": 1})
|
110
|
+
|
111
|
+
|
112
|
+
def test_nesting_order_paths_no_raise(null_config):
|
113
|
+
hf.ElementSet(nesting_order={"inputs.p1": 1, "resources.any": 2, "repeats": 3})
|