hpcflow 0.1.9__py3-none-any.whl → 0.2.0a271__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 (275) hide show
  1. hpcflow/__init__.py +2 -11
  2. hpcflow/__pyinstaller/__init__.py +5 -0
  3. hpcflow/__pyinstaller/hook-hpcflow.py +40 -0
  4. hpcflow/_version.py +1 -1
  5. hpcflow/app.py +43 -0
  6. hpcflow/cli.py +2 -462
  7. hpcflow/data/demo_data_manifest/__init__.py +3 -0
  8. hpcflow/data/demo_data_manifest/demo_data_manifest.json +6 -0
  9. hpcflow/data/jinja_templates/test/test_template.txt +8 -0
  10. hpcflow/data/programs/hello_world/README.md +1 -0
  11. hpcflow/data/programs/hello_world/hello_world.c +87 -0
  12. hpcflow/data/programs/hello_world/linux/hello_world +0 -0
  13. hpcflow/data/programs/hello_world/macos/hello_world +0 -0
  14. hpcflow/data/programs/hello_world/win/hello_world.exe +0 -0
  15. hpcflow/data/scripts/__init__.py +1 -0
  16. hpcflow/data/scripts/bad_script.py +2 -0
  17. hpcflow/data/scripts/demo_task_1_generate_t1_infile_1.py +8 -0
  18. hpcflow/data/scripts/demo_task_1_generate_t1_infile_2.py +8 -0
  19. hpcflow/data/scripts/demo_task_1_parse_p3.py +7 -0
  20. hpcflow/data/scripts/do_nothing.py +2 -0
  21. hpcflow/data/scripts/env_specifier_test/input_file_generator_pass_env_spec.py +4 -0
  22. hpcflow/data/scripts/env_specifier_test/main_script_test_pass_env_spec.py +8 -0
  23. hpcflow/data/scripts/env_specifier_test/output_file_parser_pass_env_spec.py +4 -0
  24. hpcflow/data/scripts/env_specifier_test/v1/input_file_generator_basic.py +4 -0
  25. hpcflow/data/scripts/env_specifier_test/v1/main_script_test_direct_in_direct_out.py +7 -0
  26. hpcflow/data/scripts/env_specifier_test/v1/output_file_parser_basic.py +4 -0
  27. hpcflow/data/scripts/env_specifier_test/v2/main_script_test_direct_in_direct_out.py +7 -0
  28. hpcflow/data/scripts/generate_t1_file_01.py +7 -0
  29. hpcflow/data/scripts/import_future_script.py +7 -0
  30. hpcflow/data/scripts/input_file_generator_basic.py +3 -0
  31. hpcflow/data/scripts/input_file_generator_basic_FAIL.py +3 -0
  32. hpcflow/data/scripts/input_file_generator_test_stdout_stderr.py +8 -0
  33. hpcflow/data/scripts/main_script_test_direct_in.py +3 -0
  34. hpcflow/data/scripts/main_script_test_direct_in_direct_out.py +6 -0
  35. hpcflow/data/scripts/main_script_test_direct_in_direct_out_2.py +6 -0
  36. hpcflow/data/scripts/main_script_test_direct_in_direct_out_2_fail_allowed.py +6 -0
  37. hpcflow/data/scripts/main_script_test_direct_in_direct_out_2_fail_allowed_group.py +7 -0
  38. hpcflow/data/scripts/main_script_test_direct_in_direct_out_3.py +6 -0
  39. hpcflow/data/scripts/main_script_test_direct_in_direct_out_all_iters_test.py +15 -0
  40. hpcflow/data/scripts/main_script_test_direct_in_direct_out_env_spec.py +7 -0
  41. hpcflow/data/scripts/main_script_test_direct_in_direct_out_labels.py +8 -0
  42. hpcflow/data/scripts/main_script_test_direct_in_group_direct_out_3.py +6 -0
  43. hpcflow/data/scripts/main_script_test_direct_in_group_one_fail_direct_out_3.py +6 -0
  44. hpcflow/data/scripts/main_script_test_direct_sub_param_in_direct_out.py +6 -0
  45. hpcflow/data/scripts/main_script_test_hdf5_in_obj.py +12 -0
  46. hpcflow/data/scripts/main_script_test_hdf5_in_obj_2.py +12 -0
  47. hpcflow/data/scripts/main_script_test_hdf5_in_obj_group.py +12 -0
  48. hpcflow/data/scripts/main_script_test_hdf5_out_obj.py +11 -0
  49. hpcflow/data/scripts/main_script_test_json_and_direct_in_json_out.py +14 -0
  50. hpcflow/data/scripts/main_script_test_json_in_json_and_direct_out.py +17 -0
  51. hpcflow/data/scripts/main_script_test_json_in_json_out.py +14 -0
  52. hpcflow/data/scripts/main_script_test_json_in_json_out_labels.py +16 -0
  53. hpcflow/data/scripts/main_script_test_json_in_obj.py +12 -0
  54. hpcflow/data/scripts/main_script_test_json_out_FAIL.py +3 -0
  55. hpcflow/data/scripts/main_script_test_json_out_obj.py +10 -0
  56. hpcflow/data/scripts/main_script_test_json_sub_param_in_json_out_labels.py +16 -0
  57. hpcflow/data/scripts/main_script_test_shell_env_vars.py +12 -0
  58. hpcflow/data/scripts/main_script_test_std_out_std_err.py +6 -0
  59. hpcflow/data/scripts/output_file_parser_basic.py +3 -0
  60. hpcflow/data/scripts/output_file_parser_basic_FAIL.py +7 -0
  61. hpcflow/data/scripts/output_file_parser_test_stdout_stderr.py +8 -0
  62. hpcflow/data/scripts/parse_t1_file_01.py +4 -0
  63. hpcflow/data/scripts/script_exit_test.py +5 -0
  64. hpcflow/data/template_components/__init__.py +1 -0
  65. hpcflow/data/template_components/command_files.yaml +26 -0
  66. hpcflow/data/template_components/environments.yaml +13 -0
  67. hpcflow/data/template_components/parameters.yaml +14 -0
  68. hpcflow/data/template_components/task_schemas.yaml +139 -0
  69. hpcflow/data/workflows/workflow_1.yaml +5 -0
  70. hpcflow/examples.ipynb +1037 -0
  71. hpcflow/sdk/__init__.py +149 -0
  72. hpcflow/sdk/app.py +4266 -0
  73. hpcflow/sdk/cli.py +1479 -0
  74. hpcflow/sdk/cli_common.py +385 -0
  75. hpcflow/sdk/config/__init__.py +5 -0
  76. hpcflow/sdk/config/callbacks.py +246 -0
  77. hpcflow/sdk/config/cli.py +388 -0
  78. hpcflow/sdk/config/config.py +1410 -0
  79. hpcflow/sdk/config/config_file.py +501 -0
  80. hpcflow/sdk/config/errors.py +272 -0
  81. hpcflow/sdk/config/types.py +150 -0
  82. hpcflow/sdk/core/__init__.py +38 -0
  83. hpcflow/sdk/core/actions.py +3857 -0
  84. hpcflow/sdk/core/app_aware.py +25 -0
  85. hpcflow/sdk/core/cache.py +224 -0
  86. hpcflow/sdk/core/command_files.py +814 -0
  87. hpcflow/sdk/core/commands.py +424 -0
  88. hpcflow/sdk/core/element.py +2071 -0
  89. hpcflow/sdk/core/enums.py +221 -0
  90. hpcflow/sdk/core/environment.py +256 -0
  91. hpcflow/sdk/core/errors.py +1043 -0
  92. hpcflow/sdk/core/execute.py +207 -0
  93. hpcflow/sdk/core/json_like.py +809 -0
  94. hpcflow/sdk/core/loop.py +1320 -0
  95. hpcflow/sdk/core/loop_cache.py +282 -0
  96. hpcflow/sdk/core/object_list.py +933 -0
  97. hpcflow/sdk/core/parameters.py +3371 -0
  98. hpcflow/sdk/core/rule.py +196 -0
  99. hpcflow/sdk/core/run_dir_files.py +57 -0
  100. hpcflow/sdk/core/skip_reason.py +7 -0
  101. hpcflow/sdk/core/task.py +3792 -0
  102. hpcflow/sdk/core/task_schema.py +993 -0
  103. hpcflow/sdk/core/test_utils.py +538 -0
  104. hpcflow/sdk/core/types.py +447 -0
  105. hpcflow/sdk/core/utils.py +1207 -0
  106. hpcflow/sdk/core/validation.py +87 -0
  107. hpcflow/sdk/core/values.py +477 -0
  108. hpcflow/sdk/core/workflow.py +4820 -0
  109. hpcflow/sdk/core/zarr_io.py +206 -0
  110. hpcflow/sdk/data/__init__.py +13 -0
  111. hpcflow/sdk/data/config_file_schema.yaml +34 -0
  112. hpcflow/sdk/data/config_schema.yaml +260 -0
  113. hpcflow/sdk/data/environments_spec_schema.yaml +21 -0
  114. hpcflow/sdk/data/files_spec_schema.yaml +5 -0
  115. hpcflow/sdk/data/parameters_spec_schema.yaml +7 -0
  116. hpcflow/sdk/data/task_schema_spec_schema.yaml +3 -0
  117. hpcflow/sdk/data/workflow_spec_schema.yaml +22 -0
  118. hpcflow/sdk/demo/__init__.py +3 -0
  119. hpcflow/sdk/demo/cli.py +242 -0
  120. hpcflow/sdk/helper/__init__.py +3 -0
  121. hpcflow/sdk/helper/cli.py +137 -0
  122. hpcflow/sdk/helper/helper.py +300 -0
  123. hpcflow/sdk/helper/watcher.py +192 -0
  124. hpcflow/sdk/log.py +288 -0
  125. hpcflow/sdk/persistence/__init__.py +18 -0
  126. hpcflow/sdk/persistence/base.py +2817 -0
  127. hpcflow/sdk/persistence/defaults.py +6 -0
  128. hpcflow/sdk/persistence/discovery.py +39 -0
  129. hpcflow/sdk/persistence/json.py +954 -0
  130. hpcflow/sdk/persistence/pending.py +948 -0
  131. hpcflow/sdk/persistence/store_resource.py +203 -0
  132. hpcflow/sdk/persistence/types.py +309 -0
  133. hpcflow/sdk/persistence/utils.py +73 -0
  134. hpcflow/sdk/persistence/zarr.py +2388 -0
  135. hpcflow/sdk/runtime.py +320 -0
  136. hpcflow/sdk/submission/__init__.py +3 -0
  137. hpcflow/sdk/submission/enums.py +70 -0
  138. hpcflow/sdk/submission/jobscript.py +2379 -0
  139. hpcflow/sdk/submission/schedulers/__init__.py +281 -0
  140. hpcflow/sdk/submission/schedulers/direct.py +233 -0
  141. hpcflow/sdk/submission/schedulers/sge.py +376 -0
  142. hpcflow/sdk/submission/schedulers/slurm.py +598 -0
  143. hpcflow/sdk/submission/schedulers/utils.py +25 -0
  144. hpcflow/sdk/submission/shells/__init__.py +52 -0
  145. hpcflow/sdk/submission/shells/base.py +229 -0
  146. hpcflow/sdk/submission/shells/bash.py +504 -0
  147. hpcflow/sdk/submission/shells/os_version.py +115 -0
  148. hpcflow/sdk/submission/shells/powershell.py +352 -0
  149. hpcflow/sdk/submission/submission.py +1402 -0
  150. hpcflow/sdk/submission/types.py +140 -0
  151. hpcflow/sdk/typing.py +194 -0
  152. hpcflow/sdk/utils/arrays.py +69 -0
  153. hpcflow/sdk/utils/deferred_file.py +55 -0
  154. hpcflow/sdk/utils/hashing.py +16 -0
  155. hpcflow/sdk/utils/patches.py +31 -0
  156. hpcflow/sdk/utils/strings.py +69 -0
  157. hpcflow/tests/api/test_api.py +32 -0
  158. hpcflow/tests/conftest.py +123 -0
  159. hpcflow/tests/data/__init__.py +0 -0
  160. hpcflow/tests/data/benchmark_N_elements.yaml +6 -0
  161. hpcflow/tests/data/benchmark_script_runner.yaml +26 -0
  162. hpcflow/tests/data/multi_path_sequences.yaml +29 -0
  163. hpcflow/tests/data/workflow_1.json +10 -0
  164. hpcflow/tests/data/workflow_1.yaml +5 -0
  165. hpcflow/tests/data/workflow_1_slurm.yaml +8 -0
  166. hpcflow/tests/data/workflow_1_wsl.yaml +8 -0
  167. hpcflow/tests/data/workflow_test_run_abort.yaml +42 -0
  168. hpcflow/tests/jinja_templates/test_jinja_templates.py +161 -0
  169. hpcflow/tests/programs/test_programs.py +180 -0
  170. hpcflow/tests/schedulers/direct_linux/test_direct_linux_submission.py +12 -0
  171. hpcflow/tests/schedulers/sge/test_sge_submission.py +36 -0
  172. hpcflow/tests/schedulers/slurm/test_slurm_submission.py +14 -0
  173. hpcflow/tests/scripts/test_input_file_generators.py +282 -0
  174. hpcflow/tests/scripts/test_main_scripts.py +1361 -0
  175. hpcflow/tests/scripts/test_non_snippet_script.py +46 -0
  176. hpcflow/tests/scripts/test_ouput_file_parsers.py +353 -0
  177. hpcflow/tests/shells/wsl/test_wsl_submission.py +14 -0
  178. hpcflow/tests/unit/test_action.py +1066 -0
  179. hpcflow/tests/unit/test_action_rule.py +24 -0
  180. hpcflow/tests/unit/test_app.py +132 -0
  181. hpcflow/tests/unit/test_cache.py +46 -0
  182. hpcflow/tests/unit/test_cli.py +172 -0
  183. hpcflow/tests/unit/test_command.py +377 -0
  184. hpcflow/tests/unit/test_config.py +195 -0
  185. hpcflow/tests/unit/test_config_file.py +162 -0
  186. hpcflow/tests/unit/test_element.py +666 -0
  187. hpcflow/tests/unit/test_element_iteration.py +88 -0
  188. hpcflow/tests/unit/test_element_set.py +158 -0
  189. hpcflow/tests/unit/test_group.py +115 -0
  190. hpcflow/tests/unit/test_input_source.py +1479 -0
  191. hpcflow/tests/unit/test_input_value.py +398 -0
  192. hpcflow/tests/unit/test_jobscript_unit.py +757 -0
  193. hpcflow/tests/unit/test_json_like.py +1247 -0
  194. hpcflow/tests/unit/test_loop.py +2674 -0
  195. hpcflow/tests/unit/test_meta_task.py +325 -0
  196. hpcflow/tests/unit/test_multi_path_sequences.py +259 -0
  197. hpcflow/tests/unit/test_object_list.py +116 -0
  198. hpcflow/tests/unit/test_parameter.py +243 -0
  199. hpcflow/tests/unit/test_persistence.py +664 -0
  200. hpcflow/tests/unit/test_resources.py +243 -0
  201. hpcflow/tests/unit/test_run.py +286 -0
  202. hpcflow/tests/unit/test_run_directories.py +29 -0
  203. hpcflow/tests/unit/test_runtime.py +9 -0
  204. hpcflow/tests/unit/test_schema_input.py +372 -0
  205. hpcflow/tests/unit/test_shell.py +129 -0
  206. hpcflow/tests/unit/test_slurm.py +39 -0
  207. hpcflow/tests/unit/test_submission.py +502 -0
  208. hpcflow/tests/unit/test_task.py +2560 -0
  209. hpcflow/tests/unit/test_task_schema.py +182 -0
  210. hpcflow/tests/unit/test_utils.py +616 -0
  211. hpcflow/tests/unit/test_value_sequence.py +549 -0
  212. hpcflow/tests/unit/test_values.py +91 -0
  213. hpcflow/tests/unit/test_workflow.py +827 -0
  214. hpcflow/tests/unit/test_workflow_template.py +186 -0
  215. hpcflow/tests/unit/utils/test_arrays.py +40 -0
  216. hpcflow/tests/unit/utils/test_deferred_file_writer.py +34 -0
  217. hpcflow/tests/unit/utils/test_hashing.py +65 -0
  218. hpcflow/tests/unit/utils/test_patches.py +5 -0
  219. hpcflow/tests/unit/utils/test_redirect_std.py +50 -0
  220. hpcflow/tests/unit/utils/test_strings.py +97 -0
  221. hpcflow/tests/workflows/__init__.py +0 -0
  222. hpcflow/tests/workflows/test_directory_structure.py +31 -0
  223. hpcflow/tests/workflows/test_jobscript.py +355 -0
  224. hpcflow/tests/workflows/test_run_status.py +198 -0
  225. hpcflow/tests/workflows/test_skip_downstream.py +696 -0
  226. hpcflow/tests/workflows/test_submission.py +140 -0
  227. hpcflow/tests/workflows/test_workflows.py +564 -0
  228. hpcflow/tests/workflows/test_zip.py +18 -0
  229. hpcflow/viz_demo.ipynb +6794 -0
  230. hpcflow-0.2.0a271.dist-info/LICENSE +375 -0
  231. hpcflow-0.2.0a271.dist-info/METADATA +65 -0
  232. hpcflow-0.2.0a271.dist-info/RECORD +237 -0
  233. {hpcflow-0.1.9.dist-info → hpcflow-0.2.0a271.dist-info}/WHEEL +4 -5
  234. hpcflow-0.2.0a271.dist-info/entry_points.txt +6 -0
  235. hpcflow/api.py +0 -458
  236. hpcflow/archive/archive.py +0 -308
  237. hpcflow/archive/cloud/cloud.py +0 -47
  238. hpcflow/archive/cloud/errors.py +0 -9
  239. hpcflow/archive/cloud/providers/dropbox.py +0 -432
  240. hpcflow/archive/errors.py +0 -5
  241. hpcflow/base_db.py +0 -4
  242. hpcflow/config.py +0 -232
  243. hpcflow/copytree.py +0 -66
  244. hpcflow/data/examples/_config.yml +0 -14
  245. hpcflow/data/examples/damask/demo/1.run.yml +0 -4
  246. hpcflow/data/examples/damask/demo/2.process.yml +0 -29
  247. hpcflow/data/examples/damask/demo/geom.geom +0 -2052
  248. hpcflow/data/examples/damask/demo/load.load +0 -1
  249. hpcflow/data/examples/damask/demo/material.config +0 -185
  250. hpcflow/data/examples/damask/inputs/geom.geom +0 -2052
  251. hpcflow/data/examples/damask/inputs/load.load +0 -1
  252. hpcflow/data/examples/damask/inputs/material.config +0 -185
  253. hpcflow/data/examples/damask/profiles/_variable_lookup.yml +0 -21
  254. hpcflow/data/examples/damask/profiles/damask.yml +0 -4
  255. hpcflow/data/examples/damask/profiles/damask_process.yml +0 -8
  256. hpcflow/data/examples/damask/profiles/damask_run.yml +0 -5
  257. hpcflow/data/examples/damask/profiles/default.yml +0 -6
  258. hpcflow/data/examples/thinking.yml +0 -177
  259. hpcflow/errors.py +0 -2
  260. hpcflow/init_db.py +0 -37
  261. hpcflow/models.py +0 -2549
  262. hpcflow/nesting.py +0 -9
  263. hpcflow/profiles.py +0 -455
  264. hpcflow/project.py +0 -81
  265. hpcflow/scheduler.py +0 -323
  266. hpcflow/utils.py +0 -103
  267. hpcflow/validation.py +0 -167
  268. hpcflow/variables.py +0 -544
  269. hpcflow-0.1.9.dist-info/METADATA +0 -168
  270. hpcflow-0.1.9.dist-info/RECORD +0 -45
  271. hpcflow-0.1.9.dist-info/entry_points.txt +0 -8
  272. hpcflow-0.1.9.dist-info/top_level.txt +0 -1
  273. /hpcflow/{archive → data/jinja_templates}/__init__.py +0 -0
  274. /hpcflow/{archive/cloud → data/programs}/__init__.py +0 -0
  275. /hpcflow/{archive/cloud/providers → data/workflows}/__init__.py +0 -0
