Skip to content

Add a sync/apply-dict operation that diffs and patches minimally #25

Description

@nathanjmcdougall

Problem

A common pattern when editing YAML config files is:

  1. Parse the document into a Python dict (a model)
  2. Mutate the model in Python
  3. Write it back, preserving comments and formatting

With yamltrip today, step 3 requires manually orchestrating individual upsert, replace, append, remove, and remove_from_list calls for each change. This is verbose and error-prone compared to the old ruamel.yaml approach of mutating a CommentedMap in place and dumping it.

Proposal

Add a sync method that takes a desired Python value, diffs it against the current document content at a given path, and applies the minimal set of patches:

# Scalar/mapping sync — straightforward recursive diff
doc2 = doc.sync('ci', value={'autofix_prs': False, 'skip': ['codespell']})

# List sync with identity key — matches items by a field rather than position
doc2 = doc.sync('repos', value=new_repos, identity_key='repo')

Diff strategy

Change type Patch generated Comments preserved?
New mapping key upsert Yes
Removed mapping key remove Yes
Scalar value changed replace at path Yes
Nested mapping changed Recurse deeper Yes
List item appended append Yes
List item removed remove_from_list Yes
List item inserted (needs insert_at) Depends on #24 Yes

The list-diffing challenge

Without an identity key, list diffing is ambiguous. The identity_key parameter tells sync how to match old and new items (e.g. match pre-commit repos by their repo URL, hooks by their id field). Items matched by identity are diffed recursively; unmatched old items are removed; unmatched new items are appended (or inserted, once #24 lands).

Use case

In usethis, the pre-commit integration previously did:

model.repos.append(new_repo)
mgr.commit_model(model)  # diffs and writes back

After migrating to yamltrip, this became multiple lines of manual patch orchestration. A sync method would restore the simplicity while keeping yamltrip's comment-preservation guarantees.

Notes

Activity

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

Metadata

Metadata

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions