hpcflow-new2 0.2.0a189__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.
Files changed (115) hide show
  1. hpcflow/__pyinstaller/hook-hpcflow.py +8 -6
  2. hpcflow/_version.py +1 -1
  3. hpcflow/app.py +1 -0
  4. hpcflow/data/scripts/main_script_test_hdf5_in_obj.py +1 -1
  5. hpcflow/data/scripts/main_script_test_hdf5_out_obj.py +1 -1
  6. hpcflow/sdk/__init__.py +21 -15
  7. hpcflow/sdk/app.py +2133 -770
  8. hpcflow/sdk/cli.py +281 -250
  9. hpcflow/sdk/cli_common.py +6 -2
  10. hpcflow/sdk/config/__init__.py +1 -1
  11. hpcflow/sdk/config/callbacks.py +77 -42
  12. hpcflow/sdk/config/cli.py +126 -103
  13. hpcflow/sdk/config/config.py +578 -311
  14. hpcflow/sdk/config/config_file.py +131 -95
  15. hpcflow/sdk/config/errors.py +112 -85
  16. hpcflow/sdk/config/types.py +145 -0
  17. hpcflow/sdk/core/actions.py +1054 -994
  18. hpcflow/sdk/core/app_aware.py +24 -0
  19. hpcflow/sdk/core/cache.py +81 -63
  20. hpcflow/sdk/core/command_files.py +275 -185
  21. hpcflow/sdk/core/commands.py +111 -107
  22. hpcflow/sdk/core/element.py +724 -503
  23. hpcflow/sdk/core/enums.py +192 -0
  24. hpcflow/sdk/core/environment.py +74 -93
  25. hpcflow/sdk/core/errors.py +398 -51
  26. hpcflow/sdk/core/json_like.py +540 -272
  27. hpcflow/sdk/core/loop.py +380 -334
  28. hpcflow/sdk/core/loop_cache.py +160 -43
  29. hpcflow/sdk/core/object_list.py +370 -207
  30. hpcflow/sdk/core/parameters.py +728 -600
  31. hpcflow/sdk/core/rule.py +59 -41
  32. hpcflow/sdk/core/run_dir_files.py +33 -22
  33. hpcflow/sdk/core/task.py +1546 -1325
  34. hpcflow/sdk/core/task_schema.py +240 -196
  35. hpcflow/sdk/core/test_utils.py +126 -88
  36. hpcflow/sdk/core/types.py +387 -0
  37. hpcflow/sdk/core/utils.py +410 -305
  38. hpcflow/sdk/core/validation.py +82 -9
  39. hpcflow/sdk/core/workflow.py +1192 -1028
  40. hpcflow/sdk/core/zarr_io.py +98 -137
  41. hpcflow/sdk/demo/cli.py +46 -33
  42. hpcflow/sdk/helper/cli.py +18 -16
  43. hpcflow/sdk/helper/helper.py +75 -63
  44. hpcflow/sdk/helper/watcher.py +61 -28
  45. hpcflow/sdk/log.py +83 -59
  46. hpcflow/sdk/persistence/__init__.py +8 -31
  47. hpcflow/sdk/persistence/base.py +988 -586
  48. hpcflow/sdk/persistence/defaults.py +6 -0
  49. hpcflow/sdk/persistence/discovery.py +38 -0
  50. hpcflow/sdk/persistence/json.py +408 -153
  51. hpcflow/sdk/persistence/pending.py +158 -123
  52. hpcflow/sdk/persistence/store_resource.py +37 -22
  53. hpcflow/sdk/persistence/types.py +307 -0
  54. hpcflow/sdk/persistence/utils.py +14 -11
  55. hpcflow/sdk/persistence/zarr.py +477 -420
  56. hpcflow/sdk/runtime.py +44 -41
  57. hpcflow/sdk/submission/{jobscript_info.py → enums.py} +39 -12
  58. hpcflow/sdk/submission/jobscript.py +444 -404
  59. hpcflow/sdk/submission/schedulers/__init__.py +133 -40
  60. hpcflow/sdk/submission/schedulers/direct.py +97 -71
  61. hpcflow/sdk/submission/schedulers/sge.py +132 -126
  62. hpcflow/sdk/submission/schedulers/slurm.py +263 -268
  63. hpcflow/sdk/submission/schedulers/utils.py +7 -2
  64. hpcflow/sdk/submission/shells/__init__.py +14 -15
  65. hpcflow/sdk/submission/shells/base.py +102 -29
  66. hpcflow/sdk/submission/shells/bash.py +72 -55
  67. hpcflow/sdk/submission/shells/os_version.py +31 -30
  68. hpcflow/sdk/submission/shells/powershell.py +37 -29
  69. hpcflow/sdk/submission/submission.py +203 -257
  70. hpcflow/sdk/submission/types.py +143 -0
  71. hpcflow/sdk/typing.py +163 -12
  72. hpcflow/tests/conftest.py +8 -6
  73. hpcflow/tests/schedulers/slurm/test_slurm_submission.py +5 -2
  74. hpcflow/tests/scripts/test_main_scripts.py +60 -30
  75. hpcflow/tests/shells/wsl/test_wsl_submission.py +6 -4
  76. hpcflow/tests/unit/test_action.py +86 -75
  77. hpcflow/tests/unit/test_action_rule.py +9 -4
  78. hpcflow/tests/unit/test_app.py +13 -6
  79. hpcflow/tests/unit/test_cli.py +1 -1
  80. hpcflow/tests/unit/test_command.py +71 -54
  81. hpcflow/tests/unit/test_config.py +20 -15
  82. hpcflow/tests/unit/test_config_file.py +21 -18
  83. hpcflow/tests/unit/test_element.py +58 -62
  84. hpcflow/tests/unit/test_element_iteration.py +3 -1
  85. hpcflow/tests/unit/test_element_set.py +29 -19
  86. hpcflow/tests/unit/test_group.py +4 -2
  87. hpcflow/tests/unit/test_input_source.py +116 -93
  88. hpcflow/tests/unit/test_input_value.py +29 -24
  89. hpcflow/tests/unit/test_json_like.py +44 -35
  90. hpcflow/tests/unit/test_loop.py +65 -58
  91. hpcflow/tests/unit/test_object_list.py +17 -12
  92. hpcflow/tests/unit/test_parameter.py +16 -7
  93. hpcflow/tests/unit/test_persistence.py +48 -35
  94. hpcflow/tests/unit/test_resources.py +20 -18
  95. hpcflow/tests/unit/test_run.py +8 -3
  96. hpcflow/tests/unit/test_runtime.py +2 -1
  97. hpcflow/tests/unit/test_schema_input.py +23 -15
  98. hpcflow/tests/unit/test_shell.py +3 -2
  99. hpcflow/tests/unit/test_slurm.py +8 -7
  100. hpcflow/tests/unit/test_submission.py +39 -19
  101. hpcflow/tests/unit/test_task.py +352 -247
  102. hpcflow/tests/unit/test_task_schema.py +33 -20
  103. hpcflow/tests/unit/test_utils.py +9 -11
  104. hpcflow/tests/unit/test_value_sequence.py +15 -12
  105. hpcflow/tests/unit/test_workflow.py +114 -83
  106. hpcflow/tests/unit/test_workflow_template.py +0 -1
  107. hpcflow/tests/workflows/test_jobscript.py +2 -1
  108. hpcflow/tests/workflows/test_workflows.py +18 -13
  109. {hpcflow_new2-0.2.0a189.dist-info → hpcflow_new2-0.2.0a190.dist-info}/METADATA +2 -1
  110. hpcflow_new2-0.2.0a190.dist-info/RECORD +165 -0
  111. hpcflow/sdk/core/parallel.py +0 -21
  112. hpcflow_new2-0.2.0a189.dist-info/RECORD +0 -158
  113. {hpcflow_new2-0.2.0a189.dist-info → hpcflow_new2-0.2.0a190.dist-info}/LICENSE +0 -0
  114. {hpcflow_new2-0.2.0a189.dist-info → hpcflow_new2-0.2.0a190.dist-info}/WHEEL +0 -0
  115. {hpcflow_new2-0.2.0a189.dist-info → hpcflow_new2-0.2.0a190.dist-info}/entry_points.txt +0 -0
