toml-combine 1.0.1__py3-none-any.whl → 1.0.3__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.
- toml_combine/cli.py +2 -2
- toml_combine/combiner.py +13 -1
- toml_combine/exceptions.py +1 -1
- {toml_combine-1.0.1.dist-info → toml_combine-1.0.3.dist-info}/METADATA +112 -23
- toml_combine-1.0.3.dist-info/RECORD +12 -0
- toml_combine-1.0.1.dist-info/RECORD +0 -12
- {toml_combine-1.0.1.dist-info → toml_combine-1.0.3.dist-info}/WHEEL +0 -0
- {toml_combine-1.0.1.dist-info → toml_combine-1.0.3.dist-info}/entry_points.txt +0 -0
- {toml_combine-1.0.1.dist-info → toml_combine-1.0.3.dist-info}/licenses/LICENSE +0 -0
toml_combine/cli.py
CHANGED
@@ -70,7 +70,7 @@ def cli(argv) -> int:
|
|
70
70
|
try:
|
71
71
|
config = combiner.build_config(dict_config)
|
72
72
|
except exceptions.TomlCombineError as exc:
|
73
|
-
print(exc, file=sys.stderr)
|
73
|
+
print(f"Error: {exc}", file=sys.stderr)
|
74
74
|
return 1
|
75
75
|
|
76
76
|
# Parse all arguments
|
@@ -86,7 +86,7 @@ def cli(argv) -> int:
|
|
86
86
|
try:
|
87
87
|
result = lib.combine(config=dict_config, **mapping)
|
88
88
|
except exceptions.TomlCombineError as exc:
|
89
|
-
print(exc, file=sys.stderr)
|
89
|
+
print(f"Error: {exc}", file=sys.stderr)
|
90
90
|
return 1
|
91
91
|
|
92
92
|
if args.format == "toml":
|
toml_combine/combiner.py
CHANGED
@@ -21,6 +21,7 @@ class Override:
|
|
21
21
|
class Config:
|
22
22
|
dimensions: Mapping[str, list[str]]
|
23
23
|
default: Mapping[str, Any]
|
24
|
+
# List of overrides, in order of increasing specificity
|
24
25
|
overrides: Sequence[Override]
|
25
26
|
|
26
27
|
|
@@ -30,6 +31,7 @@ def clean_dimensions_dict(
|
|
30
31
|
"""
|
31
32
|
Recreate a dictionary of dimension values with the same order as the
|
32
33
|
dimensions list.
|
34
|
+
Also check that the values are valid.
|
33
35
|
"""
|
34
36
|
result = {}
|
35
37
|
if invalid_dimensions := set(to_sort) - set(clean):
|
@@ -63,7 +65,7 @@ T = TypeVar("T", dict, list, str, int, float, bool)
|
|
63
65
|
|
64
66
|
def merge_configs(a: T, b: T, /) -> T:
|
65
67
|
"""
|
66
|
-
Recursively merge two configuration dictionaries, with b taking precedence.
|
68
|
+
Recursively merge two configuration dictionaries a and b, with b taking precedence.
|
67
69
|
"""
|
68
70
|
if isinstance(a, dict) != isinstance(b, dict):
|
69
71
|
raise ValueError(f"Cannot merge {type(a)} with {type(b)}")
|
@@ -116,6 +118,9 @@ def are_conditions_compatible(
|
|
116
118
|
|
117
119
|
|
118
120
|
def build_config(config: dict[str, Any]) -> Config:
|
121
|
+
"""
|
122
|
+
Build a finalized Config object from the given configuration dictionary.
|
123
|
+
"""
|
119
124
|
config = copy.deepcopy(config)
|
120
125
|
# Parse dimensions
|
121
126
|
dimensions = config.pop("dimensions")
|
@@ -165,6 +170,13 @@ def generate_for_mapping(
|
|
165
170
|
config: Config,
|
166
171
|
mapping: Mapping[str, str],
|
167
172
|
) -> Mapping[str, Any]:
|
173
|
+
"""
|
174
|
+
Generate a configuration based on the provided mapping of dimension values.
|
175
|
+
The mapping should contain only the dimensions defined in the config.
|
176
|
+
If a dimension is not defined in the mapping, the default value for that
|
177
|
+
dimension will be used.
|
178
|
+
"""
|
179
|
+
|
168
180
|
result = copy.deepcopy(config.default)
|
169
181
|
keys_to_conditions: dict[tuple[str, ...], list[Mapping[str, list[str]]]] = {}
|
170
182
|
# Apply each matching override
|
toml_combine/exceptions.py
CHANGED
@@ -20,7 +20,7 @@ class TomlEncodeError(TomlCombineError):
|
|
20
20
|
|
21
21
|
|
22
22
|
class IncompatibleOverrides(TomlCombineError):
|
23
|
-
"""
|
23
|
+
"""Incompatible overrides `{id}` and `{other_override}`: When they're both applicable, overrides defining a common overridden key ({key}) must be a subset of one another"""
|
24
24
|
|
25
25
|
|
26
26
|
class DimensionNotFound(TomlCombineError):
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: toml-combine
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.3
|
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
|
@@ -47,7 +47,10 @@ name = "my-service"
|
|
47
47
|
registry = "gcr.io/my-project/"
|
48
48
|
container.image_name = "my-image"
|
49
49
|
container.port = 8080
|
50
|
-
|
50
|
+
|
51
|
+
[[override]]
|
52
|
+
when.environment = "production"
|
53
|
+
service_account = "my-production-service-account"
|
51
54
|
|
52
55
|
[[override]]
|
53
56
|
when.environment = "staging"
|
@@ -68,29 +71,115 @@ The common configuration to start from, before we start overlaying overrides on
|
|
68
71
|
|
69
72
|
### Overrides
|
70
73
|
|
71
|
-
|
72
|
-
"<
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
74
|
+
Each override defines a set of condition where it applies (`when.<dimension> =
|
75
|
+
"<dimension_value>"`) and a set of overridden key/values.
|
76
|
+
|
77
|
+
```toml
|
78
|
+
[[override]]
|
79
|
+
# Keys starting with `when.` are "conditions"
|
80
|
+
when.environment = "staging"
|
81
|
+
when.region = "us"
|
82
|
+
|
83
|
+
# Other keys in an override are "overridden keys" / "overridden values"
|
84
|
+
service_account = "my-us-staging-service-account"
|
85
|
+
```
|
86
|
+
|
87
|
+
If you run `toml-combine` with a given mapping that selects multiple overrides, they
|
88
|
+
will be checked for _compatibility_ with one another, and an error will be raised if
|
89
|
+
they're _not compatible_.
|
90
|
+
|
91
|
+
Compatibility rules:
|
92
|
+
|
93
|
+
- If the two overrides don't share any _overridden key_, then they're always compatible.
|
94
|
+
|
95
|
+
<details>
|
96
|
+
<summary>Example (click to expand)</summary>
|
97
|
+
|
98
|
+
```toml
|
99
|
+
[dimensions]
|
100
|
+
environment = ["staging"]
|
101
|
+
region = ["eu"]
|
102
|
+
|
103
|
+
[[override]]
|
104
|
+
when.environment = "staging"
|
105
|
+
service_account = "my-staging-service-account"
|
106
|
+
|
107
|
+
[[override]]
|
108
|
+
when.region = "eu"
|
109
|
+
env.CURRENCY = "EUR"
|
110
|
+
```
|
111
|
+
|
112
|
+
</details>
|
113
|
+
|
114
|
+
- If an override defines a set of conditions (say `env=prod`) and the other one defines
|
115
|
+
strictly more conditions (say `env=prod, region=eu`, in other words, it defines all
|
116
|
+
the conditions of the first override and then some more), then they're compatible.
|
117
|
+
Also, in that case, **the override with more conditions will have precedence**.
|
118
|
+
|
119
|
+
<details>
|
120
|
+
<summary>Example</summary>
|
121
|
+
|
122
|
+
```toml
|
123
|
+
[dimensions]
|
124
|
+
environment = ["staging"]
|
125
|
+
region = ["eu"]
|
126
|
+
|
127
|
+
[[override]]
|
128
|
+
when.environment = "staging"
|
129
|
+
service_account = "my-staging-service-account"
|
130
|
+
|
131
|
+
[[override]]
|
132
|
+
when.environment = "staging"
|
133
|
+
when.region = "eu"
|
134
|
+
service_account = "my-staging-eu-service-account"
|
135
|
+
```
|
136
|
+
|
137
|
+
</details>
|
138
|
+
|
139
|
+
- If they both define a dimension that the other one doesn't, they're incompatible.
|
140
|
+
|
141
|
+
<details>
|
142
|
+
<summary>Example (click to expand)</summary>
|
143
|
+
|
144
|
+
Incompatible overrides: neither is a subset of the other one and they both
|
145
|
+
define a value for `service_account`:
|
146
|
+
|
147
|
+
```toml
|
148
|
+
[dimensions]
|
149
|
+
environment = ["staging"]
|
150
|
+
region = ["eu"]
|
151
|
+
|
152
|
+
[default]
|
153
|
+
service_account = "my-service-account"
|
154
|
+
|
155
|
+
[[override]]
|
156
|
+
when.environment = "staging"
|
157
|
+
service_account = "my-staging-service-account"
|
158
|
+
|
159
|
+
[[override]]
|
160
|
+
when.region = "eu"
|
161
|
+
service_account = "my-eu-service-account"
|
162
|
+
```
|
163
|
+
|
164
|
+
```console
|
165
|
+
$ toml-combine config.toml --environment=staging --region=eu
|
166
|
+
Error: Incompatible overrides `{'region': ['eu']}` and `{'environment': ['staging']}`:
|
167
|
+
When they're both applicable, overrides defining a common overridden key (foo) must be
|
168
|
+
a subset of one another
|
169
|
+
```
|
170
|
+
|
171
|
+
> [!NOTE]
|
172
|
+
> It's ok to have incompatible overrides in your config as long as you don't
|
173
|
+
> run `toml-combine` with a mapping that would select both of them. In the example
|
174
|
+
> above, if you run `toml-combine --environment=staging --region=eu`, the error
|
175
|
+
> will be triggered, but you can run `toml-combine --environment=staging`.
|
176
|
+
|
177
|
+
</details>
|
178
|
+
|
179
|
+
> [!NOTE]
|
92
180
|
> Instead of defining a single value for the override dimensions, you can define a list.
|
93
181
|
> This is a shortcut to duplicating the override with each individual value:
|
182
|
+
>
|
94
183
|
> ```
|
95
184
|
> [[override]]
|
96
185
|
> when.environment = ["staging", "prod"]
|
@@ -0,0 +1,12 @@
|
|
1
|
+
toml_combine/__init__.py,sha256=TDkOwwEM-nS6hOh79u9Qae6g2Q6VfANpPpnKGfSgu80,84
|
2
|
+
toml_combine/__main__.py,sha256=hmF8N8xX6UEApzbKTVZ-4E1HU5-rjgUkdXNLO-mF6vo,100
|
3
|
+
toml_combine/cli.py,sha256=1eeh6sdKLsn5klRSc7E1rcBhN5Cf1O1Za5-Ule9FRVU,2867
|
4
|
+
toml_combine/combiner.py,sha256=fjsZ4WAKl7uO8BE8lYirJgo_1uj1t2o24rJA_FT1NFM,6147
|
5
|
+
toml_combine/exceptions.py,sha256=KrZpSdaI_ssYKw9LMsc3PAqNXEP-q6sT9scpgpXOo8o,1094
|
6
|
+
toml_combine/lib.py,sha256=jh6OG57JefpGa-WE-mLSIK6KjyJ0-1yGBynr_kiVTww,1634
|
7
|
+
toml_combine/toml.py,sha256=iBV8xj0qWcvGp2AZaML8FCT3i2X9DL7iA6jd-wcP5Bc,814
|
8
|
+
toml_combine-1.0.3.dist-info/METADATA,sha256=mP4H-UhEjmZedJSN55C6OOKvqOf2xgS1U4xYi2afKas,10653
|
9
|
+
toml_combine-1.0.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
10
|
+
toml_combine-1.0.3.dist-info/entry_points.txt,sha256=dXUQNom54uZt_7ylEG81iNYMamYpaFo9-ItcZJU6Uzc,58
|
11
|
+
toml_combine-1.0.3.dist-info/licenses/LICENSE,sha256=tA7wpipzIPGl7xL5xzMMg0RhhXz9CKOa-ZnlYzgiTKg,1059
|
12
|
+
toml_combine-1.0.3.dist-info/RECORD,,
|
@@ -1,12 +0,0 @@
|
|
1
|
-
toml_combine/__init__.py,sha256=TDkOwwEM-nS6hOh79u9Qae6g2Q6VfANpPpnKGfSgu80,84
|
2
|
-
toml_combine/__main__.py,sha256=hmF8N8xX6UEApzbKTVZ-4E1HU5-rjgUkdXNLO-mF6vo,100
|
3
|
-
toml_combine/cli.py,sha256=hG03eDKz7xU-ydJIa1kDuu6WlFzNS3GTMJ6zals9M9c,2843
|
4
|
-
toml_combine/combiner.py,sha256=HG7KV3EGwmcHOMruhp7sMkH-uXqWKpsO7_BvhNQ2KQY,5668
|
5
|
-
toml_combine/exceptions.py,sha256=cRAZhxg3OHgzp5hJzyxNGG_jvGUm8gG8XzndQXBhvo8,1116
|
6
|
-
toml_combine/lib.py,sha256=jh6OG57JefpGa-WE-mLSIK6KjyJ0-1yGBynr_kiVTww,1634
|
7
|
-
toml_combine/toml.py,sha256=iBV8xj0qWcvGp2AZaML8FCT3i2X9DL7iA6jd-wcP5Bc,814
|
8
|
-
toml_combine-1.0.1.dist-info/METADATA,sha256=K0j97FCiS7tpENiP_HVoxE1b6_nLDqk_E1OklTtFhpk,8812
|
9
|
-
toml_combine-1.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
10
|
-
toml_combine-1.0.1.dist-info/entry_points.txt,sha256=dXUQNom54uZt_7ylEG81iNYMamYpaFo9-ItcZJU6Uzc,58
|
11
|
-
toml_combine-1.0.1.dist-info/licenses/LICENSE,sha256=tA7wpipzIPGl7xL5xzMMg0RhhXz9CKOa-ZnlYzgiTKg,1059
|
12
|
-
toml_combine-1.0.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|