@@ -117,7 +117,7 @@ def __init__(self, isolated: bool, load_only: Kind | None = None) -> None:
117
117
self ._parsers : dict [Kind , list [tuple [str , RawConfigParser ]]] = {
118
118
variant : [] for variant in OVERRIDE_ORDER
119
119
}
120
- self ._config : dict [Kind , dict [str , Any ]] = {
120
+ self ._config : dict [Kind , dict [str , dict [ str , Any ] ]] = {
121
121
variant : {} for variant in OVERRIDE_ORDER
122
122
}
123
123
self ._modified_parsers : list [tuple [str , RawConfigParser ]] = []
@@ -148,7 +148,10 @@ def get_value(self, key: str) -> Any:
148
148
orig_key = key
149
149
key = _normalize_name (key )
150
150
try :
151
- return self ._dictionary [key ]
151
+ clean_config : dict [str , Any ] = {}
152
+ for file_values in self ._dictionary .values ():
153
+ clean_config .update (file_values )
154
+ return clean_config [key ]
152
155
except KeyError :
153
156
# disassembling triggers a more useful error message than simply
154
157
# "No such key" in the case that the key isn't in the form command.option
@@ -171,7 +174,8 @@ def set_value(self, key: str, value: Any) -> None:
171
174
parser .add_section (section )
172
175
parser .set (section , name , value )
173
176
174
- self ._config [self .load_only ][key ] = value
177
+ self ._config [self .load_only ].setdefault (fname , {})
178
+ self ._config [self .load_only ][fname ][key ] = value
175
179
self ._mark_as_modified (fname , parser )
176
180
177
181
def unset_value (self , key : str ) -> None :
@@ -181,11 +185,14 @@ def unset_value(self, key: str) -> None:
181
185
self ._ensure_have_load_only ()
182
186
183
187
assert self .load_only
184
- if key not in self ._config [self .load_only ]:
185
- raise ConfigurationError (f"No such key - { orig_key } " )
186
-
187
188
fname , parser = self ._get_parser_to_modify ()
188
189
190
+ if (
191
+ key not in self ._config [self .load_only ][fname ]
192
+ and key not in self ._config [self .load_only ]
193
+ ):
194
+ raise ConfigurationError (f"No such key - { orig_key } " )
195
+
189
196
if parser is not None :
190
197
section , name = _disassemble_key (key )
191
198
if not (
@@ -200,8 +207,10 @@ def unset_value(self, key: str) -> None:
200
207
if not parser .items (section ):
201
208
parser .remove_section (section )
202
209
self ._mark_as_modified (fname , parser )
203
-
204
- del self ._config [self .load_only ][key ]
210
+ try :
211
+ del self ._config [self .load_only ][fname ][key ]
212
+ except KeyError :
213
+ del self ._config [self .load_only ][key ]
205
214
206
215
def save (self ) -> None :
207
216
"""Save the current in-memory state."""
@@ -233,7 +242,7 @@ def _ensure_have_load_only(self) -> None:
233
242
logger .debug ("Will be working with %s variant only" , self .load_only )
234
243
235
244
@property
236
- def _dictionary (self ) -> dict [str , Any ]:
245
+ def _dictionary (self ) -> dict [str , dict [ str , Any ] ]:
237
246
"""A dictionary representing the loaded configuration."""
238
247
# NOTE: Dictionaries are not populated if not loaded. So, conditionals
239
248
# are not needed here.
@@ -273,7 +282,8 @@ def _load_file(self, variant: Kind, fname: str) -> RawConfigParser:
273
282
274
283
for section in parser .sections ():
275
284
items = parser .items (section )
276
- self ._config [variant ].update (self ._normalized_keys (section , items ))
285
+ self ._config [variant ].setdefault (fname , {})
286
+ self ._config [variant ][fname ].update (self ._normalized_keys (section , items ))
277
287
278
288
return parser
279
289
@@ -300,7 +310,8 @@ def _construct_parser(self, fname: str) -> RawConfigParser:
300
310
301
311
def _load_environment_vars (self ) -> None :
302
312
"""Loads configuration from environment variables"""
303
- self ._config [kinds .ENV_VAR ].update (
313
+ self ._config [kinds .ENV_VAR ].setdefault (":env:" , {})
314
+ self ._config [kinds .ENV_VAR ][":env:" ].update (
304
315
self ._normalized_keys (":env:" , self .get_environ_vars ())
305
316
)
306
317
0 commit comments