@@ -1,13 +1,20 @@
1
1
  """
2
2
  Miscellaneous configuration-related errors.
3
3
  """
4
+ from __future__ import annotations
5
+ from typing import Any, TYPE_CHECKING
4
6
 
7
+ if TYPE_CHECKING:
8
+ from collections.abc import Sequence
9
+ from .types import ConfigMetadata
10
+ from ..typing import PathLike
5
11
 
6
- class ConfigError(Exception):
7
- """Raised when a valid configuration can not be associated with the current
8
- invocation."""
9
12
 
10
- pass
13
+ class ConfigError(Exception):
14
+ """
15
+ Raised when a valid configuration can not be associated with the current
16
+ invocation.
17
+ """
11
18
 
12
19
 
13
20
  class ConfigUnknownItemError(ConfigError):
@@ -15,12 +22,14 @@ class ConfigUnknownItemError(ConfigError):
15
22
  Raised when the configuration contains an unknown item.
16
23
  """
17
24
 
18
- def __init__(self, name, message=None):
19
- self.message = message or (
20
- f"Specified name {name!r} is not a valid meta-data or configurable "
21
- f"configuration item."
25
+ def __init__(self, name: str, message: str = ""):
26
+ super().__init__(
27
+ message
28
+ or (
29
+ f"Specified name {name!r} is not a valid meta-data or configurable "
30
+ f"configuration item."
31
+ )
22
32
  )
23
- super().__init__(self.message)
24
33
 
25
34
 
26
35
  class ConfigUnknownOverrideError(ConfigError):
@@ -28,11 +37,13 @@ class ConfigUnknownOverrideError(ConfigError):
28
37
  Raised when the configuration override contains an unknown item.
29
38
  """
