Skip to content

[v1.0] Preserve correct provenance for nested configuration merges #263

Description

@codeforester

Goal

Make Context.config_provenance report the actual winning source for every nested leaf.

Background

The batteries-included profile promises recursive merging and dotted-path provenance. The recursive branch currently calls _merge_mapping() with the global provenance map but without the parent prefix, then updates the correctly-prefixed paths afterward:

def _merge_mapping(
target: dict[str, Any],
provenance: dict[str, str],
incoming: Mapping[str, Any],
source: str,
) -> None:
for key, value in incoming.items():
if not isinstance(key, str):
raise ConfigurationError("Configuration keys must be strings.")
previous = target.get(key)
if isinstance(previous, Mapping) and isinstance(value, Mapping):
_merge_mapping(target[key], provenance, value, source)
provenance.update(_leaf_provenance(value, source, key))
continue
for path in tuple(provenance):
if path == key or path.startswith(f"{key}."):
del provenance[path]
target[key] = dict(value) if isinstance(value, Mapping) else value
provenance.update(_leaf_provenance(value, source, key))
.

A merge of {"host": "top", "db": {"host": "one"}} from user, followed by {"db": {"host": "two"}} from project, leaves the value of top-level host unchanged but changes its provenance to project. The resulting map incorrectly reports host=project and db.host=project.

Scope

  • Carry the complete dotted prefix through recursive merges.
  • Remove stale provenance only inside the replaced subtree.
  • Cover recursive mapping-to-mapping, mapping-to-scalar, scalar-to-mapping, and sibling keys with the same leaf name.

Acceptance Criteria

  • The reproduction above keeps host=user and sets only db.host=project.
  • Context.config_provenance agrees with the final value at every leaf.
  • Existing precedence and consumer-owned configuration semantics do not change.
  • Regression tests exercise at least three nested levels and repeated leaf names.

Validation

Run the batteries-included configuration tests and the full Python suite.

Non-Goals

Do not add a new precedence model or configuration source.

Project Fields

  • Status: Backlog
  • Priority: P1
  • Area: Python
  • Initiative: v1.0 Readiness
  • Size: S

Ownership

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething is not working

Type

No type

Projects

  • Status
    Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions