toml-combine 0.3.0__tar.gz → 0.5.0__tar.gz
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.
- {toml_combine-0.3.0 → toml_combine-0.5.0}/.pre-commit-config.yaml +2 -2
- {toml_combine-0.3.0 → toml_combine-0.5.0}/PKG-INFO +28 -11
- {toml_combine-0.3.0 → toml_combine-0.5.0}/README.md +27 -10
- {toml_combine-0.3.0 → toml_combine-0.5.0}/tests/test_combiner.py +123 -14
- {toml_combine-0.3.0 → toml_combine-0.5.0}/toml_combine/combiner.py +61 -21
- {toml_combine-0.3.0 → toml_combine-0.5.0}/toml_combine/exceptions.py +1 -1
- {toml_combine-0.3.0 → toml_combine-0.5.0}/toml_combine/lib.py +1 -2
- {toml_combine-0.3.0 → toml_combine-0.5.0}/toml_combine/toml.py +1 -1
- {toml_combine-0.3.0 → toml_combine-0.5.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {toml_combine-0.3.0 → toml_combine-0.5.0}/.github/renovate.json5 +0 -0
- {toml_combine-0.3.0 → toml_combine-0.5.0}/.github/workflows/ci.yml +0 -0
- {toml_combine-0.3.0 → toml_combine-0.5.0}/pyproject.toml +0 -0
- {toml_combine-0.3.0 → toml_combine-0.5.0}/tests/result.json +0 -0
- {toml_combine-0.3.0 → toml_combine-0.5.0}/tests/test.toml +0 -0
- {toml_combine-0.3.0 → toml_combine-0.5.0}/tests/test_cli.py +0 -0
- {toml_combine-0.3.0 → toml_combine-0.5.0}/tests/test_lib.py +0 -0
- {toml_combine-0.3.0 → toml_combine-0.5.0}/toml_combine/__init__.py +0 -0
- {toml_combine-0.3.0 → toml_combine-0.5.0}/toml_combine/__main__.py +0 -0
- {toml_combine-0.3.0 → toml_combine-0.5.0}/toml_combine/cli.py +0 -0
- {toml_combine-0.3.0 → toml_combine-0.5.0}/uv.lock +0 -0
@@ -22,11 +22,11 @@ repos:
|
|
22
22
|
- id: mixed-line-ending
|
23
23
|
- repo: https://github.com/astral-sh/uv-pre-commit
|
24
24
|
# uv version.
|
25
|
-
rev: 0.6.
|
25
|
+
rev: 0.6.14
|
26
26
|
hooks:
|
27
27
|
- id: uv-lock
|
28
28
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
29
|
-
rev: v0.11.
|
29
|
+
rev: v0.11.5
|
30
30
|
hooks:
|
31
31
|
- id: ruff
|
32
32
|
args: [--fix, --unsafe-fixes, --show-fixes]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: toml-combine
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.5.0
|
4
4
|
Summary: A tool for combining complex configurations in TOML format.
|
5
5
|
Author-email: Joachim Jablon <ewjoachim@gmail.com>
|
6
6
|
License-Expression: MIT
|
@@ -29,7 +29,7 @@ parts that are common to everyone.
|
|
29
29
|
|
30
30
|
### The config file
|
31
31
|
|
32
|
-
The configuration file is usually a TOML file. Here's a small example:
|
32
|
+
The configuration file is (usually) a TOML file. Here's a small example:
|
33
33
|
|
34
34
|
```toml
|
35
35
|
[dimensions]
|
@@ -65,11 +65,14 @@ Overrides define a set of condition where they apply (`when.<dimension> =
|
|
65
65
|
"<value>"`) and the values that are overriden. Overrides are applied in order from less
|
66
66
|
specific to more specific, each one overriding the values of the previous ones:
|
67
67
|
|
68
|
-
-
|
69
|
-
|
70
|
-
- In case 2 overrides
|
71
|
-
|
72
|
-
|
68
|
+
- In case 2 overrides are applicable, the more specific one (the one with more
|
69
|
+
dimensions defined) has greater priority
|
70
|
+
- In case 2 overrides use the same number of dimensions, then it depends on how the
|
71
|
+
dimensions are defined at the top of the file: dimensions defined last have a greater
|
72
|
+
priority
|
73
|
+
- In case 2 overrides use the same dimensions, if they define the same configuration
|
74
|
+
values, an error will be raised. If they define different configuation values, then
|
75
|
+
the priority is irrelevant.
|
73
76
|
|
74
77
|
> [!Note]
|
75
78
|
> Defining a list as the value of one or more conditions in an override
|
@@ -141,9 +144,9 @@ Example with the config from the previous section:
|
|
141
144
|
|
142
145
|
```console
|
143
146
|
$ toml-combine path/to/config.toml --environment=staging
|
144
|
-
|
145
|
-
environment = "staging"
|
147
|
+
```
|
146
148
|
|
149
|
+
```toml
|
147
150
|
[fruits]
|
148
151
|
apple.color = "red"
|
149
152
|
orange.color = "orange"
|
@@ -201,7 +204,10 @@ container.env.ENABLE_EXPENSIVE_MONITORING = false
|
|
201
204
|
This produces the following configs:
|
202
205
|
|
203
206
|
```console
|
204
|
-
$
|
207
|
+
$ toml-combine example.toml --environment=production --service=frontend
|
208
|
+
```
|
209
|
+
|
210
|
+
```toml
|
205
211
|
registry = "gcr.io/my-project/"
|
206
212
|
service_account = "my-service-account"
|
207
213
|
name = "service-frontend"
|
@@ -212,6 +218,9 @@ image_name = "my-image-frontend"
|
|
212
218
|
|
213
219
|
```console
|
214
220
|
$ toml-combine example.toml --environment=production --service=backend
|
221
|
+
```
|
222
|
+
|
223
|
+
```toml
|
215
224
|
registry = "gcr.io/my-project/"
|
216
225
|
service_account = "my-service-account"
|
217
226
|
name = "service-backend"
|
@@ -223,6 +232,9 @@ port = 8080
|
|
223
232
|
|
224
233
|
```console
|
225
234
|
$ toml-combine example.toml --environment=staging --service=frontend
|
235
|
+
```
|
236
|
+
|
237
|
+
```toml
|
226
238
|
registry = "gcr.io/my-project/"
|
227
239
|
service_account = "my-service-account"
|
228
240
|
name = "service-frontend"
|
@@ -233,6 +245,9 @@ image_name = "my-image-frontend"
|
|
233
245
|
|
234
246
|
```console
|
235
247
|
$ toml-combine example.toml --environment=staging --service=backend
|
248
|
+
```
|
249
|
+
|
250
|
+
```toml
|
236
251
|
registry = "gcr.io/my-project/"
|
237
252
|
service_account = "my-service-account"
|
238
253
|
name = "service-backend"
|
@@ -247,6 +262,9 @@ ENABLE_EXPENSIVE_MONITORING = false
|
|
247
262
|
|
248
263
|
```console
|
249
264
|
$ toml-combine example.toml --environment=dev --service=backend
|
265
|
+
```
|
266
|
+
|
267
|
+
```toml
|
250
268
|
registry = "gcr.io/my-project/"
|
251
269
|
service_account = "my-service-account"
|
252
270
|
name = "service-backend"
|
@@ -257,5 +275,4 @@ port = 8080
|
|
257
275
|
[container.env]
|
258
276
|
DEBUG = true
|
259
277
|
ENABLE_EXPENSIVE_MONITORING = false
|
260
|
-
|
261
278
|
```
|
@@ -10,7 +10,7 @@ parts that are common to everyone.
|
|
10
10
|
|
11
11
|
### The config file
|
12
12
|
|
13
|
-
The configuration file is usually a TOML file. Here's a small example:
|
13
|
+
The configuration file is (usually) a TOML file. Here's a small example:
|
14
14
|
|
15
15
|
```toml
|
16
16
|
[dimensions]
|
@@ -46,11 +46,14 @@ Overrides define a set of condition where they apply (`when.<dimension> =
|
|
46
46
|
"<value>"`) and the values that are overriden. Overrides are applied in order from less
|
47
47
|
specific to more specific, each one overriding the values of the previous ones:
|
48
48
|
|
49
|
-
-
|
50
|
-
|
51
|
-
- In case 2 overrides
|
52
|
-
|
53
|
-
|
49
|
+
- In case 2 overrides are applicable, the more specific one (the one with more
|
50
|
+
dimensions defined) has greater priority
|
51
|
+
- In case 2 overrides use the same number of dimensions, then it depends on how the
|
52
|
+
dimensions are defined at the top of the file: dimensions defined last have a greater
|
53
|
+
priority
|
54
|
+
- In case 2 overrides use the same dimensions, if they define the same configuration
|
55
|
+
values, an error will be raised. If they define different configuation values, then
|
56
|
+
the priority is irrelevant.
|
54
57
|
|
55
58
|
> [!Note]
|
56
59
|
> Defining a list as the value of one or more conditions in an override
|
@@ -122,9 +125,9 @@ Example with the config from the previous section:
|
|
122
125
|
|
123
126
|
```console
|
124
127
|
$ toml-combine path/to/config.toml --environment=staging
|
125
|
-
|
126
|
-
environment = "staging"
|
128
|
+
```
|
127
129
|
|
130
|
+
```toml
|
128
131
|
[fruits]
|
129
132
|
apple.color = "red"
|
130
133
|
orange.color = "orange"
|
@@ -182,7 +185,10 @@ container.env.ENABLE_EXPENSIVE_MONITORING = false
|
|
182
185
|
This produces the following configs:
|
183
186
|
|
184
187
|
```console
|
185
|
-
$
|
188
|
+
$ toml-combine example.toml --environment=production --service=frontend
|
189
|
+
```
|
190
|
+
|
191
|
+
```toml
|
186
192
|
registry = "gcr.io/my-project/"
|
187
193
|
service_account = "my-service-account"
|
188
194
|
name = "service-frontend"
|
@@ -193,6 +199,9 @@ image_name = "my-image-frontend"
|
|
193
199
|
|
194
200
|
```console
|
195
201
|
$ toml-combine example.toml --environment=production --service=backend
|
202
|
+
```
|
203
|
+
|
204
|
+
```toml
|
196
205
|
registry = "gcr.io/my-project/"
|
197
206
|
service_account = "my-service-account"
|
198
207
|
name = "service-backend"
|
@@ -204,6 +213,9 @@ port = 8080
|
|
204
213
|
|
205
214
|
```console
|
206
215
|
$ toml-combine example.toml --environment=staging --service=frontend
|
216
|
+
```
|
217
|
+
|
218
|
+
```toml
|
207
219
|
registry = "gcr.io/my-project/"
|
208
220
|
service_account = "my-service-account"
|
209
221
|
name = "service-frontend"
|
@@ -214,6 +226,9 @@ image_name = "my-image-frontend"
|
|
214
226
|
|
215
227
|
```console
|
216
228
|
$ toml-combine example.toml --environment=staging --service=backend
|
229
|
+
```
|
230
|
+
|
231
|
+
```toml
|
217
232
|
registry = "gcr.io/my-project/"
|
218
233
|
service_account = "my-service-account"
|
219
234
|
name = "service-backend"
|
@@ -228,6 +243,9 @@ ENABLE_EXPENSIVE_MONITORING = false
|
|
228
243
|
|
229
244
|
```console
|
230
245
|
$ toml-combine example.toml --environment=dev --service=backend
|
246
|
+
```
|
247
|
+
|
248
|
+
```toml
|
231
249
|
registry = "gcr.io/my-project/"
|
232
250
|
service_account = "my-service-account"
|
233
251
|
name = "service-backend"
|
@@ -238,5 +256,4 @@ port = 8080
|
|
238
256
|
[container.env]
|
239
257
|
DEBUG = true
|
240
258
|
ENABLE_EXPENSIVE_MONITORING = false
|
241
|
-
|
242
259
|
```
|
@@ -103,7 +103,7 @@ def test_merge_configs__dicts_error():
|
|
103
103
|
),
|
104
104
|
],
|
105
105
|
)
|
106
|
-
def
|
106
|
+
def __full_chain(mapping: dict, expected: dict[str, int]):
|
107
107
|
default = {
|
108
108
|
"a": 1,
|
109
109
|
"b": 2,
|
@@ -138,8 +138,11 @@ def test_generate_for_mapping(mapping: dict, expected: dict[str, int]):
|
|
138
138
|
]
|
139
139
|
|
140
140
|
result = combiner.generate_for_mapping(
|
141
|
-
|
142
|
-
|
141
|
+
config=combiner.Config(
|
142
|
+
dimensions={"env": ["prod", "staging"], "region": ["us"]},
|
143
|
+
default=default,
|
144
|
+
overrides=overrides,
|
145
|
+
),
|
143
146
|
mapping=mapping,
|
144
147
|
)
|
145
148
|
assert result == expected
|
@@ -224,10 +227,7 @@ def test_build_config():
|
|
224
227
|
def test_build_config__duplicate_overrides():
|
225
228
|
raw_config = """
|
226
229
|
[dimensions]
|
227
|
-
env = ["
|
228
|
-
|
229
|
-
[templates]
|
230
|
-
foo = "bar"
|
230
|
+
env = ["prod"]
|
231
231
|
|
232
232
|
[[override]]
|
233
233
|
when.env = "prod"
|
@@ -243,6 +243,52 @@ def test_build_config__duplicate_overrides():
|
|
243
243
|
combiner.build_config(config)
|
244
244
|
|
245
245
|
|
246
|
+
def test_build_config__duplicate_overrides_different_vars():
|
247
|
+
raw_config = """
|
248
|
+
[dimensions]
|
249
|
+
env = ["prod"]
|
250
|
+
|
251
|
+
[[override]]
|
252
|
+
when.env = "prod"
|
253
|
+
foo = "baz"
|
254
|
+
|
255
|
+
[[override]]
|
256
|
+
when.env = "prod"
|
257
|
+
baz = "qux"
|
258
|
+
"""
|
259
|
+
|
260
|
+
config = toml.loads(raw_config)
|
261
|
+
assert len(combiner.build_config(config).overrides) == 2
|
262
|
+
|
263
|
+
|
264
|
+
def test_build_config__duplicate_overrides_list():
|
265
|
+
raw_config = """
|
266
|
+
[dimensions]
|
267
|
+
env = ["prod", "dev"]
|
268
|
+
|
269
|
+
[[override]]
|
270
|
+
when.env = ["prod"]
|
271
|
+
foo = "baz"
|
272
|
+
hello = 1
|
273
|
+
|
274
|
+
[[override]]
|
275
|
+
when.env = ["prod", "dev"]
|
276
|
+
foo = "qux"
|
277
|
+
hello = 1
|
278
|
+
"""
|
279
|
+
|
280
|
+
config = toml.loads(raw_config)
|
281
|
+
with pytest.raises(exceptions.DuplicateError) as excinfo:
|
282
|
+
combiner.build_config(config)
|
283
|
+
|
284
|
+
# Message is a bit complex so we test it too.
|
285
|
+
assert (
|
286
|
+
str(excinfo.value) == "In override {'env': ['prod', 'dev']}: "
|
287
|
+
"Overrides with the same dimensions cannot define the same configuration keys: "
|
288
|
+
"foo, hello"
|
289
|
+
)
|
290
|
+
|
291
|
+
|
246
292
|
def test_build_config__dimension_not_found_in_override():
|
247
293
|
raw_config = """
|
248
294
|
[dimensions]
|
@@ -271,16 +317,79 @@ def test_build_config__dimension_value_not_found_in_override():
|
|
271
317
|
combiner.build_config(config)
|
272
318
|
|
273
319
|
|
274
|
-
@pytest.
|
275
|
-
|
276
|
-
|
320
|
+
@pytest.mark.parametrize(
|
321
|
+
"mapping, expected",
|
322
|
+
[
|
323
|
+
(
|
324
|
+
{"env": "prod"},
|
325
|
+
{"foo": "bar"},
|
326
|
+
),
|
327
|
+
(
|
328
|
+
{"env": "dev"},
|
329
|
+
{"foo": "baz"},
|
330
|
+
),
|
331
|
+
],
|
332
|
+
)
|
333
|
+
def test_generate_for_mapping__full_chain(mapping, expected):
|
334
|
+
config = combiner.build_config(
|
277
335
|
toml.loads(
|
278
336
|
"""
|
279
|
-
|
280
|
-
|
337
|
+
[dimensions]
|
338
|
+
env = ["prod", "dev"]
|
339
|
+
|
340
|
+
[default]
|
341
|
+
foo = "bar"
|
281
342
|
|
282
|
-
|
283
|
-
|
343
|
+
[[override]]
|
344
|
+
when.env = "dev"
|
345
|
+
foo = "baz"
|
346
|
+
""",
|
347
|
+
)
|
348
|
+
)
|
349
|
+
result = combiner.generate_for_mapping(
|
350
|
+
config=config,
|
351
|
+
mapping=mapping,
|
352
|
+
)
|
353
|
+
assert result == expected
|
354
|
+
|
355
|
+
|
356
|
+
def test_extract_keys():
|
357
|
+
config = toml.loads(
|
358
|
+
"""
|
359
|
+
a = 1
|
360
|
+
b.c = 1
|
361
|
+
b.d = 1
|
362
|
+
e.f.g = 1
|
284
363
|
""",
|
364
|
+
)
|
365
|
+
|
366
|
+
result = list(combiner.extract_keys(config))
|
367
|
+
assert result == [
|
368
|
+
("a",),
|
369
|
+
("b", "c"),
|
370
|
+
("b", "d"),
|
371
|
+
("e", "f", "g"),
|
372
|
+
]
|
373
|
+
|
374
|
+
|
375
|
+
def test_extract_definitions():
|
376
|
+
result = list(
|
377
|
+
combiner.extract_conditions_and_keys(
|
378
|
+
when={"env": ["dev", "staging"], "region": ["eu", "us"]},
|
379
|
+
config={
|
380
|
+
"a": 1,
|
381
|
+
"b.c.d": 4,
|
382
|
+
},
|
285
383
|
)
|
286
384
|
)
|
385
|
+
print(result)
|
386
|
+
assert result == [
|
387
|
+
((("env", "dev"), ("region", "eu")), "a"),
|
388
|
+
((("env", "dev"), ("region", "us")), "a"),
|
389
|
+
((("env", "staging"), ("region", "eu")), "a"),
|
390
|
+
((("env", "staging"), ("region", "us")), "a"),
|
391
|
+
((("env", "dev"), ("region", "eu")), "b.c.d"),
|
392
|
+
((("env", "dev"), ("region", "us")), "b.c.d"),
|
393
|
+
((("env", "staging"), ("region", "eu")), "b.c.d"),
|
394
|
+
((("env", "staging"), ("region", "us")), "b.c.d"),
|
395
|
+
]
|
@@ -2,7 +2,8 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import copy
|
4
4
|
import dataclasses
|
5
|
-
|
5
|
+
import itertools
|
6
|
+
from collections.abc import Iterable, Mapping, Sequence
|
6
7
|
from functools import partial
|
7
8
|
from typing import Any, TypeVar
|
8
9
|
|
@@ -80,6 +81,18 @@ def override_sort_key(
|
|
80
81
|
{"env": "dev", "region": "us"} (less specific)
|
81
82
|
- Override with {"env": "dev"} comes before override with {"region": "us"} ("env"
|
82
83
|
is defined before "region" in the dimensions list)
|
84
|
+
|
85
|
+
Parameters:
|
86
|
+
-----------
|
87
|
+
override: An Override object that defines the condition when it applies
|
88
|
+
(override.when)
|
89
|
+
dimensions: The dict of all existing dimensions and their values, in order of
|
90
|
+
definition
|
91
|
+
|
92
|
+
Returns:
|
93
|
+
--------
|
94
|
+
A tuple that supports comparisons. Less specific Overrides should return smaller
|
95
|
+
values and vice versa.
|
83
96
|
"""
|
84
97
|
result = [len(override.when)]
|
85
98
|
for i, dimension in enumerate(dimensions):
|
@@ -111,6 +124,35 @@ def merge_configs(a: T, b: T, /) -> T:
|
|
111
124
|
return result
|
112
125
|
|
113
126
|
|
127
|
+
def extract_keys(config: Any) -> Iterable[tuple[str, ...]]:
|
128
|
+
"""
|
129
|
+
Extract the keys from a config.
|
130
|
+
"""
|
131
|
+
if isinstance(config, dict):
|
132
|
+
for key, value in config.items():
|
133
|
+
for sub_key in extract_keys(value):
|
134
|
+
yield (key, *sub_key)
|
135
|
+
else:
|
136
|
+
yield tuple()
|
137
|
+
|
138
|
+
|
139
|
+
def extract_conditions_and_keys(
|
140
|
+
when: dict[str, list[str]], config: dict[str, Any]
|
141
|
+
) -> Iterable[tuple[Any, ...]]:
|
142
|
+
"""
|
143
|
+
Extract the definitions from an override.
|
144
|
+
"""
|
145
|
+
when_definitions = []
|
146
|
+
for key, values in when.items():
|
147
|
+
when_definitions.append([(key, value) for value in values])
|
148
|
+
|
149
|
+
when_combined_definitions = list(itertools.product(*when_definitions))
|
150
|
+
config_keys = extract_keys(config)
|
151
|
+
for config_key in config_keys:
|
152
|
+
for when_definition in when_combined_definitions:
|
153
|
+
yield (when_definition, *config_key)
|
154
|
+
|
155
|
+
|
114
156
|
def build_config(config: dict[str, Any]) -> Config:
|
115
157
|
config = copy.deepcopy(config)
|
116
158
|
# Parse dimensions
|
@@ -119,7 +161,9 @@ def build_config(config: dict[str, Any]) -> Config:
|
|
119
161
|
# Parse template
|
120
162
|
default = config.pop("default", {})
|
121
163
|
|
122
|
-
|
164
|
+
# The rule is: the same exact set of conditions cannot be used twice to define
|
165
|
+
# the same values (on the same or different overrides)
|
166
|
+
seen_conditions_and_keys = set()
|
123
167
|
overrides = []
|
124
168
|
for override in config.pop("override", []):
|
125
169
|
try:
|
@@ -132,20 +176,17 @@ def build_config(config: dict[str, Any]) -> Config:
|
|
132
176
|
type="override",
|
133
177
|
)
|
134
178
|
|
135
|
-
|
136
|
-
|
137
|
-
|
179
|
+
conditions_and_keys = set(
|
180
|
+
extract_conditions_and_keys(when=when, config=override)
|
181
|
+
)
|
182
|
+
if duplicates := (conditions_and_keys & seen_conditions_and_keys):
|
183
|
+
duplicate_str = ", ".join(sorted(key for *_, key in duplicates))
|
184
|
+
raise exceptions.DuplicateError(id=when, details=duplicate_str)
|
138
185
|
|
139
|
-
|
186
|
+
seen_conditions_and_keys |= conditions_and_keys
|
187
|
+
|
188
|
+
overrides.append(Override(when=when, config=override))
|
140
189
|
|
141
|
-
overrides.append(
|
142
|
-
Override(
|
143
|
-
when=clean_dimensions_dict(
|
144
|
-
to_sort=when, clean=dimensions, type="override"
|
145
|
-
),
|
146
|
-
config=override,
|
147
|
-
)
|
148
|
-
)
|
149
190
|
# Sort overrides by increasing specificity
|
150
191
|
overrides = sorted(
|
151
192
|
overrides,
|
@@ -159,7 +200,7 @@ def build_config(config: dict[str, Any]) -> Config:
|
|
159
200
|
)
|
160
201
|
|
161
202
|
|
162
|
-
def mapping_matches_override(mapping:
|
203
|
+
def mapping_matches_override(mapping: Mapping[str, str], override: Override) -> bool:
|
163
204
|
"""
|
164
205
|
Check if the values in the override match the given dimensions.
|
165
206
|
"""
|
@@ -174,13 +215,12 @@ def mapping_matches_override(mapping: dict[str, str], override: Override) -> boo
|
|
174
215
|
|
175
216
|
|
176
217
|
def generate_for_mapping(
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
result = copy.deepcopy(default)
|
218
|
+
config: Config,
|
219
|
+
mapping: Mapping[str, str],
|
220
|
+
) -> Mapping[str, Any]:
|
221
|
+
result = copy.deepcopy(config.default)
|
182
222
|
# Apply each matching override
|
183
|
-
for override in overrides:
|
223
|
+
for override in config.overrides:
|
184
224
|
# Check if all dimension values in the override match
|
185
225
|
|
186
226
|
if mapping_matches_override(mapping=mapping, override=override):
|
@@ -20,7 +20,7 @@ class TomlEncodeError(TomlCombineError):
|
|
20
20
|
|
21
21
|
|
22
22
|
class DuplicateError(TomlCombineError):
|
23
|
-
"""In
|
23
|
+
"""In override {id}: Overrides with the same dimensions cannot define the same configuration keys: {details}"""
|
24
24
|
|
25
25
|
|
26
26
|
class DimensionNotFound(TomlCombineError):
|
@@ -52,7 +52,6 @@ def combine(*, config=None, config_file=None, **mapping):
|
|
52
52
|
config_obj = combiner.build_config(dict_config)
|
53
53
|
|
54
54
|
return combiner.generate_for_mapping(
|
55
|
-
|
56
|
-
overrides=config_obj.overrides,
|
55
|
+
config=config_obj,
|
57
56
|
mapping=mapping,
|
58
57
|
)
|
@@ -22,6 +22,6 @@ def dumps(config: dict) -> str:
|
|
22
22
|
# features. The easiest way to turn tomlkit objects into plain dicts and strings
|
23
23
|
# is through a json round-trip.
|
24
24
|
try:
|
25
|
-
return tomlkit.dumps(json.loads(json.dumps(config)))
|
25
|
+
return tomlkit.dumps(json.loads(json.dumps(config)), sort_keys=False)
|
26
26
|
except tomlkit.exceptions.TOMLKitError as e:
|
27
27
|
raise exceptions.TomlEncodeError from e
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|