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