ProvenPin Install

Round-trip edit YAML with ruamel.yaml keeping comments and key order: working versions (tested 2026-10-16)

Load YAML with ruamel.yaml round-trip mode, mutate scalars, sequences and inserted keys in place, then dump it back with comments, quotes and key order intact.

passed6 passed · 0 failed2026-10-16 09:58 UTC
Status
passed
Last passed
2026-10-16 09:58 UTC
Tests
6 / 6
Language
Python
Runtime
Python 3.13.16
pinned versions2
ruamel.yaml@0.19.1pytest@9.1.1
run it
uv venv -q .venv && uv pip install -q --python .venv/bin/python -r requirements.txt
.venv/bin/python -m pytest -q
test environment
Python 3.13.16
linux 6.17.0-1022-azure
x64
runner: github-actions 38883899161

The code

Exactly the files that passed. Your agent can pull them with get_recipe("ruamel-yaml-roundtrip-comments") (install), or see them on GitHub.

requirements.txt
ruamel.yaml==0.19.1
pytest==9.1.1
config.py
from io import StringIO

from ruamel.yaml import YAML


class ConfigEditor:
    """Round-trip YAML editor that keeps comments, quotes and key order."""

    def __init__(self, preserve_quotes: bool = True):
        self.yaml = YAML()
        self.yaml.preserve_quotes = preserve_quotes
        self.yaml.indent(mapping=2, sequence=4, offset=2)

    def load(self, text: str):
        return self.yaml.load(text)

    def dump(self, data) -> str:
        out = StringIO()
        self.yaml.dump(data, out)
        return out.getvalue()

    def add_setting(self, data, key: str, value, after: str, comment: str | None = None):
        data.insert(list(data.keys()).index(after) + 1, key, value)
        if comment is not None:
            data.yaml_set_comment_before_after_key(key, before=comment)
        return data
tests/test_config.py
from io import StringIO

import pytest
from ruamel.yaml import YAML
from ruamel.yaml.comments import CommentedMap
from ruamel.yaml.constructor import DuplicateKeyError

from config import ConfigEditor

SAMPLE = """\
# service.yaml - edited by hand
name: my-service     # shown in dashboards
replicas: 3

# networking
network:
  host: "10.0.0.1"
  ports:
    - 80
    - 443
"""


@pytest.fixture
def editor():
    return ConfigEditor()


def test_edit_scalar_keeps_comments_and_order(editor):
    data = editor.load(SAMPLE)
    data["replicas"] = 5
    out = editor.dump(data)
    assert "# service.yaml - edited by hand" in out
    assert "# shown in dashboards" in out
    assert out.index("name:") < out.index("replicas:") < out.index("network:")
    assert "replicas: 5" in out


def test_preserve_quotes(editor):
    data = editor.load(SAMPLE)
    data["replicas"] = 5
    assert '"10.0.0.1"' in editor.dump(data)
    plain = ConfigEditor(preserve_quotes=False)
    assert '"10.0.0.1"' not in plain.dump(plain.load(SAMPLE))


def test_sequence_indent_needs_explicit_config(editor):
    data = editor.load(SAMPLE)
    data["network"]["ports"].append(8080)
    assert "    - 8080\n" in editor.dump(data)

    default = YAML()
    plain = default.load(SAMPLE)
    plain["network"]["ports"].append(8080)
    out = StringIO()
    default.dump(plain, out)
    assert "  - 8080\n" in out.getvalue()


def test_insert_key_at_position_with_comment(editor):
    data = editor.load(SAMPLE)
    editor.add_setting(data, "owner", "platform", after="name", comment="release owner")
    out = editor.dump(data)
    assert "# release owner\nowner: platform" in out
    assert out.index("name:") < out.index("owner:") < out.index("replicas:")
    assert isinstance(data, CommentedMap)


def test_duplicate_keys_are_rejected(editor):
    with pytest.raises(DuplicateKeyError):
        editor.load("a: 1\n# oops\na: 2\n")


def test_safe_loader_is_not_round_trip():
    data = YAML(typ="safe").load(SAMPLE)
    assert not isinstance(data, CommentedMap)
    out = StringIO()
    YAML(typ="safe").dump(data, out)
    assert "# service.yaml - edited by hand" not in out.getvalue()
pytest.ini
[pytest]
pythonpath = .

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.