hpcflow 0.1.9__py3-none-any.whl → 0.2.0a271__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (275) hide show
  1. hpcflow/__init__.py +2 -11
  2. hpcflow/__pyinstaller/__init__.py +5 -0
  3. hpcflow/__pyinstaller/hook-hpcflow.py +40 -0
  4. hpcflow/_version.py +1 -1
  5. hpcflow/app.py +43 -0
  6. hpcflow/cli.py +2 -462
  7. hpcflow/data/demo_data_manifest/__init__.py +3 -0
  8. hpcflow/data/demo_data_manifest/demo_data_manifest.json +6 -0
  9. hpcflow/data/jinja_templates/test/test_template.txt +8 -0
  10. hpcflow/data/programs/hello_world/README.md +1 -0
  11. hpcflow/data/programs/hello_world/hello_world.c +87 -0
  12. hpcflow/data/programs/hello_world/linux/hello_world +0 -0
  13. hpcflow/data/programs/hello_world/macos/hello_world +0 -0
  14. hpcflow/data/programs/hello_world/win/hello_world.exe +0 -0
  15. hpcflow/data/scripts/__init__.py +1 -0
  16. hpcflow/data/scripts/bad_script.py +2 -0
  17. hpcflow/data/scripts/demo_task_1_generate_t1_infile_1.py +8 -0
  18. hpcflow/data/scripts/demo_task_1_generate_t1_infile_2.py +8 -0
  19. hpcflow/data/scripts/demo_task_1_parse_p3.py +7 -0
  20. hpcflow/data/scripts/do_nothing.py +2 -0
  21. hpcflow/data/scripts/env_specifier_test/input_file_generator_pass_env_spec.py +4 -0
  22. hpcflow/data/scripts/env_specifier_test/main_script_test_pass_env_spec.py +8 -0
  23. hpcflow/data/scripts/env_specifier_test/output_file_parser_pass_env_spec.py +4 -0
  24. hpcflow/data/scripts/env_specifier_test/v1/input_file_generator_basic.py +4 -0
  25. hpcflow/data/scripts/env_specifier_test/v1/main_script_test_direct_in_direct_out.py +7 -0
  26. hpcflow/data/scripts/env_specifier_test/v1/output_file_parser_basic.py +4 -0
  27. hpcflow/data/scripts/env_specifier_test/v2/main_script_test_direct_in_direct_out.py +7 -0
  28. hpcflow/data/scripts/generate_t1_file_01.py +7 -0
  29. hpcflow/data/scripts/import_future_script.py +7 -0
  30. hpcflow/data/scripts/input_file_generator_basic.py +3 -0
  31. hpcflow/data/scripts/input_file_generator_basic_FAIL.py +3 -0
  32. hpcflow/data/scripts/input_file_generator_test_stdout_stderr.py +8 -0
  33. hpcflow/data/scripts/main_script_test_direct_in.py +3 -0
  34. hpcflow/data/scripts/main_script_test_direct_in_direct_out.py +6 -0
  35. hpcflow/data/scripts/main_script_test_direct_in_direct_out_2.py +6 -0
  36. hpcflow/data/scripts/main_script_test_direct_in_direct_out_2_fail_allowed.py +6 -0
  37. hpcflow/data/scripts/main_script_test_direct_in_direct_out_2_fail_allowed_group.py +7 -0
  38. hpcflow/data/scripts/main_script_test_direct_in_direct_out_3.py +6 -0
  39. hpcflow/data/scripts/main_script_test_direct_in_direct_out_all_iters_test.py +15 -0
  40. hpcflow/data/scripts/main_script_test_direct_in_direct_out_env_spec.py +7 -0
  41. hpcflow/data/scripts/main_script_test_direct_in_direct_out_labels.py +8 -0
  42. hpcflow/data/scripts/main_script_test_direct_in_group_direct_out_3.py +6 -0
  43. hpcflow/data/scripts/main_script_test_direct_in_group_one_fail_direct_out_3.py +6 -0
  44. hpcflow/data/scripts/main_script_test_direct_sub_param_in_direct_out.py +6 -0
  45. hpcflow/data/scripts/main_script_test_hdf5_in_obj.py +12 -0
  46. hpcflow/data/scripts/main_script_test_hdf5_in_obj_2.py +12 -0
  47. hpcflow/data/scripts/main_script_test_hdf5_in_obj_group.py +12 -0
  48. hpcflow/data/scripts/main_script_test_hdf5_out_obj.py +11 -0
  49. hpcflow/data/scripts/main_script_test_json_and_direct_in_json_out.py +14 -0
  50. hpcflow/data/scripts/main_script_test_json_in_json_and_direct_out.py +17 -0
  51. hpcflow/data/scripts/main_script_test_json_in_json_out.py +14 -0
  52. hpcflow/data/scripts/main_script_test_json_in_json_out_labels.py +16 -0
  53. hpcflow/data/scripts/main_script_test_json_in_obj.py +12 -0
  54. hpcflow/data/scripts/main_script_test_json_out_FAIL.py +3 -0
  55. hpcflow/data/scripts/main_script_test_json_out_obj.py +10 -0
  56. hpcflow/data/scripts/main_script_test_json_sub_param_in_json_out_labels.py +16 -0
  57. hpcflow/data/scripts/main_script_test_shell_env_vars.py +12 -0
  58. hpcflow/data/scripts/main_script_test_std_out_std_err.py +6 -0
  59. hpcflow/data/scripts/output_file_parser_basic.py +3 -0
  60. hpcflow/data/scripts/output_file_parser_basic_FAIL.py +7 -0
  61. hpcflow/data/scripts/output_file_parser_test_stdout_stderr.py +8 -0
  62. hpcflow/data/scripts/parse_t1_file_01.py +4 -0
  63. hpcflow/data/scripts/script_exit_test.py +5 -0
  64. hpcflow/data/template_components/__init__.py +1 -0
  65. hpcflow/data/template_components/command_files.yaml +26 -0
  66. hpcflow/data/template_components/environments.yaml +13 -0
  67. hpcflow/data/template_components/parameters.yaml +14 -0
  68. hpcflow/data/template_components/task_schemas.yaml +139 -0
  69. hpcflow/data/workflows/workflow_1.yaml +5 -0
  70. hpcflow/examples.ipynb +1037 -0
  71. hpcflow/sdk/__init__.py +149 -0
  72. hpcflow/sdk/app.py +4266 -0
  73. hpcflow/sdk/cli.py +1479 -0
  74. hpcflow/sdk/cli_common.py +385 -0
  75. hpcflow/sdk/config/__init__.py +5 -0
  76. hpcflow/sdk/config/callbacks.py +246 -0
  77. hpcflow/sdk/config/cli.py +388 -0
  78. hpcflow/sdk/config/config.py +1410 -0
  79. hpcflow/sdk/config/config_file.py +501 -0
  80. hpcflow/sdk/config/errors.py +272 -0
  81. hpcflow/sdk/config/types.py +150 -0
  82. hpcflow/sdk/core/__init__.py +38 -0
  83. hpcflow/sdk/core/actions.py +3857 -0
  84. hpcflow/sdk/core/app_aware.py +25 -0
  85. hpcflow/sdk/core/cache.py +224 -0
  86. hpcflow/sdk/core/command_files.py +814 -0
  87. hpcflow/sdk/core/commands.py +424 -0
  88. hpcflow/sdk/core/element.py +2071 -0
  89. hpcflow/sdk/core/enums.py +221 -0
  90. hpcflow/sdk/core/environment.py +256 -0
  91. hpcflow/sdk/core/errors.py +1043 -0
  92. hpcflow/sdk/core/execute.py +207 -0
  93. hpcflow/sdk/core/json_like.py +809 -0
  94. hpcflow/sdk/core/loop.py +1320 -0
  95. hpcflow/sdk/core/loop_cache.py +282 -0
  96. hpcflow/sdk/core/object_list.py +933 -0
  97. hpcflow/sdk/core/parameters.py +3371 -0
  98. hpcflow/sdk/core/rule.py +196 -0
  99. hpcflow/sdk/core/run_dir_files.py +57 -0
  100. hpcflow/sdk/core/skip_reason.py +7 -0
  101. hpcflow/sdk/core/task.py +3792 -0
  102. hpcflow/sdk/core/task_schema.py +993 -0
  103. hpcflow/sdk/core/test_utils.py +538 -0
  104. hpcflow/sdk/core/types.py +447 -0
  105. hpcflow/sdk/core/utils.py +1207 -0
  106. hpcflow/sdk/core/validation.py +87 -0
  107. hpcflow/sdk/core/values.py +477 -0
  108. hpcflow/sdk/core/workflow.py +4820 -0
  109. hpcflow/sdk/core/zarr_io.py +206 -0
  110. hpcflow/sdk/data/__init__.py +13 -0
  111. hpcflow/sdk/data/config_file_schema.yaml +34 -0
  112. hpcflow/sdk/data/config_schema.yaml +260 -0
  113. hpcflow/sdk/data/environments_spec_schema.yaml +21 -0
  114. hpcflow/sdk/data/files_spec_schema.yaml +5 -0
  115. hpcflow/sdk/data/parameters_spec_schema.yaml +7 -0
  116. hpcflow/sdk/data/task_schema_spec_schema.yaml +3 -0
  117. hpcflow/sdk/data/workflow_spec_schema.yaml +22 -0
  118. hpcflow/sdk/demo/__init__.py +3 -0
  119. hpcflow/sdk/demo/cli.py +242 -0
  120. hpcflow/sdk/helper/__init__.py +3 -0
  121. hpcflow/sdk/helper/cli.py +137 -0
  122. hpcflow/sdk/helper/helper.py +300 -0
  123. hpcflow/sdk/helper/watcher.py +192 -0
  124. hpcflow/sdk/log.py +288 -0
  125. hpcflow/sdk/persistence/__init__.py +18 -0
  126. hpcflow/sdk/persistence/base.py +2817 -0
  127. hpcflow/sdk/persistence/defaults.py +6 -0
  128. hpcflow/sdk/persistence/discovery.py +39 -0
  129. hpcflow/sdk/persistence/json.py +954 -0
  130. hpcflow/sdk/persistence/pending.py +948 -0
  131. hpcflow/sdk/persistence/store_resource.py +203 -0
  132. hpcflow/sdk/persistence/types.py +309 -0
  133. hpcflow/sdk/persistence/utils.py +73 -0
  134. hpcflow/sdk/persistence/zarr.py +2388 -0
  135. hpcflow/sdk/runtime.py +320 -0
  136. hpcflow/sdk/submission/__init__.py +3 -0
  137. hpcflow/sdk/submission/enums.py +70 -0
  138. hpcflow/sdk/submission/jobscript.py +2379 -0
  139. hpcflow/sdk/submission/schedulers/__init__.py +281 -0
  140. hpcflow/sdk/submission/schedulers/direct.py +233 -0
  141. hpcflow/sdk/submission/schedulers/sge.py +376 -0
  142. hpcflow/sdk/submission/schedulers/slurm.py +598 -0
  143. hpcflow/sdk/submission/schedulers/utils.py +25 -0
  144. hpcflow/sdk/submission/shells/__init__.py +52 -0
  145. hpcflow/sdk/submission/shells/base.py +229 -0
  146. hpcflow/sdk/submission/shells/bash.py +504 -0
  147. hpcflow/sdk/submission/shells/os_version.py +115 -0
  148. hpcflow/sdk/submission/shells/powershell.py +352 -0
  149. hpcflow/sdk/submission/submission.py +1402 -0
  150. hpcflow/sdk/submission/types.py +140 -0
  151. hpcflow/sdk/typing.py +194 -0
  152. hpcflow/sdk/utils/arrays.py +69 -0
  153. hpcflow/sdk/utils/deferred_file.py +55 -0
  154. hpcflow/sdk/utils/hashing.py +16 -0
  155. hpcflow/sdk/utils/patches.py +31 -0
  156. hpcflow/sdk/utils/strings.py +69 -0
  157. hpcflow/tests/api/test_api.py +32 -0
  158. hpcflow/tests/conftest.py +123 -0
  159. hpcflow/tests/data/__init__.py +0 -0
  160. hpcflow/tests/data/benchmark_N_elements.yaml +6 -0
  161. hpcflow/tests/data/benchmark_script_runner.yaml +26 -0
  162. hpcflow/tests/data/multi_path_sequences.yaml +29 -0
  163. hpcflow/tests/data/workflow_1.json +10 -0
  164. hpcflow/tests/data/workflow_1.yaml +5 -0
  165. hpcflow/tests/data/workflow_1_slurm.yaml +8 -0
  166. hpcflow/tests/data/workflow_1_wsl.yaml +8 -0
  167. hpcflow/tests/data/workflow_test_run_abort.yaml +42 -0
  168. hpcflow/tests/jinja_templates/test_jinja_templates.py +161 -0
  169. hpcflow/tests/programs/test_programs.py +180 -0
  170. hpcflow/tests/schedulers/direct_linux/test_direct_linux_submission.py +12 -0
  171. hpcflow/tests/schedulers/sge/test_sge_submission.py +36 -0
  172. hpcflow/tests/schedulers/slurm/test_slurm_submission.py +14 -0
  173. hpcflow/tests/scripts/test_input_file_generators.py +282 -0
  174. hpcflow/tests/scripts/test_main_scripts.py +1361 -0
  175. hpcflow/tests/scripts/test_non_snippet_script.py +46 -0
  176. hpcflow/tests/scripts/test_ouput_file_parsers.py +353 -0
  177. hpcflow/tests/shells/wsl/test_wsl_submission.py +14 -0
  178. hpcflow/tests/unit/test_action.py +1066 -0
  179. hpcflow/tests/unit/test_action_rule.py +24 -0
  180. hpcflow/tests/unit/test_app.py +132 -0
  181. hpcflow/tests/unit/test_cache.py +46 -0
  182. hpcflow/tests/unit/test_cli.py +172 -0
  183. hpcflow/tests/unit/test_command.py +377 -0
  184. hpcflow/tests/unit/test_config.py +195 -0
  185. hpcflow/tests/unit/test_config_file.py +162 -0
  186. hpcflow/tests/unit/test_element.py +666 -0
  187. hpcflow/tests/unit/test_element_iteration.py +88 -0
  188. hpcflow/tests/unit/test_element_set.py +158 -0
  189. hpcflow/tests/unit/test_group.py +115 -0
  190. hpcflow/tests/unit/test_input_source.py +1479 -0
  191. hpcflow/tests/unit/test_input_value.py +398 -0
  192. hpcflow/tests/unit/test_jobscript_unit.py +757 -0
  193. hpcflow/tests/unit/test_json_like.py +1247 -0
  194. hpcflow/tests/unit/test_loop.py +2674 -0
  195. hpcflow/tests/unit/test_meta_task.py +325 -0
  196. hpcflow/tests/unit/test_multi_path_sequences.py +259 -0
  197. hpcflow/tests/unit/test_object_list.py +116 -0
  198. hpcflow/tests/unit/test_parameter.py +243 -0
  199. hpcflow/tests/unit/test_persistence.py +664 -0
  200. hpcflow/tests/unit/test_resources.py +243 -0
  201. hpcflow/tests/unit/test_run.py +286 -0
  202. hpcflow/tests/unit/test_run_directories.py +29 -0
  203. hpcflow/tests/unit/test_runtime.py +9 -0
  204. hpcflow/tests/unit/test_schema_input.py +372 -0
  205. hpcflow/tests/unit/test_shell.py +129 -0
  206. hpcflow/tests/unit/test_slurm.py +39 -0
  207. hpcflow/tests/unit/test_submission.py +502 -0
  208. hpcflow/tests/unit/test_task.py +2560 -0
  209. hpcflow/tests/unit/test_task_schema.py +182 -0
  210. hpcflow/tests/unit/test_utils.py +616 -0
  211. hpcflow/tests/unit/test_value_sequence.py +549 -0
  212. hpcflow/tests/unit/test_values.py +91 -0
  213. hpcflow/tests/unit/test_workflow.py +827 -0
  214. hpcflow/tests/unit/test_workflow_template.py +186 -0
  215. hpcflow/tests/unit/utils/test_arrays.py +40 -0
  216. hpcflow/tests/unit/utils/test_deferred_file_writer.py +34 -0
  217. hpcflow/tests/unit/utils/test_hashing.py +65 -0
  218. hpcflow/tests/unit/utils/test_patches.py +5 -0
  219. hpcflow/tests/unit/utils/test_redirect_std.py +50 -0
  220. hpcflow/tests/unit/utils/test_strings.py +97 -0
  221. hpcflow/tests/workflows/__init__.py +0 -0
  222. hpcflow/tests/workflows/test_directory_structure.py +31 -0
  223. hpcflow/tests/workflows/test_jobscript.py +355 -0
  224. hpcflow/tests/workflows/test_run_status.py +198 -0
  225. hpcflow/tests/workflows/test_skip_downstream.py +696 -0
  226. hpcflow/tests/workflows/test_submission.py +140 -0
  227. hpcflow/tests/workflows/test_workflows.py +564 -0
  228. hpcflow/tests/workflows/test_zip.py +18 -0
  229. hpcflow/viz_demo.ipynb +6794 -0
  230. hpcflow-0.2.0a271.dist-info/LICENSE +375 -0
  231. hpcflow-0.2.0a271.dist-info/METADATA +65 -0
  232. hpcflow-0.2.0a271.dist-info/RECORD +237 -0
  233. {hpcflow-0.1.9.dist-info → hpcflow-0.2.0a271.dist-info}/WHEEL +4 -5
  234. hpcflow-0.2.0a271.dist-info/entry_points.txt +6 -0
  235. hpcflow/api.py +0 -458
  236. hpcflow/archive/archive.py +0 -308
  237. hpcflow/archive/cloud/cloud.py +0 -47
  238. hpcflow/archive/cloud/errors.py +0 -9
  239. hpcflow/archive/cloud/providers/dropbox.py +0 -432
  240. hpcflow/archive/errors.py +0 -5
  241. hpcflow/base_db.py +0 -4
  242. hpcflow/config.py +0 -232
  243. hpcflow/copytree.py +0 -66
  244. hpcflow/data/examples/_config.yml +0 -14
  245. hpcflow/data/examples/damask/demo/1.run.yml +0 -4
  246. hpcflow/data/examples/damask/demo/2.process.yml +0 -29
  247. hpcflow/data/examples/damask/demo/geom.geom +0 -2052
  248. hpcflow/data/examples/damask/demo/load.load +0 -1
  249. hpcflow/data/examples/damask/demo/material.config +0 -185
  250. hpcflow/data/examples/damask/inputs/geom.geom +0 -2052
  251. hpcflow/data/examples/damask/inputs/load.load +0 -1
  252. hpcflow/data/examples/damask/inputs/material.config +0 -185
  253. hpcflow/data/examples/damask/profiles/_variable_lookup.yml +0 -21
  254. hpcflow/data/examples/damask/profiles/damask.yml +0 -4
  255. hpcflow/data/examples/damask/profiles/damask_process.yml +0 -8
  256. hpcflow/data/examples/damask/profiles/damask_run.yml +0 -5
  257. hpcflow/data/examples/damask/profiles/default.yml +0 -6
  258. hpcflow/data/examples/thinking.yml +0 -177
  259. hpcflow/errors.py +0 -2
  260. hpcflow/init_db.py +0 -37
  261. hpcflow/models.py +0 -2549
  262. hpcflow/nesting.py +0 -9
  263. hpcflow/profiles.py +0 -455
  264. hpcflow/project.py +0 -81
  265. hpcflow/scheduler.py +0 -323
  266. hpcflow/utils.py +0 -103
  267. hpcflow/validation.py +0 -167
  268. hpcflow/variables.py +0 -544
  269. hpcflow-0.1.9.dist-info/METADATA +0 -168
  270. hpcflow-0.1.9.dist-info/RECORD +0 -45
  271. hpcflow-0.1.9.dist-info/entry_points.txt +0 -8
  272. hpcflow-0.1.9.dist-info/top_level.txt +0 -1
  273. /hpcflow/{archive → data/jinja_templates}/__init__.py +0 -0
  274. /hpcflow/{archive/cloud → data/programs}/__init__.py +0 -0
  275. /hpcflow/{archive/cloud/providers → data/workflows}/__init__.py +0 -0