30
39
 
31
- def __init__(self, name, message=None):
32
- self.message = message or (
33
- f"Specified configuration override {name!r} is not a valid configurable item."
40
+ def __init__(self, name: str, message: str = ""):
41
+ super().__init__(
42
+ message
43
+ or (
44
+ f"Specified configuration override {name!r} is not a valid configurable item."
45
+ )
34
46
  )
35
- super().__init__(self.message)
36
47
 
37
48
 
38
49
  class ConfigNonConfigurableError(ConfigError):
@@ -40,9 +51,10 @@ class ConfigNonConfigurableError(ConfigError):
40
51
  Raised when the configuration contains an item that can't be configured.
41
52
  """
42
53
 
43
- def __init__(self, name, message=None):
44
- self.message = message or (f"Specified name {name!r} is not a configurable item.")
45
- super().__init__(self.message)
54
+ def __init__(self, name: str, message: str = ""):
55
+ super().__init__(
56
+ message or f"Specified name {name!r} is not a configurable item."
57
+ )
46
58
 
47
59
 
48
60
  class ConfigItemAlreadyUnsetError(ConfigError):
@@ -50,9 +62,8 @@ class ConfigItemAlreadyUnsetError(ConfigError):
50
62
  Raised when the configuration tries to unset an unset item.
51
63
  """
52
64
 
53
- def __init__(self, name, message=None):
54
- self.message = message or f"Configuration item {name!r} is already not set."
55
- super().__init__(self.message)
65
+ def __init__(self, name: str, message: str = ""):
66
+ super().__init__(message or f"Configuration item {name!r} is already not set.")
56
67
 
57
68
 
58
69
  class ConfigFileValidationError(ConfigError):
@@ -60,7 +71,8 @@ class ConfigFileValidationError(ConfigError):
60
71
  Raised when the configuration file fails validation.
61
72
  """
62
73
 
63
- pass
74
+ def __init__(self, msg: str) -> None:
75
+ super().__init__(msg)
64
76
 
65
77
 
66
78
  class ConfigItemCallbackError(ConfigError):
@@ -68,23 +80,24 @@ class ConfigItemCallbackError(ConfigError):
68
80
  Raised when a configuration callback errors.
69
81
  """
70
82
 
71
- def __init__(self, name, callback, err, message=None):
72
- self.message = message or (
73
- f"Callback function {callback.__name__!r} for configuration item {name!r} "
74
- f"failed with exception: \n\n{str(err)}"
83
+ def __init__(self, name: str, callback: Any, err: Any, message: str = ""):
84
+ super().__init__(
85
+ message
86
+ or (
87
+ f"Callback function {callback.__name__!r} for configuration item {name!r} "
88
+ f"failed with exception: \n\n{str(err)}"
89
+ )
75
90
  )
76
- super().__init__(self.message)
77
91
 
78
92
 
79
93
  class ConfigFileInvocationIncompatibleError(ConfigError):
80
94
  """Raised when, given the run time information of the invocation, no compatible
81
95
  configuration can be found in the config file."""
82
96
 
83
- def __init__(self, message=None):
84
- self.message = message or (
85
- "No config could be found that matches the current invocation."
97
+ def __init__(self, message: str | None = ""):
98
+ super().__init__(
99
+ message or ("No config could be found that matches the current invocation.")
86
100
  )
87
- super().__init__(self.message)
88
101
 
89
102
 
90
103
  class ConfigFileInvocationUnknownMatchKey(ConfigError):
@@ -92,134 +105,148 @@ class ConfigFileInvocationUnknownMatchKey(ConfigError):
92
105
  Raised when the configuration contains an invalid match key.
93
106
  """
94
107
 
95
- def __init__(self, match_key, message=None):
96
- self.message = message or (
97
- f"Specified match key ({match_key!r}) is not a valid run time info "
98
- f"attribute."
99
- )
108
+ def __init__(self, match_key: str, message: str = ""):
100
109
  self.match_key = match_key
101
- super().__init__(self.message)
110
+ super().__init__(
111
+ message
112
+ or (
113
+ f"Specified match key ({match_key!r}) is not a valid run time info "
114
+ f"attribute."
115
+ )
116
+ )
102
117
 
103
118
 
104
119
  class ConfigInvocationKeyNotFoundError(ConfigError):
105
120
  """Raised when a configuration invocation key is passed but it is not a valid key."""
106
121
 
107
- def __init__(self, invoc_key, file_path, available_keys) -> None:
122
+ def __init__(
123
+ self, invoc_key: str, file_path: PathLike, available_keys: Sequence[str]
124
+ ):
108
125
  self.invoc_key = invoc_key
109
126
  self.file_path = file_path
110
127
  self.available_keys = available_keys
111
- self.message = (
128
+ super().__init__(
112
129
  f"Invocation key {self.invoc_key!r} does not exist in configuration file. "
113
130
  f"Available keys in configuration file {str(self.file_path)!r} are "
114
131
  f"{self.available_keys!r}."
115
132
  )
116
- super().__init__(self.message)
117
133
 
118
134
 
119
135
  class ConfigValidationError(ConfigError):
120
136
  """Raised when the matching config data is invalid."""
121
137
 
122
- def __init__(self, message, meta_data=None):
138
+ def __init__(self, message: str, meta_data: ConfigMetadata | None = None):
123
139
  self.meta_data = meta_data
124
- self.message = message + (f"config {self.meta_data}\n" if meta_data else "")
125
- super().__init__(self.message)
140
+ super().__init__(message + (f"config {self.meta_data}\n" if meta_data else ""))
126
141
 
127
142
 
128
143
  class ConfigDefaultValidationError(ConfigError):
129
144
  """Raised when the specified default configuration in the `ConfigOptions` object is
130
145
  invalid."""
131
146
 
132
- def __init__(self, validation_err, message=None):
133
- self.message = message or (
134
- f"The default configuration specified in the `ConfigOptions` object is "
135
- f"invalid.\n\n{validation_err}"
147
+ def __init__(self, validation_err: Any, message: str = ""):
148
+ super().__init__(
149
+ message
150
+ or (
151
+ f"The default configuration specified in the `ConfigOptions` object is "
152
+ f"invalid.\n\n{validation_err}"
153
+ )
136
154
  )
137
- super().__init__(self.message)
138
155
 
139
156
 
140
157
  class ConfigChangeInvalidError(ConfigError):
141
158
  """Raised when trying to set an invalid key in the Config."""
142
159
 
143
- def __init__(self, name, message=None):
144
- self.message = message or (
145
- f"Cannot modify value for invalid config item {name!r}. Use the `config list`"
146
- f" sub-command to list all configurable items."
160
+ def __init__(self, name: str, message: str = ""):
161
+ super().__init__(
162
+ message
163
+ or (
164
+ f"Cannot modify value for invalid config item {name!r}. Use the `config list`"
165
+ f" sub-command to list all configurable items."
166
+ )
147
167
  )
148
- super().__init__(self.message)
149
168
 
150
169
 
151
170
  class ConfigChangeInvalidJSONError(ConfigError):
152
171
  """Raised when attempting to set a config key using an invalid JSON string."""
153
172
 
154
- def __init__(self, name, json_str, err, message=None):
155
- self.message = message or (
156
- f"The config file has not been modified. Invalid JSON string for config item "
157
- f"{name!r}. {json_str!r}\n\n{err!r}"
173
+ def __init__(self, name: str, json_str: str, err: Any, message: str = ""):
174
+ super().__init__(
175
+ message
176
+ or (
177
+ f"The config file has not been modified. Invalid JSON string for config item "
178
+ f"{name!r}. {json_str!r}\n\n{err!r}"
179
+ )
158
180
  )
159
- super().__init__(self.message)
160
181
 
161
182
 
162
183
  class ConfigChangeValidationError(ConfigError):
163
184
  """Raised when a change to the configurable data would invalidate the config."""
164
185
 
165
- def __init__(self, name, validation_err, message=None):
166
- self.message = message or (
167
- f"The configuration has not been modified. Requested modification to item "
168
- f"{name!r} would invalidate the config in the following way."
169
- f"\n\n{validation_err}"
186
+ def __init__(self, name: str, validation_err: Any, message: str = ""):
187
+ super().__init__(
188
+ message
189
+ or (
190
+ f"The configuration has not been modified. Requested modification to item "
191
+ f"{name!r} would invalidate the config in the following way."
192
+ f"\n\n{validation_err}"
193
+ )
170
194
  )
171
- super().__init__(self.message)
172
195
 
173
196
 
174
197
  class ConfigChangeFileUpdateError(ConfigError):
175
198
  """Raised when the updating of the config YAML file fails."""
176
199
 
177
- def __init__(self, names, err, message=None):
178
- self.message = message or (
179
- f"Failed to update the config file for modification of config items {names!r}."
180
- f"\n\n{err!r}"
200
+ def __init__(self, names: Sequence[str], err, message: str = ""):
201
+ super().__init__(
202
+ message
203
+ or (
204
+ f"Failed to update the config file for modification of config items {names!r}."
205
+ f"\n\n{err!r}"
206
+ )
181
207
  )
182
- super().__init__(self.message)
183
208
 
184
209
 
185
210
  class ConfigChangeTypeInvalidError(ConfigError):
186
211
  """Raised when trying to modify a config item using a list operation, when the config
187
212
  item is not a list."""
188
213
 
189
- def __init__(self, name, typ, message=None):
190
- self.message = message or (
191
- f"The configuration has not been modified. The config item {name!r} has type "
192
- f"{typ!r} and so cannot be modified in that way."
214
+ def __init__(self, name: str, typ: type, message: str = ""):
215
+ super().__init__(
216
+ message
217
+ or (
218
+ f"The configuration has not been modified. The config item {name!r} has type "
219
+ f"{typ!r} and so cannot be modified in that way."
220
+ )
193
221
  )
194
- super().__init__(self.message)
195
222
 
196
223
 
197
224
  class ConfigChangePopIndexError(ConfigError):
198
225
  """Raised when trying to pop an item from a config item with an invalid index."""
199
226
 
200
- def __init__(self, name, length, index, message=None):
201
- self.message = message or (
202
- f"The configuration has not been modified. The config item {name!r} has length "
203
- f"{length!r} and so cannot be popped with index {index}."
227
+ def __init__(self, name: str, length: int, index: int, message: str = ""):
228
+ super().__init__(
229
+ message
230
+ or (
231
+ f"The configuration has not been modified. The config item {name!r} has length "
232
+ f"{length!r} and so cannot be popped with index {index}."
233
+ )
204
234
  )
205
- super().__init__(self.message)
206
235
 
207
236
 
208
237
  class MissingTaskSchemaFileError(ConfigError):
209
238
  """Raised when a task schema file specified in the config file does not exist."""
210
239
 
211
- def __init__(self, file_name, err, message=None):
212
- self.message = message or (
213
- f"The task schema file {file_name!r} cannot be found. \n{err!s}"
240
+ def __init__(self, file_name: str, err: Any, message: str = ""):
241
+ super().__init__(
242
+ message or (f"The task schema file {file_name!r} cannot be found. \n{err!s}")
214
243
  )
215
- super().__init__(self.message)
216
244
 
217
245
 
218
246
  class MissingEnvironmentFileError(ConfigError):
219
247
  """Raised when an environment file specified in the config file does not exist."""
220
248
 
221
- def __init__(self, file_name, err, message=None):
222
- self.message = message or (
223
- f"The environment file {file_name!r} cannot be found. \n{err!s}"
249
+ def __init__(self, file_name: str, err: Any, message: str = ""):
250
+ super().__init__(
251
+ message or (f"The environment file {file_name!r} cannot be found. \n{err!s}")
224
252
  )
225
- super().__init__(self.message)
@@ -0,0 +1,145 @@
1
+ """
2
+ Types used in configuration.
3
+ """
4
+ from __future__ import annotations
5
+ from typing import TYPE_CHECKING
6
+ from typing_extensions import TypeAlias, TypedDict, TypeVar
7
+
8
+ if TYPE_CHECKING:
9
+ from collections.abc import Callable, Sequence
10
+ from pathlib import Path
11
+ from typing import Any
12
+ from typing_extensions import NotRequired
13
+ from .config import Config
14
+ from ..core.validation import Schema
15
+
16
+
17
+ T = TypeVar("T")
18
+ #: Type of a getter callback.
19
+ GetterCallback: TypeAlias = "Callable[[Config, T], T]"
20
+ #: Type of a setter callback.
21
+ SetterCallback: TypeAlias = "Callable[[Config, T], Any]"
22
+
23
+
24
+ class SGEParallelEnvsDescriptor(TypedDict):
25
+ """
26
+ SGE parallel environment descriptor.
27
+ """
28
+
29
+ #: Number of supported cores.
30
+ num_cores: list[int]
31
+
32
+
33
+ class SLURMPartitionsDescriptor(TypedDict):
34
+ """
35
+ SLURM partition descriptor.
36
+ """
37
+
38
+ #: Number of supported cores.
39
+ num_cores: NotRequired[list[int]]
40
+ #: Number of cores per node.
41
+ num_cores_per_node: NotRequired[list[int]]
42
+ #: Number of supported nodes.
43
+ num_nodes: NotRequired[list[int]]
44
+ #: Possible parallel modes.
45
+ parallel_modes: NotRequired[list[str]]
46
+
47
+
48
+ class SchedulerConfigDescriptor(TypedDict):
49
+ """
50
+ Scheduler configuration descriptor.
51
+ """
52
+
53
+ #: Default values.
54
+ defaults: dict[str, Any]
55
+ #: SGE parallel environments, by name.
56
+ parallel_environments: NotRequired[dict[str, SGEParallelEnvsDescriptor]]
57
+ #: SLURM partitions, by name.
58
+ partitions: NotRequired[dict[str, SLURMPartitionsDescriptor]]
59
+
60
+
61
+ class ShellConfigDescriptor(TypedDict):
62
+ """
63
+ Shell configuration descriptor.
64
+ """
65
+
66
+ #: Default values.
67
+ defaults: dict[str, Any]
68
+
69
+
70
+ class ConfigDescriptor(TypedDict):
71
+ """
72
+ Configuration descriptor.
73
+ """
74
+
75
+ #: Execution machine.
76
+ machine: NotRequired[str]
77
+ #: Where to log.
78
+ log_file_path: NotRequired[str]
79
+ #: Where to find execution environments.
80
+ environment_sources: NotRequired[list[str]]
81
+ #: Where to find task schemas.
82
+ task_schema_sources: NotRequired[list[str]]
83
+ #: Where to find command files.
84
+ command_file_sources: NotRequired[list[str]]
85
+ #: Where to find parameter implementations.
86
+ parameter_sources: NotRequired[list[str]]
87
+ #: Default scheduler.
88
+ default_scheduler: NotRequired[str]
89
+ #: Default shell.
90
+ default_shell: NotRequired[str]
91
+ #: Supported schedulers.
92
+ schedulers: NotRequired[dict[str, SchedulerConfigDescriptor]]
93
+ #: Supported shells.
94
+ shells: NotRequired[dict[str, ShellConfigDescriptor]]
95
+
96
+
97
+ class InvocationDescriptor(TypedDict):
98
+ """
99
+ Invocation descriptor.
100
+ """
101
+
102
+ #: Used to set up the environment.
103
+ environment_setup: str | None
104
+ #: setting to apply if matched.
105
+ match: dict[str, str | list[str]]
106
+
107
+
108
+ class DefaultConfiguration(TypedDict):
109
+ """
110
+ The default configuration.
111
+ """
112
+
113
+ #: Default invocation.
114
+ invocation: InvocationDescriptor
115
+ #: Default configuration.
116
+ config: ConfigDescriptor
117
+
118
+
119
+ #: A configuration dictionary.
120
+ ConfigDict: TypeAlias = "dict[str, dict[str, DefaultConfiguration]]"
121
+
122
+
123
+ class ConfigMetadata(TypedDict):
124
+ """
125
+ Metadata supported by the :class:`Config` class.
126
+ """
127
+
128
+ #: Location of directory containing the config file.
129
+ config_directory: Path
130
+ #: Name of the config file.
131
+ config_file_name: str
132
+ #: Full path to the config file.
133
+ config_file_path: Path
134
+ #: The contents of the config file.
135
+ config_file_contents: str
136
+ #: The key identifying the config section within the config file.
137
+ config_key: str
138
+ #: Schemas that apply to the config.
139
+ config_schemas: Sequence[Schema]
140
+ #: The user that invoked things.
141
+ invoking_user_id: str
142
+ #: The user hosting things.
143
+ host_user_id: str
144
+ #: Path to file holding description of :attr:``host_user_id``.
145
+ host_user_id_file_path: Path