Skip to content

Migrating from ruamel.yaml

ruamel.yaml is the library people reach for when they need to preserve comments and formatting through an edit. YAMLRocks offers that same round-trip fidelity, but it is Rust-backed and dramatically faster, it returns a byte-for-byte round trip when you do not modify the document, and it adds native !include resolution and a JSON-Schema validator. This page maps ruamel’s round-trip API onto YAMLRocks’s, shows the edit workflow side by side, and is honest about what ruamel still does that YAMLRocks does not.

ruamel.yamlYAMLRocks
YAML() instance with typ="safe" / "rt"options on loads / dumps
yaml.load(stream)yamlrocks.loads(data) / yamlrocks.load(path)
yaml.dump(data, stream)yamlrocks.dumps(data) / yamlrocks.dump(data, path)
CommentedMap / CommentedSeqYAMLRocksDocument + YAMLRocksDocumentView
round-trip preserves commentsOPT_ROUND_TRIP, byte-for-byte when unmodified
pure PythonRust extension

ruamel configures behavior on a YAML() instance; YAMLRocks takes options per call. For ordinary safe loading, the translation is direct. The ruamel block here is illustrative (it needs ruamel installed), while the YAMLRocks block runs as written:

ruamel.yaml
from ruamel.yaml import YAML
yaml = YAML(typ="safe")
data = yaml.load("name: app\nport: 8080")
# yamlrocks
import yamlrocks
source = """
name: app
port: 8080
"""
data = yamlrocks.loads(source)
# {'name': 'app', 'port': 8080}

ruamel writes to a stream you provide. YAMLRocks returns bytes from dumps (decode for text), or writes to a path or stream through yamlrocks.dump:

ruamel.yaml
import sys
yaml.dump(data, sys.stdout)
# yamlrocks
import sys
import yamlrocks
sys.stdout.write(yamlrocks.dumps({"name": "app", "port": 8080}).decode())
# name: app
# port: 8080

This is the heart of a ruamel migration. ruamel’s default round-trip mode returns CommentedMap/CommentedSeq objects that you mutate in place and dump back. YAMLRocks returns a YAMLRocksDocument with the same workflow: index into it, assign, and re-emit.

ruamel.yaml
from ruamel.yaml import YAML
import sys
yaml = YAML() # typ="rt" is the default
doc = yaml.load("# config\nname: app # service\nport: 8080\n")
doc["port"] = 9090
yaml.dump(doc, sys.stdout)

The YAMLRocks equivalent loads with OPT_ROUND_TRIP, edits the same way, and re-emits with to_yaml:

import yamlrocks
doc = yamlrocks.loads(
b"# config\nname: app # service\nport: 8080\n",
option=yamlrocks.OPT_ROUND_TRIP,
)
doc["port"] = 9090
print(doc.to_yaml().decode())
# # config
# name: app # service
# port: 9090

The comment survives the edit and only the changed line is re-rendered.

ruamel exposes comments through its .ca (comment attribute) API, which is powerful but intricate to drive directly. YAMLRocks preserves comments automatically during a round trip: editing a value keeps the comments around it intact, and you rarely need to touch them at all. When you do, every YAMLRocksNode has a writable comment (the inline # ...) and comment_before (the standalone line(s) above a key), so you can read, set, or clear them by name:

import yamlrocks
doc = yamlrocks.loads(b"name: app\nport: 8080\n", option=yamlrocks.OPT_ROUND_TRIP)
doc.node["port"].comment = "the listen port"
doc.node["name"].comment_before = "service identity"

A round-trip keeps comments byte-for-byte, and editing a value preserves the spacing around it too: the comment and its gap stay put while only the value changes. The sole exception is a comment you set through the comment API, which uses a single space (a freshly written comment has no original spacing):

import yamlrocks
doc = yamlrocks.loads(
b"name: app # spacing is kept\nport: 8080\n",
option=yamlrocks.OPT_ROUND_TRIP,
)
doc["name"] = "web"
doc.to_yaml()
# b'name: web # spacing is kept\nport: 8080\n'

Things ruamel does that YAMLRocks maps differently

Section titled “Things ruamel does that YAMLRocks maps differently”
  • Indentation control (yaml.indent(mapping=..., sequence=..., offset=...)): use OPT_INDENT_2 (the default) or OPT_INDENT_4 on dumps. Round-trip output preserves the source document’s own indentation rather than imposing a setting.
  • Preserve quotes (preserve_quotes=True): always on in YAMLRocks’s round-trip mode. Quoting styles are kept as written, with no flag to set.
  • Merge keys (<<): resolved by default in yamlrocks.loads, the same as ruamel.
  • YAML version: both libraries default to YAML 1.2. For 1.1 documents, read with OPT_YAML_1_1 or normalize once with the upgrade helper.

What ruamel still does that YAMLRocks does not

Section titled “What ruamel still does that YAMLRocks does not”

Be honest with yourself about these before migrating:

  • Foot comments. YAMLRocks scripts inline and leading comments per node (comment / comment_before), and these work on mapping values, keys, and sequence items, but a trailing/foot comment block at the end of a collection is preserved through a round-trip rather than writable through the node API.
  • Building a commented document from nothing. YAMLRocks edits comments on a loaded document (including keys you add to it), but there is no constructor for a fresh round-trip document with no parsed source, the way ruamel can assemble a fully commented CommentedMap in memory.
  • Speed. Against ruamel, YAMLRocks parses on the order of 85 to 135 times faster and serializes on the order of 155 to 210 times faster in release-build benchmarks. See Performance.
  • Native includes. Resolve and write back !include files directly, far faster than a Python constructor (Includes).
  • Schema validation. Validate during the parse with line-numbered errors (Schema validation).
  • Source locations. OPT_ANNOTATED attaches __line__ and __column__ to every node (Annotated mode).