@@ -0,0 +1,123 @@
1
+ from __future__ import annotations
2
+ from pathlib import Path
3
+ import pytest
4
+ from hpcflow.app import app as hf
5
+
6
+
7
+ def pytest_addoption(parser: pytest.Parser):
8
+ parser.addoption(
9
+ "--slurm",
10
+ action="store_true",
11
+ default=False,
12
+ help="run slurm tests",
13
+ )
14
+ parser.addoption(
15
+ "--wsl",
16
+ action="store_true",
17
+ default=False,
18
+ help="run Windows Subsystem for Linux tests",
19
+ )
20
+ parser.addoption(
21
+ "--direct-linux",
22
+ action="store_true",
23
+ default=False,
24
+ help="run direct-linux submission tests",
25
+ )
26
+ parser.addoption(
27
+ "--integration",
28
+ action="store_true",
29
+ default=False,
30
+ help="run integration-like workflow submission tests",
31
+ )
32
+ parser.addoption(
33
+ "--repeat",
34
+ action="store",
35
+ default=1,
36
+ type=int,
37
+ help="number of times to repeat each test",
38
+ )
39
+
40
+
41
+ def pytest_configure(config: pytest.Config):
42
+ config.addinivalue_line("markers", "slurm: mark test as slurm to run")
43
+ config.addinivalue_line("markers", "wsl: mark test as wsl to run")
44
+ config.addinivalue_line(
45
+ "markers", "direct_linux: mark test as a direct-linux submission test to run"
46
+ )
47
+ config.addinivalue_line(
48
+ "markers",
49
+ "integration: mark test as an integration-like workflow submission test to run",
50
+ )
51
+ hf.run_time_info.in_pytest = True
52
+
53
+
54
+ def pytest_collection_modifyitems(config: pytest.Config, items: list[pytest.Item]):
55
+ if config.getoption("--slurm"):
56
+ # --slurm given in cli: only run slurm tests
57
+ for item in items:
58
+ if "slurm" not in item.keywords:
59
+ item.add_marker(pytest.mark.skip(reason="need no --slurm option to run"))
60
+ elif config.getoption("--wsl"):
61
+ # --wsl given in CLI: only run wsl tests
62
+ for item in items:
63
+ if "wsl" not in item.keywords:
64
+ item.add_marker(pytest.mark.skip(reason="need no --wsl option to run"))
65
+ elif config.getoption("--direct-linux"):
66
+ # --direct-linux in CLI: only run these tests
67
+ for item in items:
68
+ if "direct_linux" not in item.keywords:
69
+ item.add_marker(
70
+ pytest.mark.skip(reason="remove --direct-linux option to run")
71
+ )
72
+ elif config.getoption("--integration"):
73
+ # --integration in CLI: only run these tests
74
+ for item in items:
75
+ if "integration" not in item.keywords:
76
+ item.add_marker(
77
+ pytest.mark.skip(reason="remove --integration option to run")
78
+ )
79
+ else:
80
+ # --slurm not given in cli: skip slurm tests and do not skip other tests
81
+ for item in items:
82
+ if "slurm" in item.keywords:
83
+ item.add_marker(pytest.mark.skip(reason="need --slurm option to run"))
84
+ elif "wsl" in item.keywords:
85
+ item.add_marker(pytest.mark.skip(reason="need --wsl option to run"))
86
+ elif "direct_linux" in item.keywords:
87
+ item.add_marker(
88
+ pytest.mark.skip(reason="add --direct_linux option to run")
89
+ )
90
+ elif "integration" in item.keywords:
91
+ item.add_marker(
92
+ pytest.mark.skip(reason="add --integration option to run")
93
+ )
94
+
95
+
96
+ def pytest_unconfigure(config: pytest.Config):
97
+ hf.run_time_info.in_pytest = False
98
+
99
+
100
+ @pytest.fixture
101
+ def null_config(tmp_path: Path):
102
+ if not hf.is_config_loaded:
103
+ hf.load_config(config_dir=tmp_path)
104
+ hf.run_time_info.in_pytest = True
105
+
106
+
107
+ @pytest.fixture
108
+ def new_null_config(tmp_path: Path):
109
+ hf.load_config(config_dir=tmp_path, warn=False)
110
+ hf.load_template_components(warn=False)
111
+ hf.run_time_info.in_pytest = True
112
+
113
+
114
+ @pytest.fixture
115
+ def unload_config():
116
+ hf.unload_config()
117
+
118
+
119
+ def pytest_generate_tests(metafunc):
120
+ repeats_num = int(metafunc.config.getoption("--repeat"))
121
+ if repeats_num > 1:
122
+ metafunc.fixturenames.append("tmp_ct")
123
+ metafunc.parametrize("tmp_ct", range(repeats_num))
File without changes
@@ -0,0 +1,6 @@
1
+ name: workflow_1
2
+ tasks:
3
+ - schema: test_t1_conditional_OS
4
+ repeats: <<var:N>>
5
+ inputs:
6
+ p1: 101
@@ -0,0 +1,26 @@
1
+ doc: |
2
+ A workflow for benchmarking the overhead introduced by hpcflow in running a Python
3
+ script `N` times.
4
+
5
+ template_components:
6
+ task_schemas:
7
+ - objective: run_script
8
+ inputs:
9
+ - parameter: p1
10
+ outputs:
11
+ - parameter: p2
12
+ actions:
13
+ - environments:
14
+ - scope:
15
+ type: any
16
+ environment: python_env
17
+ script: <<script:main_script_test_direct_in_direct_out.py>>
18
+ script_exe: python_script
19
+ script_data_in: direct
20
+ script_data_out: direct
21
+
22
+ tasks:
23
+ - schema: run_script
24
+ inputs:
25
+ p1: 101
26
+ repeats: <<var:N[default=1]>>
@@ -0,0 +1,29 @@
1
+ template_components:
2
+ task_schemas:
3
+ - objective: add_p1_components
4
+ inputs:
5
+ - parameter: p1
6
+ outputs:
7
+ - parameter: p2
8
+ actions:
9
+ - rules:
10
+ - path: resources.os_name
11
+ condition: { value.equal_to: posix }
12
+ commands:
13
+ - command: echo "$((<<parameter:p1.a>> + <<parameter:p1.b>>))"
14
+ stdout: <<int(parameter:p2)>>
15
+ - rules:
16
+ - path: resources.os_name
17
+ condition: { value.equal_to: nt }
18
+ commands:
19
+ - command: Write-Output ((<<parameter:p1.a>> + <<parameter:p1.b>>))
20
+ stdout: <<int(parameter:p2)>>
21
+ tasks:
22
+ - schema: add_p1_components
23
+ inputs:
24
+ p1: {}
25
+ multi_path_sequences:
26
+ - paths: [inputs.p1.a, inputs.p1.b]
27
+ values:
28
+ - [101, 102]
29
+ - [201, 202]
@@ -0,0 +1,10 @@
1
+ {
2
+ "tasks": [
3
+ {
4
+ "schema": "test_t1_conditional_OS",
5
+ "inputs": {
6
+ "p1": 101
7
+ }
8
+ }
9
+ ]
10
+ }
@@ -0,0 +1,5 @@
1
+ name: workflow_1
2
+ tasks:
3
+ - schema: test_t1_conditional_OS
4
+ inputs:
5
+ p1: 101
@@ -0,0 +1,8 @@
1
+ name: workflow_1
2
+ resources:
3
+ any:
4
+ scheduler: slurm
5
+ tasks:
6
+ - schema: test_t1_conditional_OS
7
+ inputs:
8
+ p1: 101
@@ -0,0 +1,8 @@
1
+ name: workflow_1
2
+ resources:
3
+ any:
4
+ shell: WSL
5
+ tasks:
6
+ - schema: test_t1_bash
7
+ inputs:
8
+ p1: 101
@@ -0,0 +1,42 @@
1
+ doc: |
2
+ A workflow to sleep a specified number of seconds, and then set an output parameter
3
+ `is_finished` to the string "true". This is used for testing the run-abort
4
+ functionality.
5
+
6
+ template_components:
7
+ task_schemas:
8
+ - objective: sleep
9
+ inputs:
10
+ - parameter: sleep_time_seconds
11
+ outputs:
12
+ - parameter: is_finished
13
+ actions:
14
+ - abortable: true
15
+ rules:
16
+ - path: resources.os_name
17
+ condition: { value.equal_to: posix }
18
+ commands:
19
+ - command: sleep <<parameter:sleep_time_seconds>>
20
+ - abortable: true
21
+ rules:
22
+ - path: resources.os_name
23
+ condition: { value.equal_to: nt }
24
+ commands:
25
+ - command: Start-Sleep <<parameter:sleep_time_seconds>>
26
+ - rules:
27
+ - path: resources.os_name
28
+ condition: { value.equal_to: posix }
29
+ commands:
30
+ - command: echo "true"
31
+ stdout: <<parameter:is_finished>>
32
+ - rules:
33
+ - path: resources.os_name
34
+ condition: { value.equal_to: nt }
35
+ commands:
36
+ - command: Write-Output "true"
37
+ stdout: <<parameter:is_finished>>
38
+
39
+ tasks:
40
+ - schema: sleep
41
+ inputs:
42
+ sleep_time_seconds: 300 # 5 minutes
@@ -0,0 +1,161 @@
1
+ import os
2
+ from textwrap import dedent
3
+ import hpcflow.app as hf
4
+
5
+ import pytest
6
+
7
+
8
+ @pytest.mark.integration
9
+ def test_basic_jinja_template(null_config, tmp_path):
10
+ jinja_template_name = "test_template.txt"
11
+ s1 = hf.TaskSchema(
12
+ objective="t1",
13
+ inputs=[
14
+ hf.SchemaInput(parameter=hf.Parameter("name")),
15
+ hf.SchemaInput(parameter=hf.Parameter("fruits")),
16
+ ],
17
+ actions=[hf.Action(jinja_template=f"test/{jinja_template_name}")],
18
+ )
19
+ t1 = hf.Task(schema=s1, inputs={"name": "George", "fruits": ["apple", "orange"]})
20
+ wk = hf.Workflow.from_template_data(
21
+ tasks=[t1],
22
+ template_name="jinja_template_test",
23
+ path=tmp_path,
24
+ )
25
+ wk.submit(wait=True, add_to_known=False, status=False)
26
+ run_dir = wk.get_all_EARs()[0].get_directory()
27
+ rendered = run_dir.joinpath(jinja_template_name)
28
+
29
+ expected = dedent(
30
+ """\
31
+ Hola, George!
32
+
33
+ This is a template, with a loop. Here are your specified fruits:
34
+ - apple
35
+ - orange
36
+ """
37
+ )
38
+
39
+ assert rendered.is_file()
40
+ assert rendered.read_text() == expected
41
+
42
+
43
+ @pytest.mark.integration
44
+ def test_jinja_template_path_with_resource_var(null_config, tmp_path):
45
+ jinja_template_name = "test_template.txt"
46
+ s1 = hf.TaskSchema(
47
+ objective="t1",
48
+ inputs=[
49
+ hf.SchemaInput(parameter=hf.Parameter("name")),
50
+ hf.SchemaInput(parameter=hf.Parameter("fruits")),
51
+ ],
52
+ actions=[
53
+ hf.Action(jinja_template=f"<<resource:resources_id>>/{jinja_template_name}")
54
+ ],
55
+ )
56
+ t1 = hf.Task(schema=s1, inputs={"name": "George", "fruits": ["apple", "orange"]})
57
+ wk = hf.Workflow.from_template_data(
58
+ tasks=[t1],
59
+ template_name="jinja_template_test",
60
+ path=tmp_path,
61
+ resources={"any": {"resources_id": "test"}},
62
+ )
63
+ wk.submit(wait=True, add_to_known=False, status=False)
64
+ run_dir = wk.get_all_EARs()[0].get_directory()
65
+ rendered = run_dir.joinpath(jinja_template_name)
66
+
67
+ expected = dedent(
68
+ """\
69
+ Hola, George!
70
+
71
+ This is a template, with a loop. Here are your specified fruits:
72
+ - apple
73
+ - orange
74
+ """
75
+ )
76
+
77
+ assert rendered.is_file()
78
+ assert rendered.read_text() == expected
79
+
80
+
81
+ @pytest.mark.integration
82
+ def test_builtin_jinja_template_path_with_env_var(new_null_config, tmp_path):
83
+ env = hf.Environment(
84
+ name="null_env",
85
+ specifiers={"key": "test"}, # reference this specifier in the jinja template path
86
+ executables=[],
87
+ )
88
+ hf.envs.add_object(env, skip_duplicates=True)
89
+
90
+ jinja_template_name = "test_template.txt"
91
+ s1 = hf.TaskSchema(
92
+ objective="t1",
93
+ inputs=[
94
+ hf.SchemaInput(parameter=hf.Parameter("name")),
95
+ hf.SchemaInput(parameter=hf.Parameter("fruits")),
96
+ ],
97
+ actions=[hf.Action(jinja_template=f"<<env:key>>/{jinja_template_name}")],
98
+ )
99
+ t1 = hf.Task(schema=s1, inputs={"name": "George", "fruits": ["apple", "orange"]})
100
+ wk = hf.Workflow.from_template_data(
101
+ tasks=[t1],
102
+ template_name="jinja_template_test",
103
+ path=tmp_path,
104
+ environments={"null_env": {"key": "test"}},
105
+ )
106
+ wk.submit(wait=True, add_to_known=False, status=False)
107
+ run_dir = wk.get_all_EARs()[0].get_directory()
108
+ rendered = run_dir.joinpath(jinja_template_name)
109
+
110
+ expected = dedent(
111
+ """\
112
+ Hola, George!
113
+
114
+ This is a template, with a loop. Here are your specified fruits:
115
+ - apple
116
+ - orange
117
+ """
118
+ )
119
+
120
+ assert rendered.is_file()
121
+ assert rendered.read_text() == expected
122
+
123
+ hf.reload_template_components() # remove extra env
124
+
125
+
126
+ @pytest.mark.integration
127
+ def test_builtin_jinja_template_path_with_param_var(new_null_config, tmp_path):
128
+ jinja_template_name = "test_template.txt"
129
+ s1 = hf.TaskSchema(
130
+ objective="t1",
131
+ inputs=[
132
+ hf.SchemaInput(parameter=hf.Parameter("name")),
133
+ hf.SchemaInput(parameter=hf.Parameter("fruits")),
134
+ hf.SchemaInput(parameter=hf.Parameter("key")),
135
+ ],
136
+ actions=[hf.Action(jinja_template=f"<<parameter:key>>/{jinja_template_name}")],
137
+ )
138
+ t1 = hf.Task(
139
+ schema=s1, inputs={"name": "George", "fruits": ["apple", "orange"], "key": "test"}
140
+ )
141
+ wk = hf.Workflow.from_template_data(
142
+ tasks=[t1],
143
+ template_name="jinja_template_test",
144
+ path=tmp_path,
145
+ )
146
+ wk.submit(wait=True, add_to_known=False, status=False)
147
+ run_dir = wk.get_all_EARs()[0].get_directory()
148
+ rendered = run_dir.joinpath(jinja_template_name)
149
+
150
+ expected = dedent(
151
+ """\
152
+ Hola, George!
153
+
154
+ This is a template, with a loop. Here are your specified fruits:
155
+ - apple
156
+ - orange
157
+ """
158
+ )
159
+
160
+ assert rendered.is_file()
161
+ assert rendered.read_text() == expected
@@ -0,0 +1,180 @@
1
+ import os
2
+ import pytest
3
+
4
+ import hpcflow.app as hf
5
+
6
+
7
+ @pytest.mark.integration
8
+ def test_builtin_program_no_args_resource_var(new_null_config, tmp_path):
9
+ # run a builtin program
10
+ env_cmd = ("& " if os.name == "nt" else "") + "<<program_path>> <<args>>"
11
+ env = hf.Environment(
12
+ name="program_env",
13
+ executables=[
14
+ hf.Executable(
15
+ label="hello_world",
16
+ instances=[
17
+ hf.ExecutableInstance(
18
+ command=env_cmd,
19
+ num_cores=1,
20
+ parallel_mode=None,
21
+ )
22
+ ],
23
+ )
24
+ ],
25
+ )
26
+ hf.envs.add_object(env, skip_duplicates=True)
27
+
28
+ act = hf.Action(
29
+ program="hello_world/<<resource:platform>>/hello_world<<resource:executable_extension>>",
30
+ program_exe="hello_world",
31
+ environments=[hf.ActionEnvironment("program_env")],
32
+ )
33
+ s1 = hf.TaskSchema(objective="hello", actions=[act])
34
+ tasks = [hf.Task(s1)]
35
+ wk = hf.Workflow.from_template_data(
36
+ template_name="test_program_no_args",
37
+ tasks=tasks,
38
+ path=tmp_path,
39
+ )
40
+ wk.submit(wait=True, status=False)
41
+ assert wk.submissions[0].jobscripts[0].get_stdout().strip() == "hello, world"
42
+
43
+ hf.reload_template_components() # remove extra env
44
+
45
+
46
+ @pytest.mark.integration
47
+ def test_builtin_program_no_args_env_var(new_null_config, tmp_path):
48
+ # run a builtin program
49
+ env_cmd = ("& " if os.name == "nt" else "") + "<<program_path>> <<args>>"
50
+ default_platform = hf.ElementResources.get_default_platform()
51
+ env = hf.Environment(
52
+ name="program_env",
53
+ specifiers={
54
+ "platform": default_platform
55
+ }, # reference this specifier in the program path
56
+ executables=[
57
+ hf.Executable(
58
+ label="hello_world",
59
+ instances=[
60
+ hf.ExecutableInstance(
61
+ command=env_cmd,
62
+ num_cores=1,
63
+ parallel_mode=None,
64
+ )
65
+ ],
66
+ )
67
+ ],
68
+ )
69
+ hf.envs.add_object(env, skip_duplicates=True)
70
+
71
+ act = hf.Action(
72
+ program="hello_world/<<env:platform>>/hello_world<<resource:executable_extension>>",
73
+ program_exe="hello_world",
74
+ environments=[hf.ActionEnvironment("program_env")],
75
+ )
76
+ s1 = hf.TaskSchema(objective="hello", actions=[act])
77
+ tasks = [hf.Task(s1)]
78
+ wk = hf.Workflow.from_template_data(
79
+ template_name="test_program_no_args",
80
+ environments={"program_env": {"platform": default_platform}},
81
+ tasks=tasks,
82
+ path=tmp_path,
83
+ )
84
+ wk.submit(wait=True, status=False)
85
+ assert wk.submissions[0].jobscripts[0].get_stdout().strip() == "hello, world"
86
+
87
+ hf.reload_template_components() # remove extra env
88
+
89
+
90
+ @pytest.mark.integration
91
+ def test_builtin_program_no_args_param_var(new_null_config, tmp_path):
92
+ # run a builtin program
93
+ env_cmd = ("& " if os.name == "nt" else "") + "<<program_path>> <<args>>"
94
+ default_platform = hf.ElementResources.get_default_platform()
95
+ env = hf.Environment(
96
+ name="program_env",
97
+ executables=[
98
+ hf.Executable(
99
+ label="hello_world",
100
+ instances=[
101
+ hf.ExecutableInstance(
102
+ command=env_cmd,
103
+ num_cores=1,
104
+ parallel_mode=None,
105
+ )
106
+ ],
107
+ )
108
+ ],
109
+ )
110
+ hf.envs.add_object(env, skip_duplicates=True)
111
+
112
+ act = hf.Action(
113
+ program="hello_world/<<parameter:platform>>/hello_world<<resource:executable_extension>>",
114
+ program_exe="hello_world",
115
+ environments=[hf.ActionEnvironment("program_env")],
116
+ )
117
+ s1 = hf.TaskSchema(
118
+ objective="hello",
119
+ actions=[act],
120
+ inputs=[hf.SchemaInput("platform")],
121
+ )
122
+ tasks = [hf.Task(s1, inputs={"platform": default_platform})]
123
+ wk = hf.Workflow.from_template_data(
124
+ template_name="test_program_no_args",
125
+ tasks=tasks,
126
+ path=tmp_path,
127
+ )
128
+ wk.submit(wait=True, status=False)
129
+ assert wk.submissions[0].jobscripts[0].get_stdout().strip() == "hello, world"
130
+
131
+ hf.reload_template_components() # remove extra env
132
+
133
+
134
+ @pytest.mark.integration
135
+ def test_builtin_program_input_output_JSON_resource_var(new_null_config, tmp_path):
136
+ # run a builtin program that expects input and output JSON file paths as a cmdline arguments
137
+ env_cmd = ("& " if os.name == "nt" else "") + "<<program_path>> <<args>>"
138
+ env = hf.Environment(
139
+ name="program_env",
140
+ executables=[
141
+ hf.Executable(
142
+ label="hello_world",
143
+ instances=[
144
+ hf.ExecutableInstance(
145
+ command=env_cmd,
146
+ num_cores=1,
147
+ parallel_mode=None,
148
+ )
149
+ ],
150
+ )
151
+ ],
152
+ )
153
+ hf.envs.add_object(env, skip_duplicates=True)
154
+
155
+ act = hf.Action(
156
+ program="hello_world/<<resource:platform>>/hello_world<<resource:executable_extension>>",
157
+ program_exe="hello_world",
158
+ program_data_in="json",
159
+ program_data_out="json",
160
+ requires_dir=True,
161
+ environments=[hf.ActionEnvironment("program_env")],
162
+ )
163
+ s1 = hf.TaskSchema(
164
+ objective="hello",
165
+ inputs=[hf.SchemaInput("p1"), hf.SchemaInput("p2"), hf.SchemaInput("p3")],
166
+ outputs=[hf.SchemaInput("p4")],
167
+ actions=[act],
168
+ )
169
+ p1, p2, p3 = 1, 2, 3
170
+ tasks = [hf.Task(s1, inputs={"p1": p1, "p2": p2, "p3": p3})]
171
+ wk = hf.Workflow.from_template_data(
172
+ template_name="test_program_input_output_files",
173
+ tasks=tasks,
174
+ path=tmp_path,
175
+ )
176
+ wk.submit(wait=True, status=False)
177
+ assert wk.submissions[0].jobscripts[0].get_stdout().strip() == "hello, world"
178
+ assert wk.tasks[0].elements[0].get("outputs.p4") == p1 + p2 + p3
179
+
180
+ hf.reload_template_components() # remove extra env
@@ -0,0 +1,12 @@
1
+ from importlib import resources
2
+ import pytest
3
+ from hpcflow.app import app as hf
4
+
5
+
6
+ @pytest.mark.direct_linux
7
+ def test_workflow_1(tmp_path, null_config):
8
+ act = hf.Action(commands=[hf.Command("echo 'Buenas!'")])
9
+ ts = hf.TaskSchema(objective="hello", actions=[act])
10
+ wkt = hf.WorkflowTemplate(name="greetings", tasks=[hf.Task(schema=ts)])
11
+ wf = hf.Workflow.from_template(name="saludos", template=wkt)
12
+ wf.submit(wait=True, add_to_known=False)
@@ -0,0 +1,36 @@
1
+ import pytest
2
+ from hpcflow.app import app as hf
3
+
4
+
5
+ def test_SGE_process_resources_multi_core_with_parallel_env(null_config):
6
+
7
+ scheduler_config = {
8
+ "parallel_environments": {
9
+ None: {"num_cores": [1, 1, 1]}, # [start, step, stop]
10
+ "my_parallel_env": {"num_cores": [2, 1, 32]},
11
+ }
12
+ }
13
+
14
+ scheduler = hf.SGEPosix()
15
+ resources = hf.ElementResources(num_cores=2, SGE_parallel_env="my_parallel_env")
16
+
17
+ scheduler.process_resources(resources, scheduler_config)
18
+
19
+ assert resources.num_cores == 2
20
+ assert resources.SGE_parallel_env == "my_parallel_env"
21
+
22
+
23
+ def test_SGE_process_resources_raises_on_single_core_with_parallel_env(null_config):
24
+
25
+ scheduler_config = {
26
+ "parallel_environments": {
27
+ None: {"num_cores": [1, 1, 1]}, # [start, step, stop]
28
+ "my_parallel_env": {"num_cores": [2, 1, 32]},
29
+ }
30
+ }
31
+
32
+ scheduler = hf.SGEPosix()
33
+ resources = hf.ElementResources(num_cores=1, SGE_parallel_env="my_parallel_env")
34
+
35
+ with pytest.raises(ValueError):
36
+ scheduler.process_resources(resources, scheduler_config)
@@ -0,0 +1,14 @@
1
+ from pathlib import Path
2
+ import pytest
3
+ from hpcflow.app import app as hf
4
+ from hpcflow.sdk.core.test_utils import make_test_data_YAML_workflow
5
+
6
+
7
+ @pytest.mark.slurm
8
+ def test_workflow_1(tmp_path: Path, null_config):
9
+ hf.config.add_scheduler("slurm")
10
+ wk = make_test_data_YAML_workflow("workflow_1_slurm.yaml", path=tmp_path)
11
+ wk.submit(wait=True, add_to_known=False)
12
+ p2 = wk.tasks[0].elements[0].outputs.p2
13
+ assert isinstance(p2, hf.ElementParameter)
14
+ assert p2.value == "201"