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

Popular posts from this blog

Compare Two Text Files in Python Without Modifying Them

Seven CSV Quality Checks to Run Before Importing Data

Explain why SQLite transactions cannot make an HTTP call atomic