diff --git a/CHANGELOG.md b/CHANGELOG.md index 1467829..296d413 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 0.4.0 + +### Features + +- Added `Document.insert()` and `Editor.insert()` for inserting an item at a specific position in a sequence. Uses Python `list.insert()` semantics (negative indices count from end, out-of-range clamps). +- Added `Document.get()` and `Editor.get()` for non-raising value access. This returns a default (defaults to `None`) when the path doesn't exist, similar to `dict.get()`. +- Added `Document.sync()` and `Editor.sync()` that diffs the current value at a path against a desired value and applies the minimal set of patches. Supports recursive mapping diffing and `SequenceMatcher`-based list diffing to preserve comments and formatting on unchanged elements. + +### Internal + +- Introduced `OpInner` enum in Rust to support local ops (like `insert_at`) alongside yamlpatch-delegated operations. +- Extracted `KeyPart` type alias to `_types.py`. + ## 0.3.0 ### Features diff --git a/Cargo.lock b/Cargo.lock index c3d3e8d..ea6dd03 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -466,7 +466,7 @@ dependencies = [ [[package]] name = "yamltrip" -version = "0.3.0" +version = "0.4.0" dependencies = [ "indexmap", "pyo3", diff --git a/Cargo.toml b/Cargo.toml index 35e0616..6745ae5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yamltrip" -version = "0.3.0" +version = "0.4.0" edition = "2024" license = "MIT" diff --git a/README.md b/README.md index 4e506f5..43b5804 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,9 @@ doc["items"] # ["a", "b"] doc["items", 0] # "a" ("items", 0) in doc # True +doc.get("items", 0) # "a" (returns None if missing) +doc.get("missing", default=42) # 42 + doc.replace("items", 0, value="x") doc.replace("items", value=["x", "y"]) # dicts and lists accepted doc.add("items", key="c", value=3) @@ -73,8 +76,10 @@ doc.upsert("config", value={"debug": True}) # dicts and lists accepted doc.remove("items", 0) doc.prune_remove("a", "b", "c") # remove + prune empty parents doc.append("items", value="c") +doc.insert("items", index=1, value="between") # positional insert doc.extend_list("items", values=["d", "e"]) doc.remove_from_list("items", values=["a"]) +doc.sync("items", value=["a", "new", "b"]) # minimal diff-and-patch doc.query("items") # Feature with location info doc.query_pretty("items") # Feature with surrounding context @@ -94,7 +99,9 @@ with yamltrip.edit("config.yml") as ed: ed.replace("version", value="2.0") ed.upsert("new_key", value="new_value") ed.remove("old_key") + ed.sync("deps", value={"a": "1.0", "b": "2.0"}) # minimal patching print(ed["version"]) # "2.0" + print(ed.get("missing")) # None print(ed.original["version"]) # original value before edits ``` @@ -131,8 +138,9 @@ All yamltrip errors inherit from `YAMLTripError`: - **Integer keys cannot create structures.** `upsert()` with integer path components can update existing sequence entries but cannot create new intermediate mappings. Only string keys create new mappings. -- **No negative sequence indices.** Python-style negative indexing is not - supported. +- **No negative sequence indices for lookup.** Python-style negative indexing + is not supported for `[]` access or `replace()`/`remove()`. However, + `insert()` accepts negative indices (matching `list.insert()` semantics). - **Line endings preserved as-is.** No CRLF/LF normalization. Mixed line endings pass through unchanged. diff --git a/pyproject.toml b/pyproject.toml index c6476ed..28cf098 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ requires = [ "maturin>=1.0,<2.0" ] [project] name = "yamltrip" -version = "0.3.0" +version = "0.4.0" description = "A round-tripping YAML library for Python" readme = "README.md" authors = [ { name = "Nathan McDougall", email = "nathan.j.mcdougall@gmail.com" } ]