Problem
A common pattern when editing YAML config files is:
- Parse the document into a Python dict (a model)
- Mutate the model in Python
- 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
Problem
A common pattern when editing YAML config files is:
With yamltrip today, step 3 requires manually orchestrating individual
upsert,replace,append,remove, andremove_from_listcalls for each change. This is verbose and error-prone compared to the old ruamel.yaml approach of mutating aCommentedMapin place and dumping it.Proposal
Add a
syncmethod that takes a desired Python value, diffs it against the current document content at a given path, and applies the minimal set of patches:Diff strategy
upsertremovereplaceat pathappendremove_from_listinsert_at)The list-diffing challenge
Without an identity key, list diffing is ambiguous. The
identity_keyparameter tells sync how to match old and new items (e.g. match pre-commit repos by theirrepoURL, hooks by theiridfield). 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:
After migrating to yamltrip, this became multiple lines of manual patch orchestration. A
syncmethod would restore the simplicity while keeping yamltrip's comment-preservation guarantees.Notes
Documentprimitives.insert_at).