Skip to content

Merge policies

This guide introduces combining two configuration instances with merge(), and how to control that with Meta.merge and per-field merge=.

You should already know ConfigurationObj, fields, and Meta (guides 101–105).

Why merge?

Typical need: start from defaults (or a base file), then apply an overlay (environment, CLI, second file) without rewriting the whole tree by hand.

from superconf import ConfigurationObj, FieldInt, FieldList, FieldString

class AppConfig(ConfigurationObj):
    name = FieldString(default="app")
    workers = FieldInt(default=2)
    tags = FieldList(default=[])

base = AppConfig(value={"name": "api", "tags": ["core"]})
overlay = AppConfig(value={"workers": 8, "tags": ["prod"]})
merged = base.merge(overlay)

print(merged.get_value())
# {'name': 'api', 'workers': 8, 'tags': ['core', 'prod']}

Notes:

  • merge() returns a new object; base and overlay stay unchanged.
  • Scalars use policy override by default (right wins when set).
  • Lists (FieldList) use policy append by default.

Declaring a policy on Meta

Meta.merge sets the policy for this container (how it combines with a peer of the same kind):

from superconf import MergeStrategy

class AppConfig(ConfigurationObj):
    class Meta:
        merge = MergeStrategy.OVERRIDE  # default for dict/obj; can omit

    name = FieldString(default="app")

Strings work the same: merge = "override".

Overriding per field

Field kwargs beat Meta (same precedence as cast):

class AppConfig(ConfigurationObj):
    class Meta:
        merge = "override"

    # Stay frozen when parent deep-merges
    build_id = FieldInt(default=0, merge=MergeStrategy.KEEP)
    name = FieldString(default="app")
    tags = FieldList(default=[], merge="replace")  # old-style full replace

Strategy cheat sheet

Kind Default Allowed
Scalar override override, override_non_null, keep
Dict / Obj override override, replace, override_present, override_absent, keep
List append append, prepend, replace, keep

Full tables and recipes: merging_configurations.md.

Migration note (lists)

Before merge policies, a list field that was set on the right replaced the left list. That behavior is merge="replace" now. The new default is append.

# Explicit old behavior
tags = FieldList(default=[], merge="replace")

Next steps