Skip to main content

A YAML round-trip library that preserves comments and insertion order

Project description

yarutsk

A Python YAML library that round-trips documents while preserving comments and insertion order.

What it does

Most YAML libraries silently drop comments on load. yarutsk keeps them attached to their keys — both inline (key: value # like this) and block-level (# above a key) — so a load → modify → dump cycle leaves the rest of the file intact.

import io
import yarutsk

doc = yarutsk.load(io.StringIO("""
# database config
host: localhost  # primary
port: 5432
"""))

doc["port"] = 5433

out = io.StringIO()
yarutsk.dump(doc, out)
print(out.getvalue())
# # database config
# host: localhost  # primary
# port: 5433

YamlMapping is a subclass of dict and YamlSequence is a subclass of list, so they work everywhere a dict or list is expected:

import json

doc = yarutsk.loads("name: Alice\nscores: [10, 20, 30]")

isinstance(doc, dict)           # True
isinstance(doc["scores"], list) # True
json.dumps(doc)                 # '{"name": "Alice", "scores": [10, 20, 30]}'

Installation

Built with Maturin. From the repo root:

pip install maturin
maturin develop

API

Loading and dumping

# Load from stream (StringIO / BytesIO)
doc  = yarutsk.load(stream)            # first document
docs = yarutsk.load_all(stream)        # all documents as a list

# Load from string
doc  = yarutsk.loads(text)
docs = yarutsk.loads_all(text)

# Dump to stream
yarutsk.dump(doc, stream)
yarutsk.dump_all(docs, stream)

# Dump to string
text = yarutsk.dumps(doc)
text = yarutsk.dumps_all(docs)

load / loads return a YamlMapping, YamlSequence, YamlScalar, or None (for empty input). Nested nodes are also YamlMapping or YamlSequence; scalar leaves are returned as native Python primitives (int, float, bool, str, or None).

YamlScalar

Top-level scalar documents are wrapped in a YamlScalar node:

doc = yarutsk.loads("42")
doc.value                              # 42 (Python int)
doc.to_dict()                          # same as .value

YamlMapping

YamlMapping is a subclass of dict with insertion-ordered keys. All standard dict operations work directly:

# Standard dict interface (inherited)
doc["key"]                             # get (KeyError if missing)
doc["key"] = value                     # set (preserves position if key exists)
del doc["key"]                         # delete
"key" in doc                           # membership test
len(doc)                               # number of entries
for key in doc: ...                    # iterate over keys in order
doc.keys()                             # KeysView in insertion order
doc.values()                           # ValuesView in insertion order
doc.items()                            # ItemsView of (key, value) pairs
doc.get("key")                         # returns None if missing
doc.get("key", default)                # returns default if missing
doc.pop("key")                         # remove & return (KeyError if missing)
doc.pop("key", default)                # remove & return, or default
doc.setdefault("key", default)         # get or insert default
doc.update(other)                      # merge from dict or YamlMapping
doc == {"a": 1}                        # equality comparison

# Works with any dict-expecting library
isinstance(doc, dict)                  # True
json.dumps(doc)                        # works

# Conversion
doc.to_dict()                          # deep conversion to plain Python dict

# Comments
doc.get_comment_inline("key")          # -> str | None
doc.get_comment_before("key")          # -> str | None
doc.set_comment_inline("key", text)
doc.set_comment_before("key", text)

# Sorting
doc.sort_keys()                        # alphabetical, in-place
doc.sort_keys(reverse=True)            # reverse alphabetical
doc.sort_keys(key=lambda k: len(k))    # custom key function on key strings
doc.sort_keys(recursive=True)          # also sort all nested mappings

YamlSequence

YamlSequence is a subclass of list. All standard list operations work directly:

# Standard list interface (inherited)
doc[0]                                 # get by index (negative indices supported)
doc[0] = value                         # set by index
del doc[0]                             # delete by index
value in doc                           # membership test
len(doc)                               # number of items
for item in doc: ...                   # iterate over items
doc.append(value)                      # add to end
doc.insert(idx, value)                 # insert before index
doc.pop()                              # remove & return last item
doc.pop(idx)                           # remove & return item at index
doc.remove(value)                      # remove first occurrence (ValueError if missing)
doc.extend(iterable)                   # append items from list or YamlSequence
doc.index(value)                       # index of first occurrence
doc.count(value)                       # number of occurrences
doc.reverse()                          # reverse in-place
doc == [1, 2, 3]                       # equality comparison

# Works with any list-expecting library
isinstance(doc, list)                  # True
json.dumps(doc)                        # works

# Conversion
doc.to_dict()                          # deep conversion to plain Python list

# Comments (addressed by integer index)
doc.get_comment_inline(idx)            # -> str | None
doc.get_comment_before(idx)            # -> str | None
doc.set_comment_inline(idx, text)
doc.set_comment_before(idx, text)

# Sorting (preserves comment metadata)
doc.sort()                             # natural order, in-place
doc.sort(reverse=True)
doc.sort(key=lambda v: len(v))         # custom key function on item values

Sorting preserves all comments — each entry or item carries its inline and before-key comments with it when reordered.

Running tests

The repo contains three test suites. You need Rust (nightly) and Python 3.12+ with uv. Python 3.12 is the minimum — YamlSequence subclasses list, which requires PyO3's extends = PyList support introduced in Python 3.12.

# 1. Clone with the yaml-test-suite submodule
git clone --recurse-submodules https://github.com/theyugin/yarutsk
cd yarutsk

# 2. Create a virtual environment and install dev dependencies
uv sync --group dev

# 3. Build the extension in dev (debug) mode
uv run maturin develop

# 4. Run the suites
uv run pytest tests/test_yarutsk.py -v          # core library tests
uv run pytest tests/test_sort.py -v             # key-ordering tests
uv run pytest tests/test_yaml_suite.py -q       # yaml-test-suite compliance

test_yaml_suite.py requires the yaml-test-suite submodule and PyYAML (both available after the steps above). Round-trip tests that fail due to YAML normalisation (flow→block, anchors, folded scalars) are marked xfail and do not count as failures.

Benchmarks

Benchmarks compare yarutsk against PyYAML and ruamel.yaml using pytest-benchmark:

uv sync --group benchmark
uv run pytest benchmarks/ -v --benchmark-min-rounds=10

ruamel.yaml is the closest analogue to yarutsk (it also preserves comments), so it is the primary point of comparison.

Internals

The scanner and parser are vendored from yaml-rust2 (MIT licensed) with one targeted modification: the comment-skipping loop in the scanner now emits Comment tokens instead of discarding them. Everything else — block/flow parsing, scalar type coercion, multi-document support — comes from yaml-rust2 unchanged. The builder layer wires those tokens to the data model, and a hand-written block-style emitter serialises it back out.

YamlMapping and YamlSequence are PyO3 pyclasses that extend Python's built-in dict and list types. A Rust inner field stores the full YAML data model (including comments); the parent dict/list is kept in sync on every mutation so that all standard Python operations work transparently.

Disclaimer

This library was created with Claude Code (Anthropic). The design, implementation, tests, and this README were written by Claude under human direction.

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

yarutsk-0.0.4.tar.gz (82.0 kB view details)

Uploaded Source

Built Distributions

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

yarutsk-0.0.4-cp314-cp314-win_amd64.whl (317.4 kB view details)

Uploaded CPython 3.14Windows x86-64

yarutsk-0.0.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (437.0 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

yarutsk-0.0.4-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (818.2 kB view details)

Uploaded CPython 3.14macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

yarutsk-0.0.4-cp313-cp313-win_amd64.whl (320.1 kB view details)

Uploaded CPython 3.13Windows x86-64

yarutsk-0.0.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (439.6 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

yarutsk-0.0.4-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (820.4 kB view details)

Uploaded CPython 3.13macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

yarutsk-0.0.4-cp312-cp312-win_amd64.whl (320.6 kB view details)

Uploaded CPython 3.12Windows x86-64

yarutsk-0.0.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (440.6 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

yarutsk-0.0.4-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (820.7 kB view details)

Uploaded CPython 3.12macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

File details

Details for the file yarutsk-0.0.4.tar.gz.

File metadata

  • Download URL: yarutsk-0.0.4.tar.gz
  • Upload date:
  • Size: 82.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for yarutsk-0.0.4.tar.gz
Algorithm Hash digest
SHA256 f9f3798af3726b6b7d100396e1d6cd33a6c1042868208fbc6c1a2830aa77a09f
MD5 4b4c611361302623f2404a2cc0ccf1de
BLAKE2b-256 a89253e0d63806e6f85992f8ea99ad5fa9f2f1dafba23c40c6a132c8a8de40a5

See more details on using hashes here.

Provenance

The following attestation bundles were made for yarutsk-0.0.4.tar.gz:

Publisher: ci.yml on theyugin/yarutsk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file yarutsk-0.0.4-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: yarutsk-0.0.4-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 317.4 kB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for yarutsk-0.0.4-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 033ca545bbf928606d16d0bcbe24167db0c16894f315b2afcfad9bc01222d6ea
MD5 e96ae510530b9bf0bb0a9d60e7964235
BLAKE2b-256 7a6c52b0a5dba97ed017a7d03ecf96d3098ef37f72bc8511fe8cd7dfaf998648

See more details on using hashes here.

Provenance

The following attestation bundles were made for yarutsk-0.0.4-cp314-cp314-win_amd64.whl:

Publisher: ci.yml on theyugin/yarutsk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file yarutsk-0.0.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for yarutsk-0.0.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0049660722910251b398fc6a1110067c8607f9a4b274ad54efc44793861a7cc3
MD5 f137feb61ef16f607451e55396c5317e
BLAKE2b-256 db2fe5a190ffd3f378a72d5a8844f66463a61754f04cb6f8a6684d075eb36490

See more details on using hashes here.

Provenance

The following attestation bundles were made for yarutsk-0.0.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: ci.yml on theyugin/yarutsk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file yarutsk-0.0.4-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for yarutsk-0.0.4-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 94635a4cecf7a0e17909dd083135a0668a744cd2b33a2c5b710625b282cb1ee4
MD5 3a0333ca2b0ffe792e8949668202371c
BLAKE2b-256 8b5fe99d4197a949ffcb0fbb0aa534369b15d8d36fee54ce2bc0109b95c4b47b

See more details on using hashes here.

Provenance

The following attestation bundles were made for yarutsk-0.0.4-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:

Publisher: ci.yml on theyugin/yarutsk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file yarutsk-0.0.4-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: yarutsk-0.0.4-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 320.1 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for yarutsk-0.0.4-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 c7e95697720dcae73e0a1736bb43dcbdd8fbe5133c4836edbfb1129e62316c9f
MD5 a43f93e26dbf865ea36f86139877941b
BLAKE2b-256 d8186d52b8df0eaf020659a082aa63d80293c55cdce997fb205b3d8fa79ab717

See more details on using hashes here.

Provenance

The following attestation bundles were made for yarutsk-0.0.4-cp313-cp313-win_amd64.whl:

Publisher: ci.yml on theyugin/yarutsk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file yarutsk-0.0.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for yarutsk-0.0.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 ad923109b39d1c3d5d0c023075f81275759008811bacaa124d8632cafe597da4
MD5 252339eb328f4e36526299c1f1e4fa08
BLAKE2b-256 d9d3af81153c03081954cdfdb1334bf514d7ad9faf5745504b59fd0b51ef471d

See more details on using hashes here.

Provenance

The following attestation bundles were made for yarutsk-0.0.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: ci.yml on theyugin/yarutsk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file yarutsk-0.0.4-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for yarutsk-0.0.4-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 a5bd21955db0d8d17b0d0405844a31cc98844aa6ca9772a65b9116fab59d0f8d
MD5 fcebdaa5fe80c3f251fa7a705790fb96
BLAKE2b-256 7710ee7fb4ee419b23ea0f9d71e912357c330b503a59f69d953058aad16d93c2

See more details on using hashes here.

Provenance

The following attestation bundles were made for yarutsk-0.0.4-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:

Publisher: ci.yml on theyugin/yarutsk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file yarutsk-0.0.4-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: yarutsk-0.0.4-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 320.6 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for yarutsk-0.0.4-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 2dcac43cfc4cc1d47aaee384796c8253d63c61289aea72dba10b60d7b7e3b6e3
MD5 a877519d1225927c27a08bac8889d0de
BLAKE2b-256 29ed2dcba7be6bdd8beeaf25aa96fc6e53eb7635223b451871d343737b145d81

See more details on using hashes here.

Provenance

The following attestation bundles were made for yarutsk-0.0.4-cp312-cp312-win_amd64.whl:

Publisher: ci.yml on theyugin/yarutsk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file yarutsk-0.0.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for yarutsk-0.0.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 7193e6b73478ab5b8bad55f6c78da574c998f383eb5ad1eb18f713385ce54cc8
MD5 64dbe569cb42f36d7be39512b0b880b6
BLAKE2b-256 7a46d5e95dc7ebcc3fb17fa78a02473dbb6359d4bdaa032127d5b687466646dd

See more details on using hashes here.

Provenance

The following attestation bundles were made for yarutsk-0.0.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: ci.yml on theyugin/yarutsk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file yarutsk-0.0.4-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for yarutsk-0.0.4-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 66f9bdd6bdf9092dae2db9c9eddeb5bab487fa67a1cee5953736889d1d6acfc1
MD5 3fc59a5f4ec39844369ff02112be16d7
BLAKE2b-256 969a1dcf76e28445d35153983df340c0e6040df820320bcb4091dde70cc2c9ba

See more details on using hashes here.

Provenance

The following attestation bundles were made for yarutsk-0.0.4-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:

Publisher: ci.yml on theyugin/yarutsk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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