fix: prevent nested dict flattening in _create_at#42
Merged
Conversation
c354119 to
dc5b870
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes incorrect YAML structure produced by Document.upsert() when creating missing intermediate keys whose value is a nested mapping, avoiding yamlpatch MergeInto’s uniform-indent serialization limitations.
Changes:
- Update
_create_at()to route nested dict/list values through a two-stepaddplaceholder +replaceoperation instead ofmerge_into. - Add a regression test covering nested dict insertion via intermediate keys.
- Document
merge_into’s flat-only constraint in Rust bindings and update the design spec accordingly.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| tests/test_document.py | Adds regression test ensuring nested dict values remain properly nested when upserting through missing intermediate keys. |
| src/yamltrip/document.py | Implements conditional fallback to add + replace to preserve indentation for nested values when creating intermediate keys. |
| src/ops.rs | Documents merge_into as intended for flat/scalar-only updates and advises add + replace for nested values. |
| doc/specs/2026-05-13-yamltrip-design.md | Updates design notes to reflect the flat-vs-nested split in upsert() creation strategy. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
dc5b870 to
bbdd63b
Compare
bbdd63b to
5619950
Compare
…s a regression test for list values via intermediate keys.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a bug where
Op.merge_intoflattens nested dicts to the wrong indentation level when creating intermediate keys via_create_at.Problem
When calling
upsert("parent", "child", value={"x": 1, "y": 2})on a document whereparentdoesn't exist,_create_atbuildsnested_value = {"child": {"x": 1, "y": 2}}and passes it toOp.merge_into("parent", nested_value). The Rustmerge_intooperation flattens the nested dict, producing:instead of the correct:
Fix
Replace the single
Op.merge_intocall with a two-step approach:Op.add(first_key, None)— creates the key with a placeholderOp.replace(nested_value)on the new path — replaces with the full nested structureOp.replacecorrectly serializes complex values, avoiding the flattening.Testing
Adds a regression test (
test_upsert_missing_nested_path_with_dict) that fails without the fix and passes with it. All 351 existing tests continue to pass.