How-To: Merge Configurations¶
Dracon excels at layering configurations, applying overrides, and combining settings from multiple sources. This is primarily achieved through the extended YAML merge key (<<:).
Quick Reference¶
Pick the pattern that matches your intent:
| I want to... | Syntax | Example |
|---|---|---|
| Pull in defaults (my values win) | <<: |
<<: !include file:base.yaml |
| Apply overrides (incoming wins) | <<{<+}[<~]: |
<<{<+}[<~]: !include file:prod.yaml |
| Replace entirely (no deep merge) | <<{~<}[~<]: |
<<{~<}[~<]: !include file:generated.yaml |
| Defaults + concatenate lists | <<[+>]: |
<<[+>]: !include file:plugins.yaml |
| Override + concatenate lists | <<{<+}[+<]: |
<<{<+}[+<]: !include file:extra.yaml |
Import !define variables |
<<(<): |
<<(<): !include file:constants.yaml |
| Merge into a sub-key | <<@path: |
<<@app.db: !include file:db.yaml |
See the Merge Key Reference for the full syntax and all options.
Basic Merging (Multiple Files)¶
When loading multiple files with dracon.load, they are merged sequentially.
import dracon as dr
# Loads base.yaml, then merges prod.yaml onto it
# Default strategy for multi-file load: <<{<+}[<~]
# (Dict: Recursive Append, New wins; List: Replace, New wins)
config = dr.load(["config/base.yaml", "config/prod.yaml"], context={...})
Explicit Merging (<<:)¶
You can explicitly merge nodes within a single YAML file using the <<: key.
defaults: &defaults
timeout: 30
retries: 3
features: [a, b]
service_config:
# Inherit from defaults using the plain merge key
<<: *defaults # standard YAML merge (existing wins, replace keys - non recursive). Equivalent to <<{>~}[>~]: *defaults
# Override specific values
timeout: 60
# Add new values
endpoint: /api/v1
# Add new list - default for list merge is REPLACE, EXISTING wins
# So, the 'features' key from *defaults is kept.
# If we added 'features: [c, d]' here *after* the merge key,
# it would simply overwrite the merged key.
# Resulting service_config (using <<: *defaults default {+>}[~>]):
# { timeout: 30, retries: 3, features: [a, b], endpoint: /api/v1 }
# Note: timeout: 60 defined *after* the merge would override the merged value.
Advanced Merging with Options¶
Dracon extends <<: with options to control dictionary and list merging precisely:
<<{dict_opts}[list_opts]@target_path: source_node
{dict_opts}: Controls dictionary merging.~: Replace. Overwrites entire value for conflicting keys.+(Default) Append/Recurse. Merges nested dicts.>(Default): Existing value wins priority.<: New value (i.e. source_node) wins priority.N(e.g.,+2): Limit recursion depth.[list_opts]: Controls list merging (only if both existing and new values are lists).~(Default): Replace full list.+: Concatenate lists.>(Default): Existing list wins / Appends new list in+mode.<: New list (i.e. from source_node) wins / Prepends new list in+mode.@target_path: (Optional) Apply the merge to a sub-key relative to the current node. Uses KeyPath syntax.source_node: The node to merge in (e.g.,*anchor,!include file:other.yaml, or a regular YAML mapping).
Default <<: key (no options): Equivalent to <<{+>}[~>] (Dict: Append/Recurse, Existing Wins; List: Replace, Existing Wins).
Examples:
-
Recursive Dict Merge, Existing (local) Wins:
base: &base db: { host: localhost, port: 5432 } settings: { theme: light } prod: <<{+>}: *base # Merge recursively (+), existing wins (>) db: host: prod.db # Overrides base host # port inherited from base settings: workers: 4 # Added # Result prod: { db: { host: prod.db, port: 5432 }, settings: { theme: light, workers: 4 } } -
Replace and Append to List, Existing First:
defaults: &defaults middlewares: [logging, auth] # Replace custom: <<[~>]: *defaults # Replace lists (~), existing first (>) middlewares: [cors, caching] # This definition *overwrites* the merged list # Result custom: { middlewares: [cors, caching] } # Append custom_append: <<[+>]: *defaults # Concatenates, existing ([cors, caching]) first middlewares: [cors, caching] # Result custom_append: { middlewares: [cors, caching, logging, auth] } -
Merge into Sub-key:
See Merging Concepts and the Merge Key Reference for full details and strategy explanations.