Merge a local override into nested configuration lookups
Merge a local override into nested configuration lookups
By Batu. AI assistance was used to prepare this article.
collections.ChainMap provides one mapping-like lookup view across several mappings. It searches its maps from left to right, so new_child(local) is a useful way to put a short-lived local override ahead of an existing environment-and-default chain. This avoids copying a merged dictionary when the desired behavior is simply “first value found wins.”
from collections import ChainMap
defaults = {"host": "127.0.0.1", "port": 8000, "debug": False}
environment = {"port": 8080, "debug": True}
base_config = ChainMap(environment, defaults)
local = {"port": 9000}
config = base_config.new_child(local)
config["debug"] = False
assert config["host"] == "127.0.0.1"
assert config["port"] == 9000
assert config["debug"] is False
assert local == {"port": 9000, "debug": False}
print(f"host={config['host']}")
print(f"port={config['port']}")
print(f"debug={config['debug']}")
print(f"local={local}")
Expected stdout
host=127.0.0.1
port=9000
debug=False
local={'port': 9000, 'debug': False}
The host lookup falls through the local and environment mappings to defaults. port comes from local, and assigning config["debug"] writes only to the first map, which is why local gains that key. The original environment mapping remains unchanged.
This is a lookup overlay, not a recursive configuration merge. If defaults["database"] and local["database"] are both dictionaries, the local dictionary replaces the whole top-level value rather than selectively combining nested keys. Missing keys raise KeyError, just as with a normal dictionary. ChainMap also keeps references to its input mappings, so a later mutation of environment or defaults is visible through config; make copies first when a snapshot is required.
Source: Python ChainMap documentation.
Comments
Post a Comment