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
@@ -1,308 +0,0 @@
1
- """`hpcflow.archive.archive.py`
2
-
3
- This module contains a database model class for the archiving capabilities.
4
-
5
- """
6
-
7
- import shutil
8
- import enum
9
- import time
10
- from datetime import datetime
11
- from pathlib import Path
12
- from pprint import pprint
13
- from shutil import ignore_patterns
14
- from time import sleep
15
-
16
- from sqlalchemy import (Table, Column, Integer, DateTime, ForeignKey, String,
17
- UniqueConstraint, Enum, Boolean)
18
- from sqlalchemy.orm import relationship, Session
19
- from sqlalchemy.exc import IntegrityError, OperationalError
20
-
21
- from hpcflow.config import Config as CONFIG
22
- from hpcflow.archive.cloud.cloud import CloudProvider
23
- from hpcflow.archive.cloud.errors import CloudProviderError, CloudCredentialsError
24
- from hpcflow.archive.errors import ArchiveError
25
- from hpcflow.base_db import Base
26
- from hpcflow.copytree import copytree_multi
27
-
28
-
29
- archive_is_active = Table(
30
- 'archive_is_active',
31
- Base.metadata,
32
- Column(
33
- 'archive_id',
34
- Integer,
35
- ForeignKey('archive.id'),
36
- primary_key=True
37
- ),
38
- Column(
39
- 'directory_value_id',
40
- Integer,
41
- ForeignKey('var_value.id'),
42
- primary_key=True
43
- ),
44
- )
45
-
46
-
47
- class RootDirectoryName(enum.Enum):
48
-
49
- parent = 'parent'
50
- datetime = 'datetime'
51
- null = ''
52
-
53
-
54
- class TaskArchiveStatus(enum.Enum):
55
-
56
- pending = 'pending'
57
- active = 'active'
58
- complete = 'complete'
59
-
60
-
61
- class Archive(Base):
62
- """Class to represent an archive location."""
63
-
64
- __tablename__ = 'archive'
65
- __table_args__ = (
66
- UniqueConstraint('path', 'host', 'cloud_provider',
67
- name='archive_location'),
68
- )
69
-
70
- id_ = Column('id', Integer, primary_key=True)
71
- name = Column(String(255))
72
- _path = Column('path', String(255))
73
- host = Column(String(255))
74
- cloud_provider = Column(Enum(CloudProvider))
75
- root_directory_name = Column(Enum(RootDirectoryName))
76
- root_directory_increment = Column(Boolean)
77
-
78
- command_groups = relationship('CommandGroup', back_populates='archive')
79
- directories_archiving = relationship('VarValue', secondary=archive_is_active)
80
- workflow = relationship('Workflow', back_populates='root_archive', uselist=False)
81
-
82
- def __init__(self, name, path, host='', cloud_provider='', root_directory_name='',
83
- root_directory_increment=True):
84
-
85
- self.name = name
86
- self._path = path
87
- self.host = host
88
- self.cloud_provider = CloudProvider(cloud_provider)
89
- self.root_directory_name = RootDirectoryName(root_directory_name)
90
- self.root_directory_increment = root_directory_increment
91
-
92
- if not self.check_exists(self.path):
93
- raise ValueError('Archive path "{}" does not exist.'.format(self.path))
94
-
95
- @property
96
- def path(self):
97
- return Path(self._path)
98
-
99
- def get_directories(self):
100
- """Get sub directories currently on the archive path.
101
-
102
- Returns
103
- -------
104
- list of str
105
- Sub-directory names.
106
-
107
- """
108
-
109
- if not self.host:
110
- if self.cloud_provider != CloudProvider.null:
111
- directories = self.cloud_provider.get_directories(self.path)
112
- else:
113
- directories = [i.name for i in self.path.glob('*') if i.is_dir()]
114
- else:
115
- raise NotImplementedError()
116
-
117
- return directories
118
-
119
- def check_exists(self, directory):
120
- 'Check if a given directory exists on the Archive.'
121
-
122
- if not self.host:
123
- if self.cloud_provider != CloudProvider.null:
124
- exists = self.cloud_provider.check_exists(directory)
125
- else:
126
- exists = directory.is_dir()
127
- else:
128
- raise NotImplementedError()
129
-
130
- return exists
131
-
132
- def get_archive_dir(self, workflow):
133
- 'This should be called once per unique workflow Archive.'
134
-
135
- if self.root_directory_name != RootDirectoryName.null:
136
-
137
- if self.root_directory_name == RootDirectoryName.parent:
138
- archive_dir = workflow.directory.stem
139
- elif self.root_directory_name == RootDirectoryName.datetime:
140
- archive_dir = time.strftime('%Y-%m-%d-%H%M')
141
-
142
- sub_dirs = self.get_directories()
143
- if archive_dir in sub_dirs:
144
- if self.root_directory_increment:
145
- count = 0
146
- max_count = 10
147
- while archive_dir in sub_dirs:
148
- count += 1
149
- if count > max_count:
150
- msg = ('Maximum iteration reached ({}) in searching for '
151
- 'available archive directory.'.format(max_count))
152
- raise RuntimeError(msg)
153
- archive_dir = archive_dir + '_1'
154
- else:
155
- msg = ('Archive directory "{}" already exists.')
156
- raise ValueError(msg.format(archive_dir))
157
-
158
- else:
159
- archive_dir = ''
160
-
161
- return archive_dir
162
-
163
- def execute(self, exclude, archive_dir):
164
- """Execute the archive process with no lock. Used for root archive.
165
-
166
- Parameters
167
- ----------
168
- exclude : list of str
169
-
170
- """
171
-
172
- self._copy(self.workflow.directory, self.path.joinpath(archive_dir), exclude)
173
-
174
- def execute_with_lock(self, task):
175
- """Execute the archive process of a given working directory.
176
-
177
- Parameters
178
- ----------
179
- directory_value : VarValue
180
- exclude : list of str
181
-
182
- """
183
-
184
- print('Archive.execute_with_lock: task.is_archive_required: {}'.format(
185
- task.is_archive_required()))
186
-
187
- session = Session.object_session(self)
188
-
189
- cg_sub = task.command_group_submission_iteration.command_group_submission
190
- directory_value = task.get_working_directory()
191
- exclude = cg_sub.command_group.archive_excludes
192
- archive_dir = cg_sub.command_group.archive_directory
193
-
194
- root_dir = self.command_groups[0].workflow.directory
195
- src_dir = root_dir.joinpath(directory_value.value)
196
- dst_dir = self.path.joinpath(archive_dir, directory_value.value)
197
-
198
- sleep_time = 5
199
- context = 'Archive.execute_with_lock'
200
- block_msg = ('{{}} {}: Archiving blocked. Sleeping for {} '
201
- 'seconds'.format(context, sleep_time))
202
- unblock_msg = ('{{}} {}: Archiving available. Archiving from source directory: '
203
- '"{}" to destination directory: "{}".'.format(
204
- context, src_dir, dst_dir))
205
- apply_block_msg = ('{{}} {}: Applying archive lock to directory: {}.'.format(
206
- context, directory_value))
207
- remove_block_msg = ('{{}} {}: Removing archive lock from directory: {}'.format(
208
- context, directory_value))
209
- arch_done_msg = ('{{}} {}: Archive of the working directory {} performed by '
210
- 'another task.'.format(context, directory_value))
211
-
212
- if task.is_archive_required():
213
-
214
- blocked = True
215
- while blocked:
216
-
217
- session.refresh(self)
218
- if not task.is_archive_required():
219
- print(arch_done_msg.format(datetime.now()), flush=True)
220
- task.archive_status = TaskArchiveStatus('complete')
221
- session.commit()
222
- return
223
-
224
- if directory_value in self.directories_archiving:
225
- print(block_msg.format(datetime.now()), flush=True)
226
- sleep(sleep_time)
227
- else:
228
- try:
229
- self.directories_archiving.append(directory_value)
230
- session.commit()
231
- print(apply_block_msg.format(datetime.now()), flush=True)
232
- blocked = False
233
-
234
- except IntegrityError:
235
- # Another process has already set `directories_archiving`
236
- session.rollback()
237
- print(block_msg.format(datetime.now()), flush=True)
238
- sleep(sleep_time)
239
-
240
- except OperationalError:
241
- # Database is likely locked.
242
- session.rollback()
243
- print(block_msg.format(datetime.now()), flush=True)
244
- sleep(sleep_time)
245
-
246
- if not blocked:
247
-
248
- start_time = datetime.now()
249
- print(unblock_msg.format(start_time), flush=True)
250
- task.archive_status = TaskArchiveStatus('active')
251
- task.archive_start_time = start_time
252
- session.commit()
253
-
254
- self._copy(src_dir, dst_dir, exclude)
255
-
256
- end_time = datetime.now()
257
- task.archive_status = TaskArchiveStatus('complete')
258
- task.archive_end_time = end_time
259
- self.directories_archiving.remove(directory_value)
260
- session.commit()
261
-
262
- print(remove_block_msg.format(end_time), flush=True)
263
-
264
- else:
265
- print(arch_done_msg.format(datetime.now()), flush=True)
266
- task.archive_status = TaskArchiveStatus('complete')
267
- session.commit()
268
-
269
- def _copy(self, src_dir, dst_dir, exclude):
270
- """Do the actual copying.
271
-
272
- Need to ensure this function catches all exceptions, so the block is
273
- released if copying fails.
274
-
275
- TODO: does copytree overwrite all files or just copy
276
- non-existing files?
277
-
278
- TODO: later (safely) copy the database to archive as well?
279
-
280
- """
281
-
282
- ignore = [CONFIG.get('hpcflow_directory')] + (exclude or [])
283
- start = datetime.now()
284
-
285
- try:
286
-
287
- if self.cloud_provider != CloudProvider.null:
288
- try:
289
- self.cloud_provider.archive_directory(src_dir, dst_dir, ignore)
290
- except (CloudProviderError, CloudCredentialsError, ArchiveError) as err:
291
- raise ArchiveError(err)
292
- else:
293
- if ignore:
294
- ignore_func = ignore_patterns(*ignore)
295
- else:
296
- ignore_func = None
297
- try:
298
- copytree_multi(str(src_dir), str(dst_dir), ignore=ignore_func)
299
- except shutil.Error as err:
300
- raise ArchiveError(err)
301
-
302
- except ArchiveError as err:
303
- print('Archive copying error: {}'.format(err))
304
-
305
- end = datetime.now()
306
- copy_seconds = (end - start).total_seconds()
307
- print('Archive to "{}" took {} seconds'.format(
308
- self.name, copy_seconds), flush=True)
@@ -1,47 +0,0 @@
1
- """`hpcflow.archive.cloud.cloud.py
2
-
3
- TODO: if we have multiple cloud providers, perhaps it would be better to
4
- implement the `upload_directory` function generally, and then just rely on
5
- the provider-specific `upload_file` functions.
6
-
7
- """
8
-
9
- import enum
10
- import posixpath
11
- import os
12
-
13
- from hpcflow.archive.cloud.providers import dropbox
14
-
15
-
16
- class CloudProvider(enum.Enum):
17
-
18
- dropbox = 'dropbox'
19
- onedrive = 'onedrive'
20
- null = ''
21
-
22
- def check_access(self):
23
- if self.name == 'dropbox':
24
- dropbox.check_access()
25
-
26
- def archive_directory(self, local_path, remote_path, exclude):
27
- if self.name == 'dropbox':
28
- dropbox.archive_directory(
29
- dropbox.get_dropbox(), local_path, remote_path, exclude)
30
-
31
- def get_directories(self, path):
32
- 'Get sub directories within a path'
33
-
34
- if self.name == 'dropbox':
35
- dbx = dropbox.get_dropbox()
36
- return dropbox.get_folders(dbx, path)
37
-
38
- def check_exists(self, directory):
39
- 'Check a given directory exists on the cloud storage.'
40
- if self.name == 'dropbox':
41
- directory = dropbox.normalise_path(directory)
42
- dbx = dropbox.get_dropbox()
43
- return dropbox.is_folder(dbx, directory)
44
-
45
- def get_token(self):
46
- if self.name == 'dropbox':
47
- return dropbox.get_token()
@@ -1,9 +0,0 @@
1
- """`hpcflow.archive.cloud.errors.py"""
2
-
3
-
4
- class CloudProviderError(Exception):
5
- pass
6
-
7
-
8
- class CloudCredentialsError(Exception):
9
- pass