hpcflow-new2 0.2.0a188__py3-none-any.whl → 0.2.0a190__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/__pyinstaller/hook-hpcflow.py +8 -6
- hpcflow/_version.py +1 -1
- hpcflow/app.py +1 -0
- hpcflow/data/scripts/main_script_test_hdf5_in_obj.py +1 -1
- hpcflow/data/scripts/main_script_test_hdf5_out_obj.py +1 -1
- hpcflow/sdk/__init__.py +21 -15
- hpcflow/sdk/app.py +2133 -770
- hpcflow/sdk/cli.py +281 -250
- hpcflow/sdk/cli_common.py +6 -2
- hpcflow/sdk/config/__init__.py +1 -1
- hpcflow/sdk/config/callbacks.py +77 -42
- hpcflow/sdk/config/cli.py +126 -103
- hpcflow/sdk/config/config.py +578 -311
- hpcflow/sdk/config/config_file.py +131 -95
- hpcflow/sdk/config/errors.py +112 -85
- hpcflow/sdk/config/types.py +145 -0
- hpcflow/sdk/core/actions.py +1054 -994
- hpcflow/sdk/core/app_aware.py +24 -0
- hpcflow/sdk/core/cache.py +81 -63
- hpcflow/sdk/core/command_files.py +275 -185
- hpcflow/sdk/core/commands.py +111 -107
- hpcflow/sdk/core/element.py +724 -503
- hpcflow/sdk/core/enums.py +192 -0
- hpcflow/sdk/core/environment.py +74 -93
- hpcflow/sdk/core/errors.py +398 -51
- hpcflow/sdk/core/json_like.py +540 -272
- hpcflow/sdk/core/loop.py +380 -334
- hpcflow/sdk/core/loop_cache.py +160 -43
- hpcflow/sdk/core/object_list.py +370 -207
- hpcflow/sdk/core/parameters.py +728 -600
- hpcflow/sdk/core/rule.py +59 -41
- hpcflow/sdk/core/run_dir_files.py +33 -22
- hpcflow/sdk/core/task.py +1546 -1325
- hpcflow/sdk/core/task_schema.py +240 -196
- hpcflow/sdk/core/test_utils.py +126 -88
- hpcflow/sdk/core/types.py +387 -0
- hpcflow/sdk/core/utils.py +410 -305
- hpcflow/sdk/core/validation.py +82 -9
- hpcflow/sdk/core/workflow.py +1192 -1028
- hpcflow/sdk/core/zarr_io.py +98 -137
- hpcflow/sdk/demo/cli.py +46 -33
- hpcflow/sdk/helper/cli.py +18 -16
- hpcflow/sdk/helper/helper.py +75 -63
- hpcflow/sdk/helper/watcher.py +61 -28
- hpcflow/sdk/log.py +83 -59
- hpcflow/sdk/persistence/__init__.py +8 -31
- hpcflow/sdk/persistence/base.py +988 -586
- hpcflow/sdk/persistence/defaults.py +6 -0
- hpcflow/sdk/persistence/discovery.py +38 -0
- hpcflow/sdk/persistence/json.py +408 -153
- hpcflow/sdk/persistence/pending.py +158 -123
- hpcflow/sdk/persistence/store_resource.py +37 -22
- hpcflow/sdk/persistence/types.py +307 -0
- hpcflow/sdk/persistence/utils.py +14 -11
- hpcflow/sdk/persistence/zarr.py +477 -420
- hpcflow/sdk/runtime.py +44 -41
- hpcflow/sdk/submission/{jobscript_info.py → enums.py} +39 -12
- hpcflow/sdk/submission/jobscript.py +444 -404
- hpcflow/sdk/submission/schedulers/__init__.py +133 -40
- hpcflow/sdk/submission/schedulers/direct.py +97 -71
- hpcflow/sdk/submission/schedulers/sge.py +132 -126
- hpcflow/sdk/submission/schedulers/slurm.py +263 -268
- hpcflow/sdk/submission/schedulers/utils.py +7 -2
- hpcflow/sdk/submission/shells/__init__.py +14 -15
- hpcflow/sdk/submission/shells/base.py +102 -29
- hpcflow/sdk/submission/shells/bash.py +72 -55
- hpcflow/sdk/submission/shells/os_version.py +31 -30
- hpcflow/sdk/submission/shells/powershell.py +37 -29
- hpcflow/sdk/submission/submission.py +203 -257
- hpcflow/sdk/submission/types.py +143 -0
- hpcflow/sdk/typing.py +163 -12
- hpcflow/tests/conftest.py +8 -6
- hpcflow/tests/schedulers/slurm/test_slurm_submission.py +5 -2
- hpcflow/tests/scripts/test_main_scripts.py +60 -30
- hpcflow/tests/shells/wsl/test_wsl_submission.py +6 -4
- hpcflow/tests/unit/test_action.py +86 -75
- hpcflow/tests/unit/test_action_rule.py +9 -4
- hpcflow/tests/unit/test_app.py +13 -6
- hpcflow/tests/unit/test_cli.py +1 -1
- hpcflow/tests/unit/test_command.py +71 -54
- hpcflow/tests/unit/test_config.py +20 -15
- hpcflow/tests/unit/test_config_file.py +21 -18
- hpcflow/tests/unit/test_element.py +58 -62
- hpcflow/tests/unit/test_element_iteration.py +3 -1
- hpcflow/tests/unit/test_element_set.py +29 -19
- hpcflow/tests/unit/test_group.py +4 -2
- hpcflow/tests/unit/test_input_source.py +116 -93
- hpcflow/tests/unit/test_input_value.py +29 -24
- hpcflow/tests/unit/test_json_like.py +44 -35
- hpcflow/tests/unit/test_loop.py +65 -58
- hpcflow/tests/unit/test_object_list.py +17 -12
- hpcflow/tests/unit/test_parameter.py +16 -7
- hpcflow/tests/unit/test_persistence.py +48 -35
- hpcflow/tests/unit/test_resources.py +20 -18
- hpcflow/tests/unit/test_run.py +8 -3
- hpcflow/tests/unit/test_runtime.py +2 -1
- hpcflow/tests/unit/test_schema_input.py +23 -15
- hpcflow/tests/unit/test_shell.py +3 -2
- hpcflow/tests/unit/test_slurm.py +8 -7
- hpcflow/tests/unit/test_submission.py +39 -19
- hpcflow/tests/unit/test_task.py +352 -247
- hpcflow/tests/unit/test_task_schema.py +33 -20
- hpcflow/tests/unit/test_utils.py +9 -11
- hpcflow/tests/unit/test_value_sequence.py +15 -12
- hpcflow/tests/unit/test_workflow.py +114 -83
- hpcflow/tests/unit/test_workflow_template.py +0 -1
- hpcflow/tests/workflows/test_jobscript.py +2 -1
- hpcflow/tests/workflows/test_workflows.py +18 -13
- {hpcflow_new2-0.2.0a188.dist-info → hpcflow_new2-0.2.0a190.dist-info}/METADATA +2 -1
- hpcflow_new2-0.2.0a190.dist-info/RECORD +165 -0
- hpcflow/sdk/core/parallel.py +0 -21
- hpcflow_new2-0.2.0a188.dist-info/RECORD +0 -158
- {hpcflow_new2-0.2.0a188.dist-info → hpcflow_new2-0.2.0a190.dist-info}/LICENSE +0 -0
- {hpcflow_new2-0.2.0a188.dist-info → hpcflow_new2-0.2.0a190.dist-info}/WHEEL +0 -0
- {hpcflow_new2-0.2.0a188.dist-info → hpcflow_new2-0.2.0a190.dist-info}/entry_points.txt +0 -0
@@ -12,13 +12,13 @@ import os
|
|
12
12
|
from pathlib import Path
|
13
13
|
import random
|
14
14
|
import string
|
15
|
-
from typing import
|
15
|
+
from typing import cast, TYPE_CHECKING
|
16
16
|
|
17
17
|
from ruamel.yaml import YAML
|
18
18
|
|
19
|
-
from hpcflow.sdk.core.validation import get_schema
|
19
|
+
from hpcflow.sdk.core.validation import Schema, get_schema
|
20
20
|
|
21
|
-
from .errors import (
|
21
|
+
from hpcflow.sdk.config.errors import (
|
22
22
|
ConfigChangeFileUpdateError,
|
23
23
|
ConfigDefaultValidationError,
|
24
24
|
ConfigFileInvocationIncompatibleError,
|
@@ -28,6 +28,12 @@ from .errors import (
|
|
28
28
|
ConfigValidationError,
|
29
29
|
)
|
30
30
|
|
31
|
+
if TYPE_CHECKING:
|
32
|
+
from typing import Any
|
33
|
+
from ..typing import PathLike
|
34
|
+
from .config import Config, ConfigOptions
|
35
|
+
from .types import ConfigDict, DefaultConfiguration, InvocationDescriptor
|
36
|
+
|
31
37
|
|
32
38
|
class ConfigFile:
|
33
39
|
"""
|
@@ -43,7 +49,7 @@ class ConfigFile:
|
|
43
49
|
Configuration options.
|
44
50
|
"""
|
45
51
|
|
46
|
-
def __init__(self, directory, logger, config_options):
|
52
|
+
def __init__(self, directory, logger: logging.Logger, config_options: ConfigOptions):
|
47
53
|
#: Where to log messages.
|
48
54
|
self.logger = logger
|
49
55
|
#: The directory containing the configuration file.
|
@@ -53,27 +59,59 @@ class ConfigFile:
|
|
53
59
|
directory=directory,
|
54
60
|
)
|
55
61
|
|
56
|
-
self._configs = []
|
62
|
+
self._configs: list[Config] = []
|
57
63
|
|
58
64
|
# set by _load_file_data:
|
59
|
-
|
60
|
-
self.
|
61
|
-
|
62
|
-
self.
|
63
|
-
#: The parsed contents of the config file.
|
64
|
-
self.data = None
|
65
|
-
#: The parsed contents of the config file where the alternate parser was used.
|
66
|
-
self.data_rt = None
|
65
|
+
self.__path: Path | None = None
|
66
|
+
self.__contents: str | None = None
|
67
|
+
self.__data: ConfigDict | None = None
|
68
|
+
self.__data_rt: ConfigDict | None = None
|
67
69
|
|
68
70
|
self._load_file_data(config_options)
|
69
|
-
self.file_schema = self._validate(self.
|
71
|
+
self.file_schema = self._validate(self.__data)
|
72
|
+
|
73
|
+
@property
|
74
|
+
def data(self) -> ConfigDict:
|
75
|
+
"""
|
76
|
+
The parsed contents of the config file.
|
77
|
+
"""
|
78
|
+
d = self.__data
|
79
|
+
assert d is not None
|
80
|
+
return d
|
81
|
+
|
82
|
+
@property
|
83
|
+
def data_rt(self) -> ConfigDict:
|
84
|
+
"""
|
85
|
+
The parsed contents of the config file where the alternate parser was used.
|
86
|
+
"""
|
87
|
+
drt = self.__data_rt
|
88
|
+
assert drt is not None
|
89
|
+
return drt
|
90
|
+
|
91
|
+
@property
|
92
|
+
def path(self) -> Path:
|
93
|
+
"""
|
94
|
+
The path to the config file.
|
95
|
+
"""
|
96
|
+
p = self.__path
|
97
|
+
assert p is not None
|
98
|
+
return p
|
99
|
+
|
100
|
+
@property
|
101
|
+
def contents(self) -> str:
|
102
|
+
"""
|
103
|
+
The cached contents of the config file.
|
104
|
+
"""
|
105
|
+
c = self.__contents
|
106
|
+
assert c is not None
|
107
|
+
return c
|
70
108
|
|
71
109
|
@staticmethod
|
72
110
|
def select_invocation(
|
73
|
-
configs:
|
74
|
-
run_time_info:
|
75
|
-
path:
|
76
|
-
config_key:
|
111
|
+
configs: dict[str, Any],
|
112
|
+
run_time_info: dict[str, Any],
|
113
|
+
path: PathLike,
|
114
|
+
config_key: str | None = None,
|
77
115
|
) -> str:
|
78
116
|
"""Select a matching configuration for this invocation using run-time info."""
|
79
117
|
if not config_key:
|
@@ -82,7 +120,6 @@ class ConfigFile:
|
|
82
120
|
# for a config to "match", each "match key" must match the relevant run
|
83
121
|
# time info attribute. If a "match key" has multiple values, at least
|
84
122
|
# one value must match the run time info attribute:
|
85
|
-
is_match = True
|
86
123
|
for match_k, match_v in c_dat_i["invocation"]["match"].items():
|
87
124
|
# test for a matching glob pattern (where multiple may be specified):
|
88
125
|
if not isinstance(match_v, list):
|
@@ -93,39 +130,31 @@ class ConfigFile:
|
|
93
130
|
except KeyError:
|
94
131
|
raise ConfigFileInvocationUnknownMatchKey(match_k)
|
95
132
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
break
|
101
|
-
|
102
|
-
if not is_match_i:
|
103
|
-
is_match = False
|
133
|
+
if not any(
|
134
|
+
fnmatch.filter(names=[k_value], pat=match_i)
|
135
|
+
for match_i in match_v
|
136
|
+
):
|
104
137
|
break
|
105
|
-
|
106
|
-
if is_match:
|
138
|
+
else:
|
107
139
|
all_matches[c_name_i] = len(c_dat_i["invocation"]["match"])
|
108
140
|
|
109
|
-
if all_matches:
|
110
|
-
# for multiple matches select the more specific one:
|
111
|
-
all_sorted = sorted(all_matches.items(), key=lambda x: x[1], reverse=True)
|
112
|
-
config_key = all_sorted[0][0]
|
113
|
-
else:
|
141
|
+
if not all_matches:
|
114
142
|
raise ConfigFileInvocationIncompatibleError(config_key)
|
143
|
+
# for multiple matches select the more specific one:
|
144
|
+
config_key = max(all_matches.items(), key=lambda x: x[1])[0]
|
115
145
|
|
116
146
|
elif config_key not in configs:
|
117
|
-
raise ConfigInvocationKeyNotFoundError(config_key, path, list(configs
|
147
|
+
raise ConfigInvocationKeyNotFoundError(config_key, path, list(configs))
|
118
148
|
|
119
149
|
return config_key
|
120
150
|
|
121
|
-
def _validate(self, data):
|
151
|
+
def _validate(self, data: dict[str, Any] | None) -> Schema:
|
122
152
|
file_schema = get_schema("config_file_schema.yaml")
|
123
|
-
file_validated
|
124
|
-
if not file_validated.is_valid:
|
153
|
+
if not (file_validated := file_schema.validate(data)).is_valid:
|
125
154
|
raise ConfigFileValidationError(file_validated.get_failures_string())
|
126
155
|
return file_schema
|
127
156
|
|
128
|
-
def get_invoc_data(self, config_key):
|
157
|
+
def get_invoc_data(self, config_key: str) -> DefaultConfiguration:
|
129
158
|
"""
|
130
159
|
Get the invocation data for the given configuration.
|
131
160
|
|
@@ -136,7 +165,7 @@ class ConfigFile:
|
|
136
165
|
"""
|
137
166
|
return self.data["configs"][config_key]
|
138
167
|
|
139
|
-
def get_invocation(self, config_key):
|
168
|
+
def get_invocation(self, config_key: str) -> InvocationDescriptor:
|
140
169
|
"""
|
141
170
|
Get the invocation for the given configuration.
|
142
171
|
|
@@ -147,7 +176,7 @@ class ConfigFile:
|
|
147
176
|
"""
|
148
177
|
return self.get_invoc_data(config_key)["invocation"]
|
149
178
|
|
150
|
-
def save(self):
|
179
|
+
def save(self) -> None:
|
151
180
|
"""
|
152
181
|
Write the (modified) configuration to the configuration file.
|
153
182
|
"""
|
@@ -155,33 +184,38 @@ class ConfigFile:
|
|
155
184
|
new_data_rt = copy.deepcopy(self.data_rt)
|
156
185
|
new_contents = ""
|
157
186
|
|
158
|
-
modified_names = []
|
187
|
+
modified_names: list[str] = []
|
159
188
|
for config in self._configs:
|
160
|
-
modified_names
|
161
|
-
|
162
|
-
|
163
|
-
|
189
|
+
modified_names.extend(config._modified_keys)
|
190
|
+
modified_names.extend(config._unset_keys)
|
191
|
+
|
192
|
+
new_data_config = new_data["configs"][config._config_key]["config"]
|
193
|
+
new_data_rt_config = new_data_rt["configs"][config._config_key]["config"]
|
194
|
+
new_data_config.update(config._modified_keys)
|
195
|
+
new_data_rt_config.update(config._modified_keys)
|
164
196
|
|
165
197
|
for k in config._unset_keys:
|
166
|
-
del
|
167
|
-
del
|
198
|
+
del cast("dict", new_data_config)[k]
|
199
|
+
del cast("dict", new_data_rt_config)[k]
|
168
200
|
|
169
201
|
try:
|
170
202
|
new_contents = self._dump(new_data_rt)
|
171
203
|
except Exception as err:
|
172
204
|
raise ConfigChangeFileUpdateError(names=modified_names, err=err) from None
|
173
205
|
|
174
|
-
self.
|
175
|
-
self.
|
176
|
-
self.
|
206
|
+
self.__data = new_data
|
207
|
+
self.__data_rt = new_data_rt
|
208
|
+
self.__contents = new_contents
|
177
209
|
|
178
210
|
for config in self._configs:
|
179
|
-
config._unset_keys =
|
211
|
+
config._unset_keys = set()
|
180
212
|
config._modified_keys = {}
|
181
213
|
|
182
214
|
@staticmethod
|
183
215
|
def _resolve_config_dir(
|
184
|
-
config_opt
|
216
|
+
config_opt: ConfigOptions,
|
217
|
+
logger: logging.Logger,
|
218
|
+
directory: str | Path | None = None,
|
185
219
|
) -> Path:
|
186
220
|
"""Find the directory in which to locate the configuration file.
|
187
221
|
|
@@ -204,23 +238,23 @@ class ConfigFile:
|
|
204
238
|
"""
|
205
239
|
|
206
240
|
if not directory:
|
207
|
-
|
241
|
+
path = Path(
|
208
242
|
os.getenv(config_opt.directory_env_var, config_opt.default_directory)
|
209
243
|
).expanduser()
|
210
244
|
else:
|
211
|
-
|
245
|
+
path = Path(directory)
|
212
246
|
|
213
|
-
if not
|
247
|
+
if not path.is_dir():
|
214
248
|
logger.debug(
|
215
|
-
f"Configuration directory does not exist. Generating here: {str(
|
249
|
+
f"Configuration directory does not exist. Generating here: {str(path)!r}."
|
216
250
|
)
|
217
|
-
|
251
|
+
path.mkdir()
|
218
252
|
else:
|
219
|
-
logger.debug(f"Using configuration directory: {str(
|
253
|
+
logger.debug(f"Using configuration directory: {str(path)!r}.")
|
220
254
|
|
221
|
-
return
|
255
|
+
return path.resolve()
|
222
256
|
|
223
|
-
def _dump(self, config_data:
|
257
|
+
def _dump(self, config_data: ConfigDict, path: Path | None = None) -> str:
|
224
258
|
"""Dump the specified config data to the specified config file path.
|
225
259
|
|
226
260
|
Parameters
|
@@ -265,22 +299,23 @@ class ConfigFile:
|
|
265
299
|
|
266
300
|
return new_contents
|
267
301
|
|
268
|
-
def add_default_config(
|
302
|
+
def add_default_config(
|
303
|
+
self, config_options: ConfigOptions, name: str | None = None
|
304
|
+
) -> str:
|
269
305
|
"""Add a new default config to the config file, and create the file if it doesn't
|
270
306
|
exist."""
|
271
307
|
|
272
|
-
|
273
|
-
|
308
|
+
if self.path.exists():
|
309
|
+
is_new_file = False
|
310
|
+
new_data: ConfigDict = copy.deepcopy(self.data)
|
311
|
+
new_data_rt: ConfigDict = copy.deepcopy(self.data_rt)
|
312
|
+
else:
|
274
313
|
is_new_file = True
|
275
314
|
new_data = {"configs": {}}
|
276
315
|
new_data_rt = {"configs": {}}
|
277
|
-
else:
|
278
|
-
new_data = copy.deepcopy(self.data)
|
279
|
-
new_data_rt = copy.deepcopy(self.data_rt)
|
280
316
|
|
281
317
|
if not name:
|
282
|
-
|
283
|
-
name = "".join(random.choices(chars, k=6))
|
318
|
+
name = "".join(random.choices(string.ascii_letters, k=6))
|
284
319
|
|
285
320
|
def_config = copy.deepcopy(config_options.default_config)
|
286
321
|
new_config = {name: def_config}
|
@@ -303,14 +338,14 @@ class ConfigFile:
|
|
303
338
|
except (ConfigFileValidationError, ConfigValidationError) as err:
|
304
339
|
raise ConfigDefaultValidationError(err) from None
|
305
340
|
|
306
|
-
self.
|
307
|
-
self.
|
308
|
-
self.
|
341
|
+
self.__data_rt = new_data_rt
|
342
|
+
self.__data = new_data
|
343
|
+
self.__contents = self._dump(new_data_rt)
|
309
344
|
|
310
345
|
return name
|
311
346
|
|
312
347
|
@staticmethod
|
313
|
-
def get_config_file_path(directory):
|
348
|
+
def get_config_file_path(directory: Path) -> Path:
|
314
349
|
"""
|
315
350
|
Get the path to the configuration file.
|
316
351
|
"""
|
@@ -323,10 +358,10 @@ class ConfigFile:
|
|
323
358
|
return path_yml
|
324
359
|
return path_yaml
|
325
360
|
|
326
|
-
def _load_file_data(self, config_options):
|
361
|
+
def _load_file_data(self, config_options: ConfigOptions):
|
327
362
|
"""Load data from the configuration file (config.yaml or config.yml)."""
|
328
363
|
|
329
|
-
self.
|
364
|
+
self.__path = self.get_config_file_path(self.directory)
|
330
365
|
if not self.path.is_file():
|
331
366
|
self.logger.info(
|
332
367
|
"No config.yaml found in the configuration directory. Generating "
|
@@ -343,13 +378,13 @@ class ConfigFile:
|
|
343
378
|
handle.seek(0)
|
344
379
|
data_rt = yaml_rt.load(handle)
|
345
380
|
|
346
|
-
self.
|
347
|
-
self.
|
348
|
-
self.
|
381
|
+
self.__contents = contents
|
382
|
+
self.__data = data
|
383
|
+
self.__data_rt = data_rt
|
349
384
|
|
350
385
|
def get_config_item(
|
351
|
-
self, config_key, name, raise_on_missing=False, default_value=None
|
352
|
-
):
|
386
|
+
self, config_key: str, name: str, *, raise_on_missing=False, default_value=None
|
387
|
+
) -> Any | None:
|
353
388
|
"""
|
354
389
|
Get a configuration item.
|
355
390
|
|
@@ -365,11 +400,12 @@ class ConfigFile:
|
|
365
400
|
The default value to use when the config item is absent
|
366
401
|
(and ``raise_on_missing`` is not specified).
|
367
402
|
"""
|
368
|
-
|
403
|
+
cfg = self.get_invoc_data(config_key)["config"]
|
404
|
+
if raise_on_missing and name not in cfg:
|
369
405
|
raise ValueError(f"missing from file: {name!r}")
|
370
|
-
return
|
406
|
+
return cfg.get(name, default_value)
|
371
407
|
|
372
|
-
def is_item_set(self, config_key, name):
|
408
|
+
def is_item_set(self, config_key: str, name: str) -> bool:
|
373
409
|
"""
|
374
410
|
Determine if a configuration item is set.
|
375
411
|
|
@@ -382,11 +418,11 @@ class ConfigFile:
|
|
382
418
|
"""
|
383
419
|
try:
|
384
420
|
self.get_config_item(config_key, name, raise_on_missing=True)
|
421
|
+
return True
|
385
422
|
except ValueError:
|
386
423
|
return False
|
387
|
-
return True
|
388
424
|
|
389
|
-
def rename_config_key(self, config_key: str, new_config_key: str):
|
425
|
+
def rename_config_key(self, config_key: str, new_config_key: str) -> None:
|
390
426
|
"""
|
391
427
|
Change the config key of the loaded config.
|
392
428
|
|
@@ -409,22 +445,22 @@ class ConfigFile:
|
|
409
445
|
config._meta_data["config_key"] = new_config_key
|
410
446
|
config._config_key = new_config_key
|
411
447
|
|
412
|
-
self.
|
413
|
-
self.
|
414
|
-
self.
|
448
|
+
self.__data_rt = new_data_rt
|
449
|
+
self.__data = new_data
|
450
|
+
self.__contents = self._dump(new_data_rt)
|
415
451
|
|
416
452
|
def update_invocation(
|
417
453
|
self,
|
418
454
|
config_key: str,
|
419
|
-
environment_setup:
|
420
|
-
match:
|
421
|
-
):
|
455
|
+
environment_setup: str | None = None,
|
456
|
+
match: dict[str, str | list[str]] | None = None,
|
457
|
+
) -> None:
|
422
458
|
"""
|
423
459
|
Modify the invocation parameters of the loaded config.
|
424
460
|
|
425
461
|
Parameters
|
426
462
|
----------
|
427
|
-
config_key:
|
463
|
+
config_key:
|
428
464
|
The name of the configuration within the configuration file.
|
429
465
|
environment_setup:
|
430
466
|
The new value of the ``environment_setup`` key.
|
@@ -442,6 +478,6 @@ class ConfigFile:
|
|
442
478
|
if match:
|
443
479
|
invoc["match"].update(match)
|
444
480
|
|
445
|
-
self.
|
446
|
-
self.
|
447
|
-
self.
|
481
|
+
self.__data_rt = new_data_rt
|
482
|
+
self.__data = new_data
|
483
|
+
self.__contents = self._dump(new_data_rt)
|