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
hpcflow/api.py DELETED
@@ -1,458 +0,0 @@
1
- """`hpcflow.api.py`
2
-
3
- This module contains the application programming interface (API) to `hpcflow`,
4
- and includes functions that are called by the command line interface (CLI; in
5
- `hpcflow.cli.py`).
6
-
7
- """
8
-
9
- from pathlib import Path
10
- from pprint import pprint
11
- import json
12
-
13
- from beautifultable import BeautifulTable
14
-
15
- from hpcflow.config import Config
16
- from hpcflow.init_db import init_db
17
- from hpcflow.models import Workflow, Submission, CommandGroupSubmission
18
- from hpcflow.profiles import parse_job_profiles, prepare_workflow_dict
19
- from hpcflow.project import Project
20
- from hpcflow.archive.cloud.cloud import CloudProvider
21
-
22
-
23
- def make_workflow(dir_path=None, profile_list=None, json_file=None, json_str=None,
24
- workflow_dict=None, clean=False, config_dir=None):
25
- """Generate a new Workflow and add it to the local database.
26
-
27
- Parameters
28
- ----------
29
- dir_path : str or Path, optional
30
- The directory in which the Workflow will be generated. By default, this
31
- is the working (i.e. invoking) directory.
32
- profile_list : list of (str or Path), optional
33
- List of YAML profile file paths to use to construct the Workflow. By
34
- default, and if `json_file` and `json_str` and not specified, all
35
- YAML files in the `dir_path` directory that match the profile
36
- specification format in the global configuration will be parsed as
37
- Workflow profiles. If not None, only those profiles listed will be
38
- parsed as Workflow profiles.
39
- json_file : str or Path, optional
40
- Path to a JSON file that represents a Workflow. By default, set to
41
- `None`.
42
- json_str : str, optional
43
- JSON string that represents a Workflow. By default, set to `None`.
44
- workflow_dict : dict, optional
45
- Dict representing the workflow to generate.
46
- clean : bool, optional
47
- If True, all existing hpcflow data will be removed from `dir_path`.
48
- Useful for debugging.
49
-
50
- Returns
51
- -------
52
- workflow_id : int
53
- The insert ID of the Workflow object in the local database.
54
-
55
- Notes
56
- -----
57
- Specify only one of `profile_list`, `json_file` or `json_str`.
58
-
59
- """
60
-
61
- opts = [profile_list, json_file, json_str, workflow_dict]
62
- not_nones = sum([i is not None for i in opts])
63
- if not_nones > 1:
64
- msg = ('Specify only one of `profile_list`, `json_file`, `json_str` or '
65
- '`workflow_dict`.')
66
- raise ValueError(msg)
67
-
68
- project = Project(dir_path, config_dir, clean=clean)
69
-
70
- if json_str:
71
- workflow_dict = json.loads(json_str)
72
-
73
- elif json_file:
74
- json_file = Path(json_file).resolve()
75
- with Path(json_file).open() as handle:
76
- workflow_dict = json.load(handle)
77
-
78
- elif profile_list:
79
- profile_list = [Path(i).resolve() for i in profile_list]
80
- # Get workflow from YAML profiles:
81
- workflow_dict = parse_job_profiles(project.dir_path, profile_list)
82
-
83
- else:
84
- workflow_dict = prepare_workflow_dict(workflow_dict)
85
-
86
- Session = init_db(project, check_exists=False)
87
- session = Session()
88
-
89
- workflow = Workflow(directory=project.dir_path, **workflow_dict)
90
-
91
- session.add(workflow)
92
- session.commit()
93
-
94
- workflow_id = workflow.id_
95
- session.close()
96
-
97
- return workflow_id
98
-
99
-
100
- def submit_workflow(workflow_id, dir_path=None, task_range='all', config_dir=None):
101
- """Submit (part of) a previously generated Workflow.
102
-
103
- Parameters
104
- ----------
105
- workflow_id : int
106
- The ID of the Workflow to submit, as in the local database.
107
- dir_path : str or Path, optional
108
- The directory in which the Workflow exists. By default, this is the working (i.e.
109
- invoking) directory.
110
- task_range : (list of int) or str, optional
111
- Specify which tasks from the initial command group to submit. If a list, it must
112
- have either two or three elements; if it has two elements, these signify the first
113
- and last tasks, inclusively, to submit. By default, the task step size is one, but
114
- this can be chosen as a third list entry. If a string "all", all tasks are
115
- submitted.
116
-
117
- TODO: do validation of task_ranges here? so models.workflow.add_submission
118
- always receives a definite `task_ranges`? What about if the number is
119
- indeterminate at submission time?
120
-
121
- """
122
-
123
- if task_range == 'all' or task_range is None:
124
- task_range = [1, -1, 1]
125
- if len(task_range) == 2:
126
- task_range.append(1)
127
-
128
- # print('api.submit_workflow: task_range: {}'.format(task_range), flush=True)
129
-
130
- project = Project(dir_path, config_dir)
131
- Session = init_db(project, check_exists=True)
132
- session = Session()
133
-
134
- workflow = session.query(Workflow).get(workflow_id)
135
- submission = workflow.add_submission(project, task_range)
136
-
137
- session.commit()
138
-
139
- submission_id = submission.id_
140
- session.close()
141
-
142
- return submission_id
143
-
144
-
145
- def get_workflow_ids(dir_path=None, config_dir=None):
146
- """Get the IDs of existing Workflows.
147
-
148
- Parameters
149
- ----------
150
- dir_path : str or Path, optional
151
- The directory in which the Workflows exist. By default, this is the
152
- working (i.e. invoking) directory.
153
-
154
- Returns
155
- -------
156
- workflow_ids : list of int
157
- List of IDs of Workflows.
158
-
159
- """
160
-
161
- project = Project(dir_path, config_dir)
162
- Session = init_db(project, check_exists=True)
163
- session = Session()
164
-
165
- workflow_ids = [i.id_ for i in session.query(Workflow.id_)]
166
-
167
- session.close()
168
-
169
- return workflow_ids
170
-
171
-
172
- def clean(dir_path=None, config_dir=None):
173
- """Clean the directory of all content generated by `hpcflow`."""
174
-
175
- project = Project(dir_path, config_dir)
176
- project.clean()
177
-
178
-
179
- def write_runtime_files(cmd_group_sub_id, task_idx, iter_idx, dir_path=None,
180
- config_dir=None):
181
- """Write the commands files for a given command group submission.
182
-
183
- Parameters
184
- ----------
185
- cmd_group_sub_id : int
186
- ID of the command group submission for which a command file is to be
187
- generated.
188
- task_idx : int, optional
189
- Task ID. What is this for???
190
- dir_path : str or Path, optional
191
- The directory in which the Workflow will be generated. By default, this
192
- is the working (i.e. invoking) directory.
193
-
194
- """
195
-
196
- project = Project(dir_path, config_dir)
197
- Session = init_db(project, check_exists=True)
198
- session = Session()
199
-
200
- cg_sub = session.query(CommandGroupSubmission).get(cmd_group_sub_id)
201
- cg_sub.write_runtime_files(project, task_idx, iter_idx)
202
-
203
- session.commit()
204
- session.close()
205
-
206
-
207
- def set_task_start(cmd_group_sub_id, task_idx, iter_idx, dir_path=None, config_dir=None):
208
-
209
- project = Project(dir_path, config_dir)
210
- Session = init_db(project, check_exists=True)
211
- session = Session()
212
-
213
- cg_sub = session.query(CommandGroupSubmission).get(cmd_group_sub_id)
214
- cg_sub.set_task_start(task_idx, iter_idx)
215
-
216
- session.commit()
217
- session.close()
218
-
219
-
220
- def set_task_end(cmd_group_sub_id, task_idx, iter_idx, dir_path=None, config_dir=None):
221
-
222
- project = Project(dir_path, config_dir)
223
- Session = init_db(project, check_exists=True)
224
- session = Session()
225
-
226
- cg_sub = session.query(CommandGroupSubmission).get(cmd_group_sub_id)
227
- cg_sub.set_task_end(task_idx, iter_idx)
228
-
229
- session.commit()
230
- session.close()
231
-
232
-
233
- def archive(cmd_group_sub_id, task_idx, iter_idx, dir_path=None, config_dir=None):
234
- """Initiate an archive of a given task.
235
-
236
- Parameters
237
- ----------
238
- cmd_group_sub_id : int
239
- ID of the command group submission for which an archive is to be
240
- started.
241
- task_idx : int
242
- The task index to be archived (or rather, the task whose working directory
243
- will be archived).
244
- dir_path : str or Path, optional
245
- The directory in which the Workflow will be generated. By default, this
246
- is the working (i.e. invoking) directory.
247
-
248
- """
249
-
250
- project = Project(dir_path, config_dir)
251
- Session = init_db(project, check_exists=True)
252
- session = Session()
253
-
254
- cg_sub = session.query(CommandGroupSubmission).get(cmd_group_sub_id)
255
- cg_sub.do_archive(task_idx, iter_idx)
256
-
257
- session.commit()
258
- session.close()
259
-
260
-
261
- def root_archive(workflow_id, dir_path=None, config_dir=None):
262
- """Archive the root directory of the Workflow."""
263
-
264
- project = Project(dir_path, config_dir)
265
- Session = init_db(project, check_exists=True)
266
- session = Session()
267
-
268
- workflow = session.query(Workflow).get(workflow_id)
269
- workflow.do_root_archive()
270
-
271
- session.commit()
272
- session.close()
273
-
274
-
275
- def get_scheduler_stats(cmd_group_sub_id, task_idx, iter_idx, dir_path=None,
276
- config_dir=None):
277
- """Scrape completed task information from the scheduler.
278
-
279
- Parameters
280
- ----------
281
- cmd_group_sub_id : int
282
- ID of the command group submission for which an archive is to be
283
- started.
284
- task_idx : int
285
- The task index to be archived (or rather, the task whose working directory
286
- will be archived).
287
- dir_path : str or Path, optional
288
- The directory in which the Workflow will be generated. By default, this
289
- is the working (i.e. invoking) directory.
290
-
291
- """
292
-
293
- project = Project(dir_path, config_dir)
294
- Session = init_db(project, check_exists=True)
295
- session = Session()
296
-
297
- cg_sub = session.query(CommandGroupSubmission).get(cmd_group_sub_id)
298
- cg_sub.get_scheduler_stats(task_idx, iter_idx)
299
-
300
- session.commit()
301
- session.close()
302
-
303
-
304
- def get_stats(dir_path=None, workflow_id=None, jsonable=True, datetime_dicts=False,
305
- config_dir=None):
306
- 'Get task statistics (as a JSON-like dict) for a project.'
307
-
308
- project = Project(dir_path, config_dir)
309
- Session = init_db(project, check_exists=True)
310
- session = Session()
311
-
312
- all_workflow_ids = [i.id_ for i in session.query(Workflow.id_)]
313
-
314
- if not all_workflow_ids:
315
- msg = 'No workflows exist in directory: "{}"'
316
- raise ValueError(msg.format(project.dir_path))
317
-
318
- elif workflow_id:
319
-
320
- if workflow_id not in all_workflow_ids:
321
- msg = 'No workflow with ID "{}" was found in directory: "{}"'
322
- raise ValueError(msg.format(workflow_id, project.dir_path))
323
-
324
- workflow_ids = [workflow_id]
325
-
326
- else:
327
- workflow_ids = all_workflow_ids
328
-
329
- workflows = [session.query(Workflow).get(i) for i in workflow_ids]
330
- stats = [i.get_stats(jsonable=jsonable, datetime_dicts=datetime_dicts)
331
- for i in workflows]
332
-
333
- session.close()
334
-
335
- return stats
336
-
337
-
338
- def get_formatted_stats(dir_path=None, workflow_id=None, max_width=100,
339
- show_task_end=False, config_dir=None):
340
- 'Get task statistics formatted like a table.'
341
-
342
- stats = get_stats(dir_path, workflow_id, jsonable=True, config_dir=config_dir)
343
-
344
- out = ''
345
- for workflow in stats:
346
- out += 'Workflow ID: {}\n'.format(workflow['workflow_id'])
347
- for submission in workflow['submissions']:
348
- out += 'Submission ID: {}\n'.format(submission['submission_id'])
349
- for cmd_group_sub in submission['command_group_submissions']:
350
- out += 'Command group submission ID: {}\n'.format(
351
- cmd_group_sub['command_group_submission_id'])
352
- out += 'Commands:\n'
353
- for cmd in cmd_group_sub['commands']:
354
- out += '\t{}\n'.format(cmd)
355
- task_table = BeautifulTable(max_width=max_width)
356
- task_table.set_style(BeautifulTable.STYLE_BOX)
357
- task_table.row_separator_char = ''
358
- headers = [
359
- 'It.',
360
- '#',
361
- 'SID',
362
- 'Dir.',
363
- 'Start',
364
- 'Duration',
365
- 'Archive',
366
- 'memory',
367
- 'hostname',
368
- ]
369
- if show_task_end:
370
- headers = headers[:5] + ['End'] + headers[5:]
371
- task_table.column_headers = headers
372
- task_table.column_alignments['Duration'] = BeautifulTable.ALIGN_RIGHT
373
-
374
- for task in cmd_group_sub['tasks']:
375
- row = [
376
- task['iteration'],
377
- task['order_id'],
378
- task['scheduler_id'],
379
- task['working_directory'],
380
- task['start_time'] or 'pending',
381
- task['duration'] or '-',
382
- task['archive_status'] or '-',
383
- task['memory'] or '-',
384
- task['hostname'] or '-',
385
- ]
386
- if show_task_end:
387
- row = row[:5] + [task['end_time'] or '-'] + row[5:]
388
- task_table.append_row(row)
389
-
390
- out += str(task_table) + '\n\n'
391
-
392
- return out
393
-
394
-
395
- def save_stats(save_path, dir_path=None, workflow_id=None, config_dir=None):
396
- 'Save task statistics as a JSON file.'
397
-
398
- stats = get_stats(dir_path, workflow_id, jsonable=True, config_dir=config_dir)
399
-
400
- save_path = Path(save_path)
401
- with save_path.open('w') as handle:
402
- json.dump(stats, handle, indent=4, sort_keys=True)
403
-
404
-
405
- def kill(dir_path=None, workflow_id=None, config_dir=None):
406
- 'Delete jobscripts associated with a given workflow.'
407
-
408
- project = Project(dir_path, config_dir)
409
- Session = init_db(project, check_exists=True)
410
- session = Session()
411
-
412
- all_workflow_ids = [i.id_ for i in session.query(Workflow.id_)]
413
-
414
- if not all_workflow_ids:
415
- msg = 'No workflows exist in directory: "{}"'
416
- raise ValueError(msg.format(project.dir_path))
417
-
418
- elif workflow_id:
419
-
420
- if workflow_id not in all_workflow_ids:
421
- msg = 'No workflow with ID "{}" was found in directory: "{}"'
422
- raise ValueError(msg.format(workflow_id, project.dir_path))
423
-
424
- workflow_ids = [workflow_id]
425
-
426
- else:
427
- workflow_ids = all_workflow_ids
428
-
429
- for i in workflow_ids:
430
- workflow = session.query(Workflow).get(i)
431
- workflow.kill_active()
432
-
433
- session.commit()
434
- session.close()
435
-
436
-
437
- def update_config(name, value, config_dir=None):
438
- Config.update(name, value, config_dir=config_dir)
439
-
440
-
441
- def cloud_connect(provider, config_dir=None):
442
- Config.set_config(config_dir)
443
- token_key = {'dropbox': 'dropbox_token'}[provider.lower()]
444
- provider = {'dropbox': CloudProvider.dropbox}[provider.lower()]
445
- token = Config.get(token_key)
446
- good = False
447
- if token:
448
- try:
449
- provider.check_access()
450
- print('Connected to cloud provider.')
451
- good = True
452
- except:
453
- print('Existing cloud provider key does not work.')
454
- pass
455
- if not good:
456
- print('Getting new cloud token.')
457
- token = provider.get_token()
458
- update_config(token_key, token, config_dir=config_dir)