Skip to main content

A round-tripping YAML library for Python

Project description

yamltrip

usethis PyPI Version PyPI License PyPI Supported Versions

Edit YAML files from Python, while respecting format and comments during the round-trip.

Built on tree-sitter-yaml via the yamlpath and yamlpatch Rust crates.

Installation

# With uv
$ uv add yamltrip

# With pip
$ pip install yamltrip

Quick Start

import yamltrip

# Load and read
doc = yamltrip.loads("name: Alice\nage: 30")
print(doc["name"])       # "Alice"
print("name" in doc)     # True

# Immutable mutations: each call returns a new Document
doc2 = doc.replace("age", value=31)
doc3 = doc2.add(key="city", value="Portland")
print(doc3.dumps())

# Complex values (dicts/lists) work too
doc4 = doc3.replace("age", value={"years": 31, "months": 4})
doc5 = doc4.upsert("hobbies", value=["reading", "hiking"])

# File-based editing with a context manager
with yamltrip.edit("config.yml") as editor:
    editor.replace("version", value="2.0")
    editor.upsert("settings", "debug", value=True)
    # writes back on successful exit; discards on exception

API Overview

Top-level function

Function Description
yamltrip.loads(source) Parse a YAML string into a Document
yamltrip.load(path) Read a YAML file into a Document
yamltrip.edit(path) Open a YAML file for editing (context manager)

Document (immutable)

Every mutation method returns a new Document. The original is never modified.

doc = yamltrip.loads("items:\n  - a\n  - b")

doc.root                      # {"items": ["a", "b"]}
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)
doc.upsert("new", "nested", value=True)
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.ensure_in_list("items", value="c")  # no-op if already present
doc.ensure_in_list("repos", where={"name": "x"}, value={"name": "x", "version": "1.0"})
doc.sync("items", value=["a", "new", "b"])  # minimal diff-and-patch
doc.merge("config", value={"debug": True, "level": 2})  # recursive mapping merge
doc.find_index("repos", where={"id": "x"})  # find in list-of-dicts; returns int | None

doc.query("items")            # Feature with location info
doc.query_pretty("items")    # Feature with surrounding context
doc.extract(feature)          # raw YAML text for a Feature
doc.has_anchors()             # True if anchors/aliases present
doc.dumps()                   # full YAML source
doc.dump("output.yml")        # write to file

Editor (mutable context manager)

Wraps Document with the same mutation methods, but applies changes in place and writes back to disk when the context exits cleanly:

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
    ed.merge("settings", value={"debug": True, "level": 2})  # recursive merge
    print(ed["version"])        # "2.0"
    print(ed.get("missing"))    # None
    print(ed.original["version"])  # original value before edits

Error Hierarchy

All yamltrip errors inherit from YAMLTripError:

  • ParseError: YAML input cannot be parsed.
  • QueryError: path not found during lookup.
  • PatchError: mutation operation failed.
    • KeyExistsError: add() target already exists.
    • KeyMissingError: replace() target does not exist.
    • RoutingError: path passes through a non-mapping node (scalar or list).
    • NodeTypeError (PatchError + TypeError): node is the wrong type for the operation (e.g. appending to a scalar).

Limitations

  • Multi-document YAML streams (--- separated) are not supported.
  • YAML tags (!!omap, !!set, !!merge, custom tags) are not interpreted.
  • Anchors and aliases (&anchor / *alias) are detected (doc.has_anchors()) but not resolved during value extraction.
  • Large integers may lose precision. YAML integers outside the signed 64-bit range (i64) may become float during deserialization.
  • Editor write-back is not atomic. Editor detects external file changes between enter and exit, but the check-then-write is racy. Do not use it with concurrent writers.

Design Decisions

  • No custom Python class serialization. Values convert to/from str, int, float, bool, None, list, and dict only.
  • UTF-8 only. Other encodings raise ParseError.
  • Non-finite floats round-trip. float("inf"), float("-inf"), and float("nan") map to YAML's .inf, -.inf, and .nan.
  • 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 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.

Acknowledgements

yamltrip depends entirely on the yamlpath and yamlpatch Rust crates for format-preserving YAML parsing and patching. These libraries use tree-sitter to query and modify YAML source text without discarding comments, whitespace, or key ordering. All of the core logic in yamltrip passes through them. Thanks to William Woodruff for creating and maintaining both crates as part of zizmor.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

