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.
- hpcflow/__init__.py +2 -11
- hpcflow/__pyinstaller/__init__.py +5 -0
- hpcflow/__pyinstaller/hook-hpcflow.py +40 -0
- hpcflow/_version.py +1 -1
- hpcflow/app.py +43 -0
- hpcflow/cli.py +2 -462
- hpcflow/data/demo_data_manifest/__init__.py +3 -0
- hpcflow/data/demo_data_manifest/demo_data_manifest.json +6 -0
- hpcflow/data/jinja_templates/test/test_template.txt +8 -0
- hpcflow/data/programs/hello_world/README.md +1 -0
- hpcflow/data/programs/hello_world/hello_world.c +87 -0
- hpcflow/data/programs/hello_world/linux/hello_world +0 -0
- hpcflow/data/programs/hello_world/macos/hello_world +0 -0
- hpcflow/data/programs/hello_world/win/hello_world.exe +0 -0
- hpcflow/data/scripts/__init__.py +1 -0
- hpcflow/data/scripts/bad_script.py +2 -0
- hpcflow/data/scripts/demo_task_1_generate_t1_infile_1.py +8 -0
- hpcflow/data/scripts/demo_task_1_generate_t1_infile_2.py +8 -0
- hpcflow/data/scripts/demo_task_1_parse_p3.py +7 -0
- hpcflow/data/scripts/do_nothing.py +2 -0
- hpcflow/data/scripts/env_specifier_test/input_file_generator_pass_env_spec.py +4 -0
- hpcflow/data/scripts/env_specifier_test/main_script_test_pass_env_spec.py +8 -0
- hpcflow/data/scripts/env_specifier_test/output_file_parser_pass_env_spec.py +4 -0
- hpcflow/data/scripts/env_specifier_test/v1/input_file_generator_basic.py +4 -0
- hpcflow/data/scripts/env_specifier_test/v1/main_script_test_direct_in_direct_out.py +7 -0
- hpcflow/data/scripts/env_specifier_test/v1/output_file_parser_basic.py +4 -0
- hpcflow/data/scripts/env_specifier_test/v2/main_script_test_direct_in_direct_out.py +7 -0
- hpcflow/data/scripts/generate_t1_file_01.py +7 -0
- hpcflow/data/scripts/import_future_script.py +7 -0
- hpcflow/data/scripts/input_file_generator_basic.py +3 -0
- hpcflow/data/scripts/input_file_generator_basic_FAIL.py +3 -0
- hpcflow/data/scripts/input_file_generator_test_stdout_stderr.py +8 -0
- hpcflow/data/scripts/main_script_test_direct_in.py +3 -0
- hpcflow/data/scripts/main_script_test_direct_in_direct_out.py +6 -0
- hpcflow/data/scripts/main_script_test_direct_in_direct_out_2.py +6 -0
- hpcflow/data/scripts/main_script_test_direct_in_direct_out_2_fail_allowed.py +6 -0
- hpcflow/data/scripts/main_script_test_direct_in_direct_out_2_fail_allowed_group.py +7 -0
- hpcflow/data/scripts/main_script_test_direct_in_direct_out_3.py +6 -0
- hpcflow/data/scripts/main_script_test_direct_in_direct_out_all_iters_test.py +15 -0
- hpcflow/data/scripts/main_script_test_direct_in_direct_out_env_spec.py +7 -0
- hpcflow/data/scripts/main_script_test_direct_in_direct_out_labels.py +8 -0
- hpcflow/data/scripts/main_script_test_direct_in_group_direct_out_3.py +6 -0
- hpcflow/data/scripts/main_script_test_direct_in_group_one_fail_direct_out_3.py +6 -0
- hpcflow/data/scripts/main_script_test_direct_sub_param_in_direct_out.py +6 -0
- hpcflow/data/scripts/main_script_test_hdf5_in_obj.py +12 -0
- hpcflow/data/scripts/main_script_test_hdf5_in_obj_2.py +12 -0
- hpcflow/data/scripts/main_script_test_hdf5_in_obj_group.py +12 -0
- hpcflow/data/scripts/main_script_test_hdf5_out_obj.py +11 -0
- hpcflow/data/scripts/main_script_test_json_and_direct_in_json_out.py +14 -0
- hpcflow/data/scripts/main_script_test_json_in_json_and_direct_out.py +17 -0
- hpcflow/data/scripts/main_script_test_json_in_json_out.py +14 -0
- hpcflow/data/scripts/main_script_test_json_in_json_out_labels.py +16 -0
- hpcflow/data/scripts/main_script_test_json_in_obj.py +12 -0
- hpcflow/data/scripts/main_script_test_json_out_FAIL.py +3 -0
- hpcflow/data/scripts/main_script_test_json_out_obj.py +10 -0
- hpcflow/data/scripts/main_script_test_json_sub_param_in_json_out_labels.py +16 -0
- hpcflow/data/scripts/main_script_test_shell_env_vars.py +12 -0
- hpcflow/data/scripts/main_script_test_std_out_std_err.py +6 -0
- hpcflow/data/scripts/output_file_parser_basic.py +3 -0
- hpcflow/data/scripts/output_file_parser_basic_FAIL.py +7 -0
- hpcflow/data/scripts/output_file_parser_test_stdout_stderr.py +8 -0
- hpcflow/data/scripts/parse_t1_file_01.py +4 -0
- hpcflow/data/scripts/script_exit_test.py +5 -0
- hpcflow/data/template_components/__init__.py +1 -0
- hpcflow/data/template_components/command_files.yaml +26 -0
- hpcflow/data/template_components/environments.yaml +13 -0
- hpcflow/data/template_components/parameters.yaml +14 -0
- hpcflow/data/template_components/task_schemas.yaml +139 -0
- hpcflow/data/workflows/workflow_1.yaml +5 -0
- hpcflow/examples.ipynb +1037 -0
- hpcflow/sdk/__init__.py +149 -0
- hpcflow/sdk/app.py +4266 -0
- hpcflow/sdk/cli.py +1479 -0
- hpcflow/sdk/cli_common.py +385 -0
- hpcflow/sdk/config/__init__.py +5 -0
- hpcflow/sdk/config/callbacks.py +246 -0
- hpcflow/sdk/config/cli.py +388 -0
- hpcflow/sdk/config/config.py +1410 -0
- hpcflow/sdk/config/config_file.py +501 -0
- hpcflow/sdk/config/errors.py +272 -0
- hpcflow/sdk/config/types.py +150 -0
- hpcflow/sdk/core/__init__.py +38 -0
- hpcflow/sdk/core/actions.py +3857 -0
- hpcflow/sdk/core/app_aware.py +25 -0
- hpcflow/sdk/core/cache.py +224 -0
- hpcflow/sdk/core/command_files.py +814 -0
- hpcflow/sdk/core/commands.py +424 -0
- hpcflow/sdk/core/element.py +2071 -0
- hpcflow/sdk/core/enums.py +221 -0
- hpcflow/sdk/core/environment.py +256 -0
- hpcflow/sdk/core/errors.py +1043 -0
- hpcflow/sdk/core/execute.py +207 -0
- hpcflow/sdk/core/json_like.py +809 -0
- hpcflow/sdk/core/loop.py +1320 -0
- hpcflow/sdk/core/loop_cache.py +282 -0
- hpcflow/sdk/core/object_list.py +933 -0
- hpcflow/sdk/core/parameters.py +3371 -0
- hpcflow/sdk/core/rule.py +196 -0
- hpcflow/sdk/core/run_dir_files.py +57 -0
- hpcflow/sdk/core/skip_reason.py +7 -0
- hpcflow/sdk/core/task.py +3792 -0
- hpcflow/sdk/core/task_schema.py +993 -0
- hpcflow/sdk/core/test_utils.py +538 -0
- hpcflow/sdk/core/types.py +447 -0
- hpcflow/sdk/core/utils.py +1207 -0
- hpcflow/sdk/core/validation.py +87 -0
- hpcflow/sdk/core/values.py +477 -0
- hpcflow/sdk/core/workflow.py +4820 -0
- hpcflow/sdk/core/zarr_io.py +206 -0
- hpcflow/sdk/data/__init__.py +13 -0
- hpcflow/sdk/data/config_file_schema.yaml +34 -0
- hpcflow/sdk/data/config_schema.yaml +260 -0
- hpcflow/sdk/data/environments_spec_schema.yaml +21 -0
- hpcflow/sdk/data/files_spec_schema.yaml +5 -0
- hpcflow/sdk/data/parameters_spec_schema.yaml +7 -0
- hpcflow/sdk/data/task_schema_spec_schema.yaml +3 -0
- hpcflow/sdk/data/workflow_spec_schema.yaml +22 -0
- hpcflow/sdk/demo/__init__.py +3 -0
- hpcflow/sdk/demo/cli.py +242 -0
- hpcflow/sdk/helper/__init__.py +3 -0
- hpcflow/sdk/helper/cli.py +137 -0
- hpcflow/sdk/helper/helper.py +300 -0
- hpcflow/sdk/helper/watcher.py +192 -0
- hpcflow/sdk/log.py +288 -0
- hpcflow/sdk/persistence/__init__.py +18 -0
- hpcflow/sdk/persistence/base.py +2817 -0
- hpcflow/sdk/persistence/defaults.py +6 -0
- hpcflow/sdk/persistence/discovery.py +39 -0
- hpcflow/sdk/persistence/json.py +954 -0
- hpcflow/sdk/persistence/pending.py +948 -0
- hpcflow/sdk/persistence/store_resource.py +203 -0
- hpcflow/sdk/persistence/types.py +309 -0
- hpcflow/sdk/persistence/utils.py +73 -0
- hpcflow/sdk/persistence/zarr.py +2388 -0
- hpcflow/sdk/runtime.py +320 -0
- hpcflow/sdk/submission/__init__.py +3 -0
- hpcflow/sdk/submission/enums.py +70 -0
- hpcflow/sdk/submission/jobscript.py +2379 -0
- hpcflow/sdk/submission/schedulers/__init__.py +281 -0
- hpcflow/sdk/submission/schedulers/direct.py +233 -0
- hpcflow/sdk/submission/schedulers/sge.py +376 -0
- hpcflow/sdk/submission/schedulers/slurm.py +598 -0
- hpcflow/sdk/submission/schedulers/utils.py +25 -0
- hpcflow/sdk/submission/shells/__init__.py +52 -0
- hpcflow/sdk/submission/shells/base.py +229 -0
- hpcflow/sdk/submission/shells/bash.py +504 -0
- hpcflow/sdk/submission/shells/os_version.py +115 -0
- hpcflow/sdk/submission/shells/powershell.py +352 -0
- hpcflow/sdk/submission/submission.py +1402 -0
- hpcflow/sdk/submission/types.py +140 -0
- hpcflow/sdk/typing.py +194 -0
- hpcflow/sdk/utils/arrays.py +69 -0
- hpcflow/sdk/utils/deferred_file.py +55 -0
- hpcflow/sdk/utils/hashing.py +16 -0
- hpcflow/sdk/utils/patches.py +31 -0
- hpcflow/sdk/utils/strings.py +69 -0
- hpcflow/tests/api/test_api.py +32 -0
- hpcflow/tests/conftest.py +123 -0
- hpcflow/tests/data/__init__.py +0 -0
- hpcflow/tests/data/benchmark_N_elements.yaml +6 -0
- hpcflow/tests/data/benchmark_script_runner.yaml +26 -0
- hpcflow/tests/data/multi_path_sequences.yaml +29 -0
- hpcflow/tests/data/workflow_1.json +10 -0
- hpcflow/tests/data/workflow_1.yaml +5 -0
- hpcflow/tests/data/workflow_1_slurm.yaml +8 -0
- hpcflow/tests/data/workflow_1_wsl.yaml +8 -0
- hpcflow/tests/data/workflow_test_run_abort.yaml +42 -0
- hpcflow/tests/jinja_templates/test_jinja_templates.py +161 -0
- hpcflow/tests/programs/test_programs.py +180 -0
- hpcflow/tests/schedulers/direct_linux/test_direct_linux_submission.py +12 -0
- hpcflow/tests/schedulers/sge/test_sge_submission.py +36 -0
- hpcflow/tests/schedulers/slurm/test_slurm_submission.py +14 -0
- hpcflow/tests/scripts/test_input_file_generators.py +282 -0
- hpcflow/tests/scripts/test_main_scripts.py +1361 -0
- hpcflow/tests/scripts/test_non_snippet_script.py +46 -0
- hpcflow/tests/scripts/test_ouput_file_parsers.py +353 -0
- hpcflow/tests/shells/wsl/test_wsl_submission.py +14 -0
- hpcflow/tests/unit/test_action.py +1066 -0
- hpcflow/tests/unit/test_action_rule.py +24 -0
- hpcflow/tests/unit/test_app.py +132 -0
- hpcflow/tests/unit/test_cache.py +46 -0
- hpcflow/tests/unit/test_cli.py +172 -0
- hpcflow/tests/unit/test_command.py +377 -0
- hpcflow/tests/unit/test_config.py +195 -0
- hpcflow/tests/unit/test_config_file.py +162 -0
- hpcflow/tests/unit/test_element.py +666 -0
- hpcflow/tests/unit/test_element_iteration.py +88 -0
- hpcflow/tests/unit/test_element_set.py +158 -0
- hpcflow/tests/unit/test_group.py +115 -0
- hpcflow/tests/unit/test_input_source.py +1479 -0
- hpcflow/tests/unit/test_input_value.py +398 -0
- hpcflow/tests/unit/test_jobscript_unit.py +757 -0
- hpcflow/tests/unit/test_json_like.py +1247 -0
- hpcflow/tests/unit/test_loop.py +2674 -0
- hpcflow/tests/unit/test_meta_task.py +325 -0
- hpcflow/tests/unit/test_multi_path_sequences.py +259 -0
- hpcflow/tests/unit/test_object_list.py +116 -0
- hpcflow/tests/unit/test_parameter.py +243 -0
- hpcflow/tests/unit/test_persistence.py +664 -0
- hpcflow/tests/unit/test_resources.py +243 -0
- hpcflow/tests/unit/test_run.py +286 -0
- hpcflow/tests/unit/test_run_directories.py +29 -0
- hpcflow/tests/unit/test_runtime.py +9 -0
- hpcflow/tests/unit/test_schema_input.py +372 -0
- hpcflow/tests/unit/test_shell.py +129 -0
- hpcflow/tests/unit/test_slurm.py +39 -0
- hpcflow/tests/unit/test_submission.py +502 -0
- hpcflow/tests/unit/test_task.py +2560 -0
- hpcflow/tests/unit/test_task_schema.py +182 -0
- hpcflow/tests/unit/test_utils.py +616 -0
- hpcflow/tests/unit/test_value_sequence.py +549 -0
- hpcflow/tests/unit/test_values.py +91 -0
- hpcflow/tests/unit/test_workflow.py +827 -0
- hpcflow/tests/unit/test_workflow_template.py +186 -0
- hpcflow/tests/unit/utils/test_arrays.py +40 -0
- hpcflow/tests/unit/utils/test_deferred_file_writer.py +34 -0
- hpcflow/tests/unit/utils/test_hashing.py +65 -0
- hpcflow/tests/unit/utils/test_patches.py +5 -0
- hpcflow/tests/unit/utils/test_redirect_std.py +50 -0
- hpcflow/tests/unit/utils/test_strings.py +97 -0
- hpcflow/tests/workflows/__init__.py +0 -0
- hpcflow/tests/workflows/test_directory_structure.py +31 -0
- hpcflow/tests/workflows/test_jobscript.py +355 -0
- hpcflow/tests/workflows/test_run_status.py +198 -0
- hpcflow/tests/workflows/test_skip_downstream.py +696 -0
- hpcflow/tests/workflows/test_submission.py +140 -0
- hpcflow/tests/workflows/test_workflows.py +564 -0
- hpcflow/tests/workflows/test_zip.py +18 -0
- hpcflow/viz_demo.ipynb +6794 -0
- hpcflow-0.2.0a271.dist-info/LICENSE +375 -0
- hpcflow-0.2.0a271.dist-info/METADATA +65 -0
- hpcflow-0.2.0a271.dist-info/RECORD +237 -0
- {hpcflow-0.1.9.dist-info → hpcflow-0.2.0a271.dist-info}/WHEEL +4 -5
- hpcflow-0.2.0a271.dist-info/entry_points.txt +6 -0
- hpcflow/api.py +0 -458
- hpcflow/archive/archive.py +0 -308
- hpcflow/archive/cloud/cloud.py +0 -47
- hpcflow/archive/cloud/errors.py +0 -9
- hpcflow/archive/cloud/providers/dropbox.py +0 -432
- hpcflow/archive/errors.py +0 -5
- hpcflow/base_db.py +0 -4
- hpcflow/config.py +0 -232
- hpcflow/copytree.py +0 -66
- hpcflow/data/examples/_config.yml +0 -14
- hpcflow/data/examples/damask/demo/1.run.yml +0 -4
- hpcflow/data/examples/damask/demo/2.process.yml +0 -29
- hpcflow/data/examples/damask/demo/geom.geom +0 -2052
- hpcflow/data/examples/damask/demo/load.load +0 -1
- hpcflow/data/examples/damask/demo/material.config +0 -185
- hpcflow/data/examples/damask/inputs/geom.geom +0 -2052
- hpcflow/data/examples/damask/inputs/load.load +0 -1
- hpcflow/data/examples/damask/inputs/material.config +0 -185
- hpcflow/data/examples/damask/profiles/_variable_lookup.yml +0 -21
- hpcflow/data/examples/damask/profiles/damask.yml +0 -4
- hpcflow/data/examples/damask/profiles/damask_process.yml +0 -8
- hpcflow/data/examples/damask/profiles/damask_run.yml +0 -5
- hpcflow/data/examples/damask/profiles/default.yml +0 -6
- hpcflow/data/examples/thinking.yml +0 -177
- hpcflow/errors.py +0 -2
- hpcflow/init_db.py +0 -37
- hpcflow/models.py +0 -2549
- hpcflow/nesting.py +0 -9
- hpcflow/profiles.py +0 -455
- hpcflow/project.py +0 -81
- hpcflow/scheduler.py +0 -323
- hpcflow/utils.py +0 -103
- hpcflow/validation.py +0 -167
- hpcflow/variables.py +0 -544
- hpcflow-0.1.9.dist-info/METADATA +0 -168
- hpcflow-0.1.9.dist-info/RECORD +0 -45
- hpcflow-0.1.9.dist-info/entry_points.txt +0 -8
- hpcflow-0.1.9.dist-info/top_level.txt +0 -1
- /hpcflow/{archive → data/jinja_templates}/__init__.py +0 -0
- /hpcflow/{archive/cloud → data/programs}/__init__.py +0 -0
- /hpcflow/{archive/cloud/providers → data/workflows}/__init__.py +0 -0
|
@@ -1,432 +0,0 @@
|
|
|
1
|
-
"""`hpcflow.archive.cloud.providers.dropbox.py`
|
|
2
|
-
|
|
3
|
-
This module provides interactivity with a Dropbox account for archiving.
|
|
4
|
-
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import os
|
|
8
|
-
import posixpath
|
|
9
|
-
import fnmatch
|
|
10
|
-
from pathlib import Path
|
|
11
|
-
from pprint import pprint
|
|
12
|
-
from datetime import datetime
|
|
13
|
-
from textwrap import dedent
|
|
14
|
-
|
|
15
|
-
import dropbox as dropbox_api
|
|
16
|
-
|
|
17
|
-
from hpcflow.config import Config
|
|
18
|
-
from hpcflow.archive.errors import ArchiveError
|
|
19
|
-
from hpcflow.archive.cloud.errors import CloudProviderError, CloudCredentialsError
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def get_token():
|
|
23
|
-
|
|
24
|
-
APP_KEY = Config.get('dropbox_app_key')
|
|
25
|
-
auth_flow = dropbox_api.DropboxOAuth2FlowNoRedirect(APP_KEY, use_pkce=True)
|
|
26
|
-
authorize_url = auth_flow.start()
|
|
27
|
-
|
|
28
|
-
msg = dedent(f"""
|
|
29
|
-
--------------------------- Connecting hpcflow to Dropbox ----------------------------
|
|
30
|
-
|
|
31
|
-
1. Go to this URL:
|
|
32
|
-
|
|
33
|
-
{authorize_url}
|
|
34
|
-
|
|
35
|
-
2. Click "Allow" (you might have to log in first).
|
|
36
|
-
3. Copy the authorization code below.
|
|
37
|
-
|
|
38
|
-
--------------------------------------------------------------------------------------
|
|
39
|
-
""")
|
|
40
|
-
print(msg)
|
|
41
|
-
|
|
42
|
-
auth_code = input('Enter the authorization code here: ').strip()
|
|
43
|
-
try:
|
|
44
|
-
oauth_result = auth_flow.finish(auth_code)
|
|
45
|
-
except Exception as err:
|
|
46
|
-
print(f'Error: {err}')
|
|
47
|
-
|
|
48
|
-
token = oauth_result.access_token
|
|
49
|
-
|
|
50
|
-
return token
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def get_dropbox():
|
|
54
|
-
env_var_name = 'DROPBOX_TOKEN'
|
|
55
|
-
token = Config.get('dropbox_token') or os.getenv(env_var_name)
|
|
56
|
-
if not token:
|
|
57
|
-
msg = ('Please set the Dropbox access token in an environment variable '
|
|
58
|
-
f'"{env_var_name}", or in the config file as "dropbox_token".')
|
|
59
|
-
raise CloudCredentialsError(msg)
|
|
60
|
-
|
|
61
|
-
dbx = dropbox_api.Dropbox(token)
|
|
62
|
-
|
|
63
|
-
return dbx
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def check_access():
|
|
67
|
-
dbx = get_dropbox()
|
|
68
|
-
try:
|
|
69
|
-
user_acc = dbx.users_get_current_account()
|
|
70
|
-
except:
|
|
71
|
-
msg = 'Could not connect to Dropbox using the supplied access token.'
|
|
72
|
-
raise ValueError(msg)
|
|
73
|
-
|
|
74
|
-
print('OK!', flush=True)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def get_files(dbx, path):
|
|
78
|
-
path = normalise_path(path)
|
|
79
|
-
out = []
|
|
80
|
-
for i in dbx.files_list_folder(path).entries:
|
|
81
|
-
if isinstance(i, dropbox_api.files.FileMetadata):
|
|
82
|
-
out.append(i.name)
|
|
83
|
-
return out
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
def get_folders(dbx, path):
|
|
87
|
-
path = normalise_path(path)
|
|
88
|
-
out = []
|
|
89
|
-
for i in dbx.files_list_folder(path).entries:
|
|
90
|
-
if isinstance(i, dropbox_api.files.FolderMetadata):
|
|
91
|
-
out.append(i.name)
|
|
92
|
-
return out
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def is_file(dbx, path):
|
|
96
|
-
"""Check given path on dropbox is a file."""
|
|
97
|
-
meta = dbx.files_get_metadata(path)
|
|
98
|
-
return isinstance(meta, dropbox_api.files.FileMetadata)
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
def is_folder(dbx, path):
|
|
102
|
-
"""Check given path on dropbox is a folder."""
|
|
103
|
-
try:
|
|
104
|
-
meta = dbx.files_get_metadata(path)
|
|
105
|
-
return isinstance(meta, dropbox_api.files.FolderMetadata)
|
|
106
|
-
except dropbox_api.exceptions.ApiError:
|
|
107
|
-
return False
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
def rename_file(dbx, src_path, dst_path):
|
|
111
|
-
"""Rename a file from one path to another."""
|
|
112
|
-
if is_file(dbx, src_path):
|
|
113
|
-
print('Renaming file: {} to {}'.format(src_path, dst_path))
|
|
114
|
-
dbx.files_move_v2(src_path, dst_path)
|
|
115
|
-
else:
|
|
116
|
-
raise ValueError('Cannot rename a file that does not exist.')
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
def download_dropbox_file(dbx, dropbox_path, local_path):
|
|
120
|
-
dbx.files_download_to_file(local_path, dropbox_path)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
def normalise_path(path):
|
|
124
|
-
'Modify a path (str or Path) such that it is a Dropbox-compatible path string.'
|
|
125
|
-
path = posixpath.join(*str(path).split(os.path.sep))
|
|
126
|
-
if not path.startswith('/'):
|
|
127
|
-
path = '/' + path
|
|
128
|
-
return path
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
def archive_file(dbx, local_path, dropbox_dir, check_modified_time=True):
|
|
132
|
-
"""Upload a file to a dropbox directory such that if the local file is newer than the
|
|
133
|
-
copy on Dropbox, the newer file overwrites the older file, and if the local file is
|
|
134
|
-
older than the copy on Dropbox, the local file is uploaded with an "auto-incremented"
|
|
135
|
-
name.
|
|
136
|
-
|
|
137
|
-
Note that if the modified times are different, the file still won't be uploaded
|
|
138
|
-
by dropbox if the file contents are identical. The point of checking for the
|
|
139
|
-
modified times is to save some time by not having Dropbox check file contents.
|
|
140
|
-
|
|
141
|
-
Parameters
|
|
142
|
-
----------
|
|
143
|
-
dbx: Dropbox
|
|
144
|
-
local_path : str or Path
|
|
145
|
-
Path of file on local computer to upload to dropbox.
|
|
146
|
-
dropbox_dir : str or Path
|
|
147
|
-
Directory on Dropbox into which the file should be uploaded.
|
|
148
|
-
|
|
149
|
-
"""
|
|
150
|
-
|
|
151
|
-
local_path = Path(local_path)
|
|
152
|
-
dropbox_path = normalise_path(Path(dropbox_dir).joinpath(local_path.name))
|
|
153
|
-
|
|
154
|
-
if not check_modified_time:
|
|
155
|
-
overwrite = True
|
|
156
|
-
autorename = False
|
|
157
|
-
client_modified = None
|
|
158
|
-
|
|
159
|
-
else:
|
|
160
|
-
# Note: Dropbox culls microseconds from the datetime passed as the
|
|
161
|
-
# `client_modified` parameter (it does not round).
|
|
162
|
-
# Ref: ("https://www.dropboxforum.com/t5/API-Support-Feedback/Python-API-client"
|
|
163
|
-
# "-modified-resolution/m-p/362170/highlight/true#M20596")
|
|
164
|
-
ts_sec = local_path.stat().st_mtime_ns / 1e9
|
|
165
|
-
dt = datetime.utcfromtimestamp(ts_sec)
|
|
166
|
-
client_modified = datetime( # no microseconds
|
|
167
|
-
year=dt.year,
|
|
168
|
-
month=dt.month,
|
|
169
|
-
day=dt.day,
|
|
170
|
-
hour=dt.hour,
|
|
171
|
-
minute=dt.minute,
|
|
172
|
-
second=dt.second,
|
|
173
|
-
)
|
|
174
|
-
|
|
175
|
-
try:
|
|
176
|
-
# Check for existing file
|
|
177
|
-
existing_file = dbx.files_get_metadata(dropbox_path)
|
|
178
|
-
existing_modified = existing_file.client_modified
|
|
179
|
-
|
|
180
|
-
# print('client_modified: {!r}'.format(client_modified))
|
|
181
|
-
# print('existing_modified: {!r}'.format(existing_modified))
|
|
182
|
-
|
|
183
|
-
if client_modified == existing_modified:
|
|
184
|
-
# print('client_modified time same!')
|
|
185
|
-
return
|
|
186
|
-
|
|
187
|
-
elif client_modified < existing_modified:
|
|
188
|
-
overwrite = False
|
|
189
|
-
autorename = True
|
|
190
|
-
# print('client file older!')
|
|
191
|
-
|
|
192
|
-
elif client_modified > existing_modified:
|
|
193
|
-
overwrite = True
|
|
194
|
-
autorename = False
|
|
195
|
-
# print('client file newer!')
|
|
196
|
-
|
|
197
|
-
except dropbox_api.exceptions.ApiError:
|
|
198
|
-
|
|
199
|
-
# print('File does not exist.')
|
|
200
|
-
|
|
201
|
-
overwrite = False
|
|
202
|
-
autorename = False
|
|
203
|
-
|
|
204
|
-
except:
|
|
205
|
-
msg = 'Unexpected error.'
|
|
206
|
-
raise CloudProviderError(msg)
|
|
207
|
-
|
|
208
|
-
_upload_dropbox_file(
|
|
209
|
-
dbx,
|
|
210
|
-
local_path,
|
|
211
|
-
dropbox_path,
|
|
212
|
-
overwrite=overwrite,
|
|
213
|
-
autorename=autorename,
|
|
214
|
-
client_modified=client_modified
|
|
215
|
-
)
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
def upload_dropbox_file(dbx, local_path, dropbox_dir, overwrite=False, autorename=True,
|
|
219
|
-
client_modified=None):
|
|
220
|
-
"""
|
|
221
|
-
Parameters
|
|
222
|
-
----------
|
|
223
|
-
dbx: Dropbox
|
|
224
|
-
local_path : str or Path
|
|
225
|
-
Path of file on local computer to upload to dropbox.
|
|
226
|
-
dropbox_dir : str or Path
|
|
227
|
-
Directory on Dropbox into which the file should be uploaded.
|
|
228
|
-
overwrite : bool
|
|
229
|
-
If True, the file overwrites an existing file with the same name.
|
|
230
|
-
autorename : bool
|
|
231
|
-
If True, rename the file if there is a conflict.
|
|
232
|
-
|
|
233
|
-
"""
|
|
234
|
-
|
|
235
|
-
local_path = Path(local_path)
|
|
236
|
-
dropbox_path = normalise_path(Path(dropbox_dir).joinpath(local_path.name))
|
|
237
|
-
_upload_dropbox_file(
|
|
238
|
-
dbx,
|
|
239
|
-
local_path,
|
|
240
|
-
dropbox_path,
|
|
241
|
-
overwrite=overwrite,
|
|
242
|
-
autorename=autorename,
|
|
243
|
-
client_modified=client_modified,
|
|
244
|
-
)
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
def _upload_dropbox_file(dbx, local_path, dropbox_path, overwrite=False, autorename=True,
|
|
248
|
-
client_modified=None):
|
|
249
|
-
"""
|
|
250
|
-
Parameters
|
|
251
|
-
----------
|
|
252
|
-
dbx: Dropbox
|
|
253
|
-
local_path : Path
|
|
254
|
-
Path of file on local computer to upload to dropbox.
|
|
255
|
-
dropbox_path : str
|
|
256
|
-
Path to upload the file to nn dropbox.
|
|
257
|
-
overwrite : bool
|
|
258
|
-
If True, the file overwrites an existing file with the same name.
|
|
259
|
-
autorename : bool
|
|
260
|
-
If True, rename the file if there is a conflict.
|
|
261
|
-
|
|
262
|
-
"""
|
|
263
|
-
|
|
264
|
-
if overwrite:
|
|
265
|
-
mode = dropbox_api.dropbox.files.WriteMode('overwrite', None)
|
|
266
|
-
else:
|
|
267
|
-
mode = dropbox_api.dropbox.files.WriteMode('add', None)
|
|
268
|
-
|
|
269
|
-
try:
|
|
270
|
-
with local_path.open(mode='rb') as handle:
|
|
271
|
-
|
|
272
|
-
try:
|
|
273
|
-
dbx.files_upload(
|
|
274
|
-
handle.read(),
|
|
275
|
-
dropbox_path,
|
|
276
|
-
mode=mode,
|
|
277
|
-
autorename=autorename,
|
|
278
|
-
client_modified=client_modified,
|
|
279
|
-
)
|
|
280
|
-
|
|
281
|
-
except dropbox_api.exceptions.ApiError as err:
|
|
282
|
-
msg = ('Cloud provider error. {}'.format(err))
|
|
283
|
-
raise CloudProviderError(msg)
|
|
284
|
-
except:
|
|
285
|
-
msg = 'Unexpected error.'
|
|
286
|
-
raise CloudProviderError(msg)
|
|
287
|
-
|
|
288
|
-
except FileNotFoundError as err:
|
|
289
|
-
raise ArchiveError(err)
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
def archive_directory(dbx, local_dir, dropbox_dir, exclude=None):
|
|
293
|
-
"""
|
|
294
|
-
Archive a the contents of a local directory into a directory on dropbox.
|
|
295
|
-
|
|
296
|
-
Any files in the dropbox directory not in the source directory are ignored.
|
|
297
|
-
|
|
298
|
-
Parameters
|
|
299
|
-
----------
|
|
300
|
-
dbx: Dropbox
|
|
301
|
-
local_dir : str or Path
|
|
302
|
-
Path of directory on local computer to upload to dropbox.
|
|
303
|
-
dropbox_dir : str or Path
|
|
304
|
-
Directory on dropbox to upload the files to.
|
|
305
|
-
|
|
306
|
-
"""
|
|
307
|
-
|
|
308
|
-
print('hpcflow.archive.cloud.providers.dropbox.archive_directory', flush=True)
|
|
309
|
-
|
|
310
|
-
local_dir = Path(local_dir)
|
|
311
|
-
dropbox_dir = Path(dropbox_dir)
|
|
312
|
-
_upload_dropbox_dir(
|
|
313
|
-
dbx,
|
|
314
|
-
local_dir,
|
|
315
|
-
dropbox_dir,
|
|
316
|
-
exclude=exclude,
|
|
317
|
-
archive=True,
|
|
318
|
-
)
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
def upload_dropbox_dir(dbx, local_dir, dropbox_dir, overwrite=False, autorename=False,
|
|
322
|
-
exclude=None):
|
|
323
|
-
"""
|
|
324
|
-
Parameters
|
|
325
|
-
----------
|
|
326
|
-
dbx: Dropbox
|
|
327
|
-
local_dir : str or Path
|
|
328
|
-
Path of directory on local computer to upload to dropbox.
|
|
329
|
-
dropbox_dir : str or Path
|
|
330
|
-
Directory on dropbox to upload the file to.
|
|
331
|
-
overwrite : bool
|
|
332
|
-
If True, the file overwrites an existing file with the same name.
|
|
333
|
-
autorename : bool
|
|
334
|
-
If True, rename the file if there is a conflict.
|
|
335
|
-
exclude : list, optional
|
|
336
|
-
List of file or directory names to exclude, matched with `fnmatch` for
|
|
337
|
-
files, or compared directly for directories.
|
|
338
|
-
|
|
339
|
-
"""
|
|
340
|
-
|
|
341
|
-
local_dir = Path(local_dir)
|
|
342
|
-
dropbox_dir = Path(dropbox_dir)
|
|
343
|
-
_upload_dropbox_dir(
|
|
344
|
-
dbx,
|
|
345
|
-
local_dir,
|
|
346
|
-
dropbox_dir,
|
|
347
|
-
overwrite=overwrite,
|
|
348
|
-
autorename=autorename,
|
|
349
|
-
exclude=exclude,
|
|
350
|
-
archive=False,
|
|
351
|
-
)
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
def _upload_dropbox_dir(dbx, local_dir, dropbox_dir, overwrite=False, autorename=False,
|
|
355
|
-
exclude=None, archive=False):
|
|
356
|
-
"""
|
|
357
|
-
Parameters
|
|
358
|
-
----------
|
|
359
|
-
dbx: Dropbox
|
|
360
|
-
local_dir : Path
|
|
361
|
-
Path of directory on local computer to upload to dropbox.
|
|
362
|
-
dropbox_dir : Path
|
|
363
|
-
Directory on dropbox to upload the file to.
|
|
364
|
-
overwrite : bool
|
|
365
|
-
If True, the file overwrites an existing file with the same name.
|
|
366
|
-
autorename : bool
|
|
367
|
-
If True, rename the file if there is a conflict.
|
|
368
|
-
exclude : list, optional
|
|
369
|
-
List of file or directory names to exclude, matched with `fnmatch` for
|
|
370
|
-
files, or compared directly for directories.
|
|
371
|
-
archive : bool, optional
|
|
372
|
-
|
|
373
|
-
Notes
|
|
374
|
-
-----
|
|
375
|
-
Does not upload empty directories.
|
|
376
|
-
|
|
377
|
-
"""
|
|
378
|
-
|
|
379
|
-
if not exclude:
|
|
380
|
-
exclude = []
|
|
381
|
-
|
|
382
|
-
# Validation
|
|
383
|
-
if not local_dir.is_dir():
|
|
384
|
-
raise ValueError('Specified `local_dir` is not a directory: {}'.format(local_dir))
|
|
385
|
-
|
|
386
|
-
for root, dirs, files in os.walk(str(local_dir)):
|
|
387
|
-
|
|
388
|
-
root_test = Path(root)
|
|
389
|
-
|
|
390
|
-
dirs[:] = [d for d in dirs if d not in exclude]
|
|
391
|
-
|
|
392
|
-
print('Uploading from root directory: {}'.format(root), flush=True)
|
|
393
|
-
|
|
394
|
-
for file_name in sorted(files):
|
|
395
|
-
|
|
396
|
-
up_file = False
|
|
397
|
-
|
|
398
|
-
if exclude is not None:
|
|
399
|
-
if not any([fnmatch.fnmatch(file_name, i) for i in exclude]):
|
|
400
|
-
up_file = True
|
|
401
|
-
else:
|
|
402
|
-
up_file = True
|
|
403
|
-
|
|
404
|
-
if up_file:
|
|
405
|
-
|
|
406
|
-
src_file = root_test.joinpath(file_name)
|
|
407
|
-
rel_path = src_file.relative_to(local_dir)
|
|
408
|
-
dst_dir = dropbox_dir.joinpath(rel_path.parent)
|
|
409
|
-
|
|
410
|
-
print('Uploading file: {}'.format(file_name), flush=True)
|
|
411
|
-
try:
|
|
412
|
-
if archive:
|
|
413
|
-
archive_file(
|
|
414
|
-
dbx,
|
|
415
|
-
src_file,
|
|
416
|
-
dst_dir
|
|
417
|
-
)
|
|
418
|
-
else:
|
|
419
|
-
upload_dropbox_file(
|
|
420
|
-
dbx,
|
|
421
|
-
src_file,
|
|
422
|
-
dst_dir,
|
|
423
|
-
overwrite=overwrite,
|
|
424
|
-
autorename=autorename
|
|
425
|
-
)
|
|
426
|
-
except ArchiveError as err:
|
|
427
|
-
print('Archive error: {}'.format(err), flush=True)
|
|
428
|
-
continue
|
|
429
|
-
|
|
430
|
-
except CloudProviderError as err:
|
|
431
|
-
print('Cloud provider error: {}'.format(err), flush=True)
|
|
432
|
-
continue
|
hpcflow/archive/errors.py
DELETED
hpcflow/base_db.py
DELETED
hpcflow/config.py
DELETED
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from pathlib import Path
|
|
3
|
-
from warnings import warn
|
|
4
|
-
|
|
5
|
-
from ruamel.yaml import YAML, safe_load
|
|
6
|
-
|
|
7
|
-
from hpcflow.errors import ConfigurationError
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class Config(object):
|
|
11
|
-
|
|
12
|
-
__PROFILE_KEYS_REQ = [
|
|
13
|
-
'command_groups',
|
|
14
|
-
'profile_name',
|
|
15
|
-
'profile_order',
|
|
16
|
-
]
|
|
17
|
-
__PROFILE_KEYS_GOOD = __PROFILE_KEYS_REQ + [
|
|
18
|
-
'alternate_scratch',
|
|
19
|
-
'archive_locations',
|
|
20
|
-
'archive',
|
|
21
|
-
'archive_excludes',
|
|
22
|
-
'directory',
|
|
23
|
-
'inherits',
|
|
24
|
-
'is_job_array',
|
|
25
|
-
'loop',
|
|
26
|
-
'environment',
|
|
27
|
-
'nesting',
|
|
28
|
-
'scheduler',
|
|
29
|
-
'scheduler_options',
|
|
30
|
-
'output_dir',
|
|
31
|
-
'error_dir',
|
|
32
|
-
'pre_commands',
|
|
33
|
-
'root_archive',
|
|
34
|
-
'root_archive_excludes',
|
|
35
|
-
'variable_scope',
|
|
36
|
-
'variables',
|
|
37
|
-
'stats',
|
|
38
|
-
]
|
|
39
|
-
__CMD_GROUP_KEYS_REQ = [
|
|
40
|
-
'commands',
|
|
41
|
-
]
|
|
42
|
-
__CMD_GROUP_KEYS_GOOD = __CMD_GROUP_KEYS_REQ + [
|
|
43
|
-
'alternate_scratch',
|
|
44
|
-
'archive',
|
|
45
|
-
'archive_excludes',
|
|
46
|
-
'directory',
|
|
47
|
-
'is_job_array',
|
|
48
|
-
'environment',
|
|
49
|
-
'nesting',
|
|
50
|
-
'scheduler',
|
|
51
|
-
'scheduler_options',
|
|
52
|
-
'output_dir',
|
|
53
|
-
'error_dir',
|
|
54
|
-
'profile_name',
|
|
55
|
-
'profile_order',
|
|
56
|
-
'exec_order',
|
|
57
|
-
'stats',
|
|
58
|
-
'job_name',
|
|
59
|
-
]
|
|
60
|
-
__CMD_GROUP_DEFAULTS = {
|
|
61
|
-
'is_job_array': True,
|
|
62
|
-
'nesting': None,
|
|
63
|
-
'directory': '',
|
|
64
|
-
'archive': None,
|
|
65
|
-
'archive_excludes': [],
|
|
66
|
-
'scheduler': 'direct',
|
|
67
|
-
'scheduler_options': {},
|
|
68
|
-
'output_dir': None, # Set in `Config.set_config`
|
|
69
|
-
'error_dir': None, # Set in `Config.set_config`
|
|
70
|
-
'stats': False,
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
__CONSTANTS = {
|
|
74
|
-
'DB_name': 'workflow.db',
|
|
75
|
-
'alt_scratch_exc_file': 'alt_scratch_exclude',
|
|
76
|
-
'alt_scratch_exc_file_ext': '.txt',
|
|
77
|
-
'profile_keys_required': __PROFILE_KEYS_REQ,
|
|
78
|
-
'profile_keys_allowed': __PROFILE_KEYS_GOOD,
|
|
79
|
-
'cmd_group_keys_required': __CMD_GROUP_KEYS_REQ,
|
|
80
|
-
'cmd_group_keys_allowed': __CMD_GROUP_KEYS_GOOD,
|
|
81
|
-
'cmd_group_defaults': __CMD_GROUP_DEFAULTS,
|
|
82
|
-
'dropbox_app_key': 'g2zt0hmhfjavd2d',
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
# These may be customised in the config file:
|
|
86
|
-
__ALLOWED = {
|
|
87
|
-
'data_dir': None,
|
|
88
|
-
'variable_delimiters': ['<<', '>>'],
|
|
89
|
-
'default_cmd_group_dir_var_name': '__hpcflow_cmd_group_directory_var',
|
|
90
|
-
'profile_filename_fmt': '<<profile_order>>.<<profile_name>>.yml',
|
|
91
|
-
'profile_ext': '.yml',
|
|
92
|
-
'jobscript_ext': '.sh',
|
|
93
|
-
'variable_file_ext': '.txt',
|
|
94
|
-
'working_dirs_file_ext': '.txt',
|
|
95
|
-
'default_output_dir': 'output',
|
|
96
|
-
'default_error_dir': 'output',
|
|
97
|
-
'hpcflow_directory': '.hpcflow',
|
|
98
|
-
'archive_locations': {},
|
|
99
|
-
'dropbox_token': None
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
__conf = {}
|
|
103
|
-
|
|
104
|
-
is_set = False
|
|
105
|
-
|
|
106
|
-
@staticmethod
|
|
107
|
-
def resolve_config_dir(config_dir=None):
|
|
108
|
-
|
|
109
|
-
if not config_dir:
|
|
110
|
-
config_dir = Path(os.getenv('HPCFLOW_CONFIG_DIR', '~/.hpcflow')).expanduser()
|
|
111
|
-
else:
|
|
112
|
-
config_dir = Path(config_dir)
|
|
113
|
-
|
|
114
|
-
if Config.is_set:
|
|
115
|
-
if config_dir != Config.get('config_dir'):
|
|
116
|
-
warn(f'Config is already set, but `config_dir` changed from '
|
|
117
|
-
f'"{Config.get("config_dir")}" to "{config_dir}".')
|
|
118
|
-
|
|
119
|
-
if not config_dir.is_dir():
|
|
120
|
-
print('Configuration directory does not exist. Generating.')
|
|
121
|
-
config_dir.mkdir()
|
|
122
|
-
|
|
123
|
-
return config_dir
|
|
124
|
-
|
|
125
|
-
@staticmethod
|
|
126
|
-
def get_config_file(config_dir, round_trip_load=False, quiet=False):
|
|
127
|
-
|
|
128
|
-
config_file = config_dir.joinpath('config.yml')
|
|
129
|
-
if not config_file.is_file():
|
|
130
|
-
if not quiet:
|
|
131
|
-
print('No config.yml found. Generating a config.yml file.')
|
|
132
|
-
with config_file.open('w'):
|
|
133
|
-
pass
|
|
134
|
-
|
|
135
|
-
if not quiet:
|
|
136
|
-
print(f'Loading hpcflow config from {config_file}.')
|
|
137
|
-
if round_trip_load:
|
|
138
|
-
yaml = YAML(typ='rt')
|
|
139
|
-
else:
|
|
140
|
-
yaml = YAML(typ='safe')
|
|
141
|
-
with config_file.open() as handle:
|
|
142
|
-
config_dat = yaml.load(handle) or {}
|
|
143
|
-
|
|
144
|
-
bad_keys = list(set(config_dat.keys()) - set(Config.__ALLOWED.keys()))
|
|
145
|
-
if bad_keys:
|
|
146
|
-
bad_keys_fmt = ', '.join([f'"{i}"' for i in bad_keys])
|
|
147
|
-
raise ConfigurationError(f'Unknown configuration options: {bad_keys_fmt}.')
|
|
148
|
-
|
|
149
|
-
return config_dat, config_file
|
|
150
|
-
|
|
151
|
-
@staticmethod
|
|
152
|
-
def set_config(config_dir=None, raise_on_set=False):
|
|
153
|
-
'Load configuration from a YAML file.'
|
|
154
|
-
|
|
155
|
-
config_dir = Config.resolve_config_dir(config_dir)
|
|
156
|
-
|
|
157
|
-
if Config.is_set:
|
|
158
|
-
if raise_on_set:
|
|
159
|
-
raise ConfigurationError('Configuration is already set.')
|
|
160
|
-
return
|
|
161
|
-
|
|
162
|
-
config_dat, _ = Config.get_config_file(config_dir)
|
|
163
|
-
|
|
164
|
-
profiles_dir = config_dir.joinpath('profiles')
|
|
165
|
-
if not profiles_dir.is_dir():
|
|
166
|
-
print('Profiles directory does not exist. Generating.')
|
|
167
|
-
profiles_dir.mkdir()
|
|
168
|
-
|
|
169
|
-
projects_DB_dir = config_dir.joinpath('projects')
|
|
170
|
-
if not projects_DB_dir.is_dir():
|
|
171
|
-
print('Projects database directory does not exist. Generating.')
|
|
172
|
-
projects_DB_dir.mkdir()
|
|
173
|
-
|
|
174
|
-
yaml = YAML()
|
|
175
|
-
var_look_file = config_dir.joinpath('variable_lookup.yml')
|
|
176
|
-
if not var_look_file.is_file():
|
|
177
|
-
print('No variable lookup file found. Generating.')
|
|
178
|
-
var_look_dat = {'variable_templates': {}, 'scopes': {}}
|
|
179
|
-
yaml.dump(var_look_dat, var_look_file)
|
|
180
|
-
else:
|
|
181
|
-
var_look_dat = yaml.load(var_look_file)
|
|
182
|
-
|
|
183
|
-
if sorted(var_look_dat.keys()) != ['scopes', 'variable_templates']:
|
|
184
|
-
msg = (f'Variable lookup file must have keys "scopes" (dict) and '
|
|
185
|
-
f'"variable_templates" (dict): {var_look_file}.')
|
|
186
|
-
raise ConfigurationError(msg)
|
|
187
|
-
|
|
188
|
-
Config.__conf.update(Config.__ALLOWED)
|
|
189
|
-
Config.__conf.update(config_dat)
|
|
190
|
-
Config.__conf.update({
|
|
191
|
-
'config_dir': config_dir,
|
|
192
|
-
'profiles_dir': profiles_dir,
|
|
193
|
-
'projects_DB_dir': projects_DB_dir,
|
|
194
|
-
'variable_lookup': var_look_dat,
|
|
195
|
-
})
|
|
196
|
-
Config.__conf.update(Config.__CONSTANTS)
|
|
197
|
-
Config.__conf['cmd_group_defaults']['output_dir'] = (
|
|
198
|
-
Config.__conf['default_output_dir']
|
|
199
|
-
)
|
|
200
|
-
Config.__conf['cmd_group_defaults']['error_dir'] = (
|
|
201
|
-
Config.__conf['default_error_dir']
|
|
202
|
-
)
|
|
203
|
-
|
|
204
|
-
Config.is_set = True
|
|
205
|
-
|
|
206
|
-
@staticmethod
|
|
207
|
-
def get(name):
|
|
208
|
-
if not Config.is_set:
|
|
209
|
-
raise ConfigurationError('Configuration is not yet set.')
|
|
210
|
-
return Config.__conf[name]
|
|
211
|
-
|
|
212
|
-
@staticmethod
|
|
213
|
-
def write_config_file(config_dat, config_file):
|
|
214
|
-
yaml = YAML(typ='rt')
|
|
215
|
-
yaml.dump(config_dat, config_file)
|
|
216
|
-
|
|
217
|
-
@staticmethod
|
|
218
|
-
def update(name, value, config_dir=None):
|
|
219
|
-
'Update the config file.'
|
|
220
|
-
if name not in Config.__ALLOWED:
|
|
221
|
-
msg = f'Cannot update configuration; value "{name}" is not allowed.'
|
|
222
|
-
raise ConfigurationError(msg)
|
|
223
|
-
config_dir = Config.resolve_config_dir(config_dir)
|
|
224
|
-
config_dat, config_file = Config.get_config_file(
|
|
225
|
-
config_dir,
|
|
226
|
-
round_trip_load=True,
|
|
227
|
-
quiet=True,
|
|
228
|
-
)
|
|
229
|
-
config_dat.update({name: value})
|
|
230
|
-
Config.write_config_file(config_dat, config_file)
|
|
231
|
-
if Config.is_set:
|
|
232
|
-
Config.__conf[name] = value
|