@@ -0,0 +1,388 @@
1
+ """Module defining a function that returns the click CLI group for manipulating the app
2
+ configuration."""
3
+
4
+ from __future__ import annotations
5
+ import json
6
+ import logging
7
+ import warnings
8
+ from functools import wraps
9
+ from contextlib import contextmanager
10
+ from typing import TYPE_CHECKING
11
+
12
+ import click
13
+ from colorama import init as colorama_init
14
+ from termcolor import colored # type: ignore
15
+
16
+ from hpcflow.sdk.core.utils import open_file
17
+
18
+ from hpcflow.sdk.config.errors import ConfigError
19
+ from hpcflow.sdk.config.config import Config
20
+
21
+ if TYPE_CHECKING:
22
+ from collections.abc import Callable, Sequence
23
+ from ..app import BaseApp
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+ colorama_init(autoreset=True)
28
+
29
+
30
+ def CLI_exception_wrapper_gen(*exception_cls):
31
+ """
32
+ Decorator factory that enhances the wrapped function to display a nice message on
33
+ success or failure.
34
+ """
35
+
36
+ @contextmanager
37
+ def warning_formatter():
38
+ """
39
+ Context manager to apply a simple warning formatter that shows just the warning
40
+ type and the message. We use this in the CLI to avoid producing distracting
41
+ output.
42
+ """
43
+
44
+ def custom_warning_formatter(
45
+ message, category, filename, lineno, file=None, line=None
46
+ ):
47
+ return f"{colored(category.__name__, 'yellow')}: {message}\n"
48
+
49
+ existing_func = warnings.formatwarning
50
+ try:
51
+ warnings.formatwarning = custom_warning_formatter
52
+ yield
53
+ finally:
54
+ warnings.formatwarning = existing_func
55
+
56
+ def CLI_exception_wrapper(func: Callable):
57
+ """Decorator
58
+
59
+ Parameters
60
+ ----------
61
+ func
62
+ Function that return a non-None value if the operation succeeds
63
+ """
64
+
65
+ @wraps(func)
66
+ @click.pass_context
67
+ def wrapper(ctx: click.Context, *args, **kwargs):
68
+ try:
69
+ with warning_formatter():
70
+ out = func(*args, **kwargs)
71
+ if out is not None:
72
+ click.echo(f"{colored('✔ Config file updated.', 'green')}")
73
+ return out
74
+ except exception_cls as err:
75
+ click.echo(f"{colored(err.__class__.__name__, 'red')}: {err}")
76
+ ctx.exit(1)
77
+
78
+ return wrapper
79
+
80
+ return CLI_exception_wrapper
81
+
82
+
83
+ def get_config_CLI(app: BaseApp) -> click.Group:
84
+ """Generate the configuration CLI for the app."""
85
+
86
+ pass_config = click.make_pass_decorator(Config)
87
+
88
+ def find_config(ctx: click.Context) -> Config:
89
+ if (cfg := ctx.find_object(Config)) is None:
90
+ raise RuntimeError("no configuration defined")
91
+ return cfg
92
+
93
+ def show_all_config(ctx: click.Context, param, value: bool):
94
+ if not value or ctx.resilient_parsing:
95
+ return
96
+ find_config(ctx)._show(config=True, metadata=False)
97
+ ctx.exit()
98
+
99
+ def show_all_metadata(ctx: click.Context, param, value: bool):
100
+ if not value or ctx.resilient_parsing:
101
+ return
102
+ find_config(ctx)._show(config=False, metadata=True)
103
+ ctx.exit()
104
+
105
+ def show_config_file(ctx: click.Context, param, value: bool):
106
+ if not value or ctx.resilient_parsing:
107
+ return
108
+ print(find_config(ctx).config_file_contents)
109
+ ctx.exit()
110
+
111
+ @click.group()
112
+ @click.option(
113
+ "--no-callback",
114
+ multiple=True,
115
+ help="Exclude a named get/set callback function during execution of the command.",
116
+ )
117
+ @click.pass_context
118
+ def config(ctx: click.Context, no_callback: Sequence[str]):
119
+ """Configuration sub-command for getting and setting data in the configuration
120
+ file(s)."""
121
+ ctx.obj = app.config
122
+ if no_callback:
123
+ app.config._disable_callbacks(no_callback)
124
+
125
+ @config.command("list")
126
+ @pass_config
127
+ def config_list(config: Config):
128
+ """Show a list of all configurable keys."""
129
+ click.echo("\n".join(config.get_configurable()))
130
+
131
+ @config.command("import")
132
+ @click.argument("file_path")
133
+ @click.option(
134
+ "--rename/--no-rename",
135
+ default=True,
136
+ help=(
137
+ "Rename the currently loaded config file according to the name of the file "
138
+ "that is being imported (default is to rename). Ignored if `--new` is "
139
+ "specified."
140
+ ),
141
+ )
142
+ @click.option(
143
+ "--new",
144
+ type=click.BOOL,
145
+ is_flag=True,
146
+ default=False,
147
+ help=(
148
+ "If True, generate a new default config, and import the file into this "
149
+ "config. If False, modify the currently loaded config."
150
+ ),
151
+ )
152
+ @pass_config
153
+ def import_from_file(config: Config, file_path: str, rename: bool, new: bool):
154
+ """Update the config file with keys from a YAML file."""
155
+ config.import_from_file(file_path, rename=rename, make_new=new)
156
+
157
+ @config.command()
158
+ @click.argument("name")
159
+ @click.option(
160
+ "--all",
161
+ is_flag=True,
162
+ expose_value=False,
163
+ is_eager=True,
164
+ help="Show all configuration items.",
165
+ callback=show_all_config,
166
+ )
167
+ @click.option(
168
+ "--metadata",
169
+ is_flag=True,
170
+ expose_value=False,
171
+ is_eager=True,
172
+ help="Show all metadata items.",
173
+ callback=show_all_metadata,
174
+ )
175
+ @click.option(
176
+ "--file",
177
+ is_flag=True,
178
+ expose_value=False,
179
+ is_eager=True,
180
+ help="Show the contents of the configuration file.",
181
+ callback=show_config_file,
182
+ )
183
+ @pass_config
184
+ @CLI_exception_wrapper_gen(ConfigError)
185
+ def get(config: Config, name: str):
186
+ """Show the value of the specified configuration item."""
187
+ val = config.get(name)
188
+ if isinstance(val, list):
189
+ val = "\n".join(str(i) for i in val)
190
+ click.echo(val)
191
+
192
+ @config.command()
193
+ @click.argument("name")
194
+ @click.argument("value")
195
+ @click.option(
196
+ "--json",
197
+ "is_json",
198
+ is_flag=True,
199
+ default=False,
200
+ help="Interpret VALUE as a JSON string.",
201
+ )
202
+ @pass_config
203
+ @CLI_exception_wrapper_gen(ConfigError)
204
+ def set(config: Config, name: str, value: str, is_json: bool):
205
+ """Set and save the value of the specified configuration item."""
206
+ if is_json:
207
+ config.set(name, value, is_json=True)
208
+ else:
209
+ config.set(name, value, is_json=False)
210
+ config.save()
211
+
212
+ @config.command()
213
+ @click.argument("name")
214
+ @pass_config
215
+ @CLI_exception_wrapper_gen(ConfigError)
216
+ def unset(config: Config, name: str):
217
+ """Unset and save the value of the specified configuration item."""
218
+ config.unset(name)
219
+ config.save()
220
+
221
+ @config.command()
222
+ @click.argument("name")
223
+ @click.argument("value")
224
+ @click.option(
225
+ "--json",
226
+ "is_json",
227
+ is_flag=True,
228
+ default=False,
229
+ help="Interpret VALUE as a JSON string.",
230
+ )
231
+ @pass_config
232
+ @CLI_exception_wrapper_gen(ConfigError)
233
+ def append(config: Config, name: str, value: str, is_json: bool):
234
+ """Append a new value to the specified configuration item.
235
+
236
+ NAME is the dot-delimited path to the list to be appended to.
237
+
238
+ """
239
+ if is_json:
240
+ config.append(name, value, is_json=True)
241
+ else:
242
+ config.append(name, value, is_json=False)
243
+ config.save()
244
+
245
+ @config.command()
246
+ @click.argument("name")
247
+ @click.argument("value")
248
+ @click.option(
249
+ "--json",
250
+ "is_json",
251
+ is_flag=True,
252
+ default=False,
253
+ help="Interpret VALUE as a JSON string.",
254
+ )
255
+ @pass_config
256
+ @CLI_exception_wrapper_gen(ConfigError)
257
+ def prepend(config: Config, name: str, value: str, is_json: bool):
258
+ """Prepend a new value to the specified configuration item.
259
+
260
+ NAME is the dot-delimited path to the list to be prepended to.
261
+
262
+ """
263
+ if is_json:
264
+ config.prepend(name, value, is_json=True)
265
+ else:
266
+ config.prepend(name, value, is_json=False)
267
+ config.save()
268
+
269
+ @config.command(context_settings={"ignore_unknown_options": True})
270
+ @click.argument("name")
271
+ @click.argument("index", type=click.types.INT)
272
+ @pass_config
273
+ @CLI_exception_wrapper_gen(ConfigError)
274
+ def pop(config: Config, name: str, index: int):
275
+ """Remove a value from a list-like configuration item.
276
+
277
+ NAME is the dot-delimited path to the list to be modified.
278
+
279
+ """
280
+ config.pop(name, index)
281
+ config.save()
282
+
283
+ @config.command()
284
+ @click.argument("name")
285
+ @click.argument("value")
286
+ @click.option(
287
+ "--json",
288
+ "is_json",
289
+ is_flag=True,
290
+ default=False,
291
+ help="Interpret VALUE as a JSON string.",
292
+ )
293
+ @pass_config
294
+ @CLI_exception_wrapper_gen(ConfigError)
295
+ def update(config: Config, name: str, value: str, is_json: bool):
296
+ """Update a map-like value in the configuration.
297
+
298
+ NAME is the dot-delimited path to the map to be updated.
299
+
300
+ """
301
+ if is_json:
302
+ config.update(name, value, is_json=True)
303
+ else:
304
+ config.update(name, value, is_json=False)
305
+ config.save()
306
+
307
+ @config.command()
308
+ @click.argument("name")
309
+ @click.option("--defaults")
310
+ @pass_config
311
+ @CLI_exception_wrapper_gen(ConfigError)
312
+ def add_scheduler(config: Config, name: str, defaults: str | None):
313
+ if defaults:
314
+ loaded_defaults: dict = json.loads(defaults)
315
+ else:
316
+ loaded_defaults = {}
317
+ config.add_scheduler(name, **loaded_defaults)
318
+ config.save()
319
+
320
+ @config.command()
321
+ @click.argument("name")
322
+ @click.option("--defaults")
323
+ @pass_config
324
+ @CLI_exception_wrapper_gen(ConfigError)
325
+ def add_shell(config: Config, name: str, defaults: str | None):
326
+ if defaults:
327
+ loaded_defaults: dict = json.loads(defaults)
328
+ else:
329
+ loaded_defaults = {}
330
+ config.add_shell(name, **loaded_defaults)
331
+ config.save()
332
+
333
+ @config.command()
334
+ @click.option("--defaults")
335
+ @pass_config
336
+ @CLI_exception_wrapper_gen(ConfigError)
337
+ def add_shell_wsl(config: Config, defaults: str | None):
338
+ if defaults:
339
+ loaded_defaults: dict = json.loads(defaults)
340
+ else:
341
+ loaded_defaults = {}
342
+ config.add_shell_WSL(**loaded_defaults)
343
+ config.save()
344
+
345
+ @config.command()
346
+ @click.argument("sha")
347
+ @pass_config
348
+ @CLI_exception_wrapper_gen(ConfigError)
349
+ def set_github_demo_data_dir(config: Config, sha: str):
350
+ config.set_github_demo_data_dir(sha=sha)
351
+ config.save()
352
+
353
+ @config.command()
354
+ def load_data_files():
355
+ """Check we can load the data files (e.g. task schema files) as specified in the
356
+ configuration."""
357
+ app.load_data_files()
358
+ # FIXME: No such method?
359
+
360
+ @config.command()
361
+ @click.option("--path", is_flag=True, default=False)
362
+ @pass_config
363
+ def open(config: Config, path: bool = False):
364
+ """Alias for `{package_name} open config`: open the configuration file, or retrieve
365
+ it's path."""
366
+ file_path = config.get("config_file_path")
367
+ if path:
368
+ click.echo(file_path)
369
+ else:
370
+ open_file(file_path)
371
+
372
+ @config.command()
373
+ @click.argument("known_name")
374
+ @click.option(
375
+ "--path",
376
+ default=None,
377
+ help=(
378
+ "An `fsspec`-compatible path in which to look for configuration-import "
379
+ "files."
380
+ ),
381
+ )
382
+ @pass_config
383
+ def init(config: Config, known_name: str, path: str | None):
384
+ config.init(known_name=known_name, path=path)
385
+
386
+ open.help = (open.help or "").format(package_name=app.package_name)
387
+
388
+ return config