yamltrip-0.6.0.tar.gz (137.6 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

yamltrip-0.6.0-cp310-abi3-win_amd64.whl (556.8 kB view details)

Uploaded CPython 3.10+Windows x86-64

yamltrip-0.6.0-cp310-abi3-musllinux_1_2_x86_64.whl (976.7 kB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ x86-64

yamltrip-0.6.0-cp310-abi3-musllinux_1_2_aarch64.whl (933.8 kB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ ARM64

yamltrip-0.6.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (794.2 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ x86-64

yamltrip-0.6.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (755.3 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ ARM64

yamltrip-0.6.0-cp310-abi3-macosx_11_0_arm64.whl (693.9 kB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

yamltrip-0.6.0-cp310-abi3-macosx_10_12_x86_64.whl (711.8 kB view details)

Uploaded CPython 3.10+macOS 10.12+ x86-64

File details

Details for the file yamltrip-0.6.0.tar.gz.

File metadata

  • Download URL: yamltrip-0.6.0.tar.gz
  • Upload date:
  • Size: 137.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for yamltrip-0.6.0.tar.gz
Algorithm Hash digest
SHA256 2983877975ed10be6907a9cc7ef372f415bdcb2024dd91e2897e71dc2bba2b25
MD5 b5dcaace6735f5db050b18739862bfc0
BLAKE2b-256 ab0336404a8e2028ce4def0102eef142ccffbc74a1c12890c8d913c8e187bc41

See more details on using hashes here.

File details

Details for the file yamltrip-0.6.0-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: yamltrip-0.6.0-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 556.8 kB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for yamltrip-0.6.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 11cba12d86fd5ed44fe2ce98a51e12fb60d4420ab2f1075ad8d744ee3beb0b2c
MD5 307ddbb960d70b3521165ada464e36da
BLAKE2b-256 c31e3f62eea5f06d4de4a17b583fccb63001eec942f06f2cf5fc05eaa47a6965

See more details on using hashes here.

File details

Details for the file yamltrip-0.6.0-cp310-abi3-musllinux_1_2_x86_64.whl.

File metadata

  • Download URL: yamltrip-0.6.0-cp310-abi3-musllinux_1_2_x86_64.whl
  • Upload date:
  • Size: 976.7 kB
  • Tags: CPython 3.10+, musllinux: musl 1.2+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for yamltrip-0.6.0-cp310-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 b2d11277568743cacd397607663d75075115dd88a0bf4a4fad7fb0100dc5f612
MD5 611f25af23249c0dace37b32c83742de
BLAKE2b-256 fde43b6ed066a75341da8b50f9ad49aec9d80b3812602dd29be3498a5da8c21d

See more details on using hashes here.

File details

Details for the file yamltrip-0.6.0-cp310-abi3-musllinux_1_2_aarch64.whl.

File metadata

  • Download URL: yamltrip-0.6.0-cp310-abi3-musllinux_1_2_aarch64.whl
  • Upload date:
  • Size: 933.8 kB
  • Tags: CPython 3.10+, musllinux: musl 1.2+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for yamltrip-0.6.0-cp310-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 2054a7d9447829a4b531463c2454201e163e04341619614c8a3526e5a91f7b98
MD5 9ab259f4fcd3c01e1cdcb215fc1a0c9e
BLAKE2b-256 05f01cb44f39c08e4101e55ec6662071dcfcc6660210039fcd2ff537bc7a808c

See more details on using hashes here.

File details

Details for the file yamltrip-0.6.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

  • Download URL: yamltrip-0.6.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
  • Upload date:
  • Size: 794.2 kB
  • Tags: CPython 3.10+, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for yamltrip-0.6.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 f11d97cddb255776f32888b8fcfce7707d39d83955c8202b067af7c17b270ce9
MD5 dabc1bc3db5ff7a8f8026f143aaf7700
BLAKE2b-256 69ca65fc1930f58b6381b0a43c9ebb8f385f576fa629113c039e0aa2d12b584f

See more details on using hashes here.

File details

Details for the file yamltrip-0.6.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

  • Download URL: yamltrip-0.6.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
  • Upload date:
  • Size: 755.3 kB
  • Tags: CPython 3.10+, manylinux: glibc 2.17+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for yamltrip-0.6.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 985f8c0908764f6823999f2ce4916fdce5129bf6993b7df4bf1f0535379acdd4
MD5 190b4f50c38cbb7af8b6944551b64930
BLAKE2b-256 b909a751cf170298929edb00ff2eee67206dbbd76cf41076b9ed2b8bd5c78532

See more details on using hashes here.

File details

Details for the file yamltrip-0.6.0-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

  • Download URL: yamltrip-0.6.0-cp310-abi3-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 693.9 kB
  • Tags: CPython 3.10+, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for yamltrip-0.6.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 08e9e9add38e2ea5fd14d5825897ebec065150d3c3a74c13a9b8db37778fa6a8
MD5 4600bb2f06f1306374355a89c3234a79
BLAKE2b-256 d4cd3033674844b9bfdce057c8debf5b104f7004e1a7e21e55240b472b20e102

See more details on using hashes here.

File details

Details for the file yamltrip-0.6.0-cp310-abi3-macosx_10_12_x86_64.whl.

File metadata

  • Download URL: yamltrip-0.6.0-cp310-abi3-macosx_10_12_x86_64.whl
  • Upload date:
  • Size: 711.8 kB
  • Tags: CPython 3.10+, macOS 10.12+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for yamltrip-0.6.0-cp310-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 c58a90f9a5315af45d068458f4e0995fb7181df2b56c96da10bc9bca8284378d
MD5 6738f302adc80c88659646ee529d35b8
BLAKE2b-256 c7351f28e3d11603483b953f0e6f11dbd25f52525cb87d9407b97c04562e8ef5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page