Skip to main content

pythonizeyaml

English | 简体中文

pythonizeyaml is a YAML library with a PyYAML-compatible API and a lossless round-trip engine implemented in Rust. Loading and dumping an untouched document reproduces its source text, including comments, blank lines, indentation, scalar styles, document markers, anchors, and multi-document layout.

The parser and emitter are compiled through PyO3 and Maturin. There is no Python YAML runtime dependency.

Comparison with Other YAML Libraries

The table below compares pythonizeyaml 0.5.0 with PyYAML, yamltrip, and ruamel.yaml.

Area pythonizeyaml PyYAML yamltrip ruamel.yaml
Primary purpose PyYAML-style YAML API with lossless round trips General YAML serializer/parser Format-preserving YAML file editor and query API General YAML with strong round-trip support
Main API load, load_all, dump, dump_all, safe_*, full_*, unsafe_*, YAML Same function-oriented API, plus lower-level scanner/parser APIs load/loads return Document; immutable edits plus Editor Class-oriented YAML() API; legacy top-level functions are deprecated
Document API load/load_all return mutable Document objects; load_document/load_documents and read_document/read_documents are explicit spellings; style editing on the values themselves No mutable document wrapper; use Python values or low-level nodes/events Document/Editor centered editing and query API YAML().load() returns mutable CommentedMap/CommentedSeq documents
Return model Document roots (dict/list subclasses); nested standard Python scalars, RoundTripMap/List/Set, Decimal, Tagged Plain Python objects and YAML AST/event/token objects Document wrapper around plain Python values CommentedMap, CommentedSeq, scalar subclasses
Backend Custom Rust parser/emitter through PyO3 Pure Python plus optional LibYAML C extension tree-sitter-yaml through Rust yamlpath/yamlpatch Python plus optional C parser
Unchanged round trip Exact source text, including comments, blanks, styles, markers, and line layout No preservation guarantee; output is regenerated Preserves source and format while patching edits Preserves comments and styles in round-trip mode, but output remains emitter-controlled
Comments and whitespace Preserved exactly for unchanged documents Lost or normalized Preserved Preserved, generally
Indentation and flow style Original formatting retained; explicit IndentConfig can override Regenerated according to dumper settings Preserved Retained in normal round-trip workflows, with indentation configurable
Scalar quotes/styles Preserved, including redundant quotes and block styles Rewritten Preserved as raw source Preserved, including preserve_quotes support
Mutation model Mutate loaded Document objects (dict-like/list-like); unchanged bytes are retained Mutate plain objects, then regenerate Immutable Document methods or mutable Editor; minimal patches Mutate CommentedMap/CommentedSeq objects
Style editing API values carry style, collection_style, chomping, comments, tags, anchors; set(...) applies fields atomically Dumper options and low-level representers; no source style editing API Path/editor operations preserve selected source formatting Object attributes and YAML emitter options expose round-trip style controls
Structural edit fidelity Local edits are patched; replaced/new subtrees may be canonically emitted Full regeneration Designed for minimal structural patches Strong preservation of attached comments and formatting
YAML schema PyYAML-compatible YAML 1.1 resolver by default (yes/no booleans, 010 octal, 1:30 sexagesimal); a %YAML 1.2 directive switches to the YAML 1.2 core schema YAML 1.1-oriented resolver by default Focused on editable YAML values; tags are not interpreted YAML 1.2 by default
Large integers Arbitrary-precision Python int Arbitrary-precision Python int May lose precision outside signed 64-bit range Arbitrary-precision Python int
Decimal values Exact binary64-representable decimals become float; others become Decimal; !!decimal forces Decimal Normally float; custom constructors needed for Decimal Basic scalar conversion; no special big-decimal support Normally float; custom representers/constructors needed for Decimal
Unknown/application tags Returned as Tagged; never executed Depends on loader/constructors; unsafe loaders can construct Python objects Not interpreted Preserved; constructors can define behavior
Safe loading safe_load rejects non-standard tags safe_load uses SafeLoader No separate safe/unsafe object-construction model YAML(typ="safe") or safe loading APIs
Anchors and aliases Parsed, preserved, resolved to shared Python objects Resolved; dumper may emit anchors Detected but not resolved during extraction Resolved and preserved
Multi-document streams Supported Supported Not supported Supported
Custom classes No constructor/representer plugin API YAMLObject, constructors, representers No custom class serialization Constructors, representers, and plug-ins
Events/nodes No public scan/parse/event API Full scanner, parser, composer, node APIs Tree/query/path API instead Full event/node APIs
Errors PyYAML-compatible hierarchy PyYAML hierarchy YAMLTripError hierarchy ruamel-specific YAMLError hierarchy
Encoding UTF-8 input through str/bytes/streams Several YAML encodings depending on reader UTF-8 only Configurable, broad encoding support
Maturity New 0.5.0 custom implementation Very mature, widely deployed Newer focused library, version 0.4.x Very mature round-trip implementation

The biggest practical distinctions:

  • Compared with PyYAML: pythonizeyaml keeps source layout by default, but is much younger and lacks PyYAML's mature event API, custom constructor ecosystem, encoding breadth, and long-term compatibility history. Unlike unsafe PyYAML loaders, it does not execute !!python/... tags.
  • Compared with yamltrip: yamltrip is optimized around editing and querying YAML files through Document/Editor; it explicitly does not support multi-document streams, tag interpretation, anchor resolution, or arbitrary-size integer preservation. pythonizeyaml provides a PyYAML-style data API and broader YAML semantics, but its structural-edit patching is less specialized than yamltrip's.
  • Compared with ruamel.yaml: ruamel is the mature reference for mutable comment-preserving YAML objects. pythonizeyaml instead promises exact source replay for unchanged documents and uses Rust-native parsing, Decimal precision policy, and Tagged values. It does not yet offer ruamel's class registration, plug-in ecosystem, or depth of YAML conformance coverage.

Sources: PyYAML repository, yamltrip README, and ruamel.yaml repository.

Requirements

  • Python 3.10 or newer
  • Rust 1.83 or newer when building from source
  • Maturin 1.15 or newer for extension development

Installation

pip install pythonizeyaml

Optional Pydantic integration: pip install "pythonizeyaml[pydantic]" (adds YAMLModel); add pip install "pythonizeyaml[pydantic-settings]" for YAMLSettings.

For a source checkout:

poetry install
poetry run maturin develop

Quickstart

import pythonizeyaml as yaml

document = yaml.load(open("config.yaml", encoding="utf-8"))
document["service"]["port"] = 9090
text = yaml.dump(document)

Only the changed scalar is rewritten. Comments and formatting elsewhere remain byte-identical. Pass a writable stream as the second argument to write directly:

with open("config.yaml", "w", encoding="utf-8") as handle:
    yaml.dump(document, handle)

Numeric Resolution

Integers use Python's arbitrary-precision int. Decimal and exponent literals are compared exactly with IEEE 754 binary64:

from decimal import Decimal
import pythonizeyaml as yaml

assert type(yaml.load("value: 1.5\n")["value"]) is float
assert type(yaml.load("value: 0.1\n")["value"]) is Decimal
assert type(yaml.load("value: 1e400\n")["value"]) is Decimal

Use !!float to force float or !!decimal to force Decimal.

Tags and Safety

The core and common standard YAML tags are resolved, including !!binary, !!timestamp, !!set, and merge keys. Unknown application tags are returned as pythonizeyaml.Tagged(tag, value) and preserve their spelling during round trips.

Use safe_load or safe_load_all for untrusted YAML. These functions reject non-standard tags instead of constructing arbitrary Python objects.

value = yaml.safe_load("enabled: true\n")

full_load/full_load_all return plain data while tolerating unknown tags (they come back as inert Tagged values), and unsafe_load/unsafe_load_all are documented aliases of them. Like every loader in this library, they never construct arbitrary Python objects.

API

The module exposes:

  • load, load_all, dump, dump_all
  • safe_load, safe_load_all, safe_dump, safe_dump_all
  • full_load, full_load_all, unsafe_load, unsafe_load_all
  • round_trip_load, round_trip_load_all, round_trip_dump, round_trip_dump_all
  • YAML, SafeYAML, IndentConfig, DEFAULT_CONFIG, Tagged
  • Document, DocumentStream, and Comments
  • load_document, load_documents, read_document, and read_documents
  • ScalarStyle, CollectionStyle, Chomping, and SourceSpan
  • YAMLError and its PyYAML-compatible subclasses
  • YAMLModel, and with pydantic-settings also YAMLSettings (optional Pydantic integration)

Loader=, Dumper, sort_keys, default_flow_style, allow_unicode, and encoding are accepted for migration compatibility and ignored where they conflict with lossless output.

Advanced Style Documents

load(), load_all(), and load_document() all return mutable, style-aware Document objects whose values carry the styling API directly. For explicit control over comments, scalar styles, collection styles, tags, anchors, aliases, directives, and document markers, style the values you read:

from pythonizeyaml import ScalarStyle, load_document

document = load_document("name: example\nitems:\n  - one\n  - two\n")
document["name"].style = ScalarStyle.DOUBLE
document["name"].comments.before = ["# service name"]
document["items"].collection_style = "flow"

text = document.dump()

load_document() returns one mutable Document; load_documents() returns a list-like DocumentStream. Collection roots load as DocumentMapping or DocumentSequence (dict/list subclasses) and scalar roots as DocumentScalar. Every value inside a document is a round-trip wrapper — a dict/list subclass, or a subclass of the scalar's own type — that compares and hashes like a plain value. Assigned scalars are wrapped and plain dict/list values are converted, so new subtrees are styleable immediately. Documents edit like their wrapped dict/list: document["key"] = value, del document["key"], document["items"].append(x). Use Document.new() to create styled documents from scratch.

Values expose path, value, span, style, collection_style, chomping, block_indent_indicator, tag, anchor, and comments. The set(...) method applies multiple fields atomically. Style changes are validated before mutation; see StyleError, PathError, and AliasError for failures. bool and None values are plain (they cannot be subclassed) and are the only loaded scalars without this API.

For repository setup, testing, and contribution conventions, see CONTRIBUTING.md.

Indentation Configuration

IndentConfig(mapping=2, sequence=2, offset=0, width=80, preserve_quotes=True) controls newly created data and explicit re-layout requests. Loaded documents retain their original layout unless an override is supplied.

Development

cargo test --manifest-path rust/Cargo.toml --no-default-features
poetry run maturin develop
poetry run pytest
poetry build

Tests run against tests/fixtures/; add malformed inputs under tests/fixtures/invalid/.

Root Scalar Documents

Root scalars load as DocumentScalar, a Document wrapper that keeps source metadata and scalar styles (quotes, block headers) but is not a str/int subclass. It compares equal to the wrapped value and coerces through str(), int(), float(), and bool(); nested scalars are ordinary Python values with their original style and formatting retained.

Metadata

Release files for pythonizeyaml 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pythonizeyaml 0.5.0
File Size Uploaded
pythonizeyaml-0.5.0.tar.gz 106.9 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for pythonizeyaml 0.5.0
File Interpreter ABI Platform
pythonizeyaml-0.5.0-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
pythonizeyaml-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details
pythonizeyaml-0.5.0-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details

Total release size: 1.6 MB

Release files / pythonizeyaml-0.5.0.tar.gz

Download URL pythonizeyaml-0.5.0.tar.gz
Size 106.9 kB
Tags Source
SHA-256 checksum
How to use checksums
00f5372b7c6bee63a927c28f2131a72db3a60b342e986a523a42054b583a9270
BLAKE2b-256 checksum
How to use checksums
e07babea4143a1dd4440f863b3f414e6a6cb4cfcce2d841bfa350695036e10ac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.

Transparency log

Release files / pythonizeyaml-0.5.0-cp310-abi3-win_amd64.whl

Download URL pythonizeyaml-0.5.0-cp310-abi3-win_amd64.whl
Size 417.9 kB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
8d7a771d2f450f576d54aababd06fb0ab438895f83ee45a4831228255ef19c2e
BLAKE2b-256 checksum
How to use checksums
a697874da75d717436287648561af30cfde767b5adbc95f60c5ff39f5280ff92
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.

Transparency log

Release files / pythonizeyaml-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL pythonizeyaml-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 543.6 kB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
8bf6893202725f516bc92fa77d6a10814e26bc3cccb03c14162ff97a1faeb527
BLAKE2b-256 checksum
How to use checksums
813c30fa8c656ffefb4e2c5da03bbc310562ed501f22349974e8c2232b76de37
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.

Transparency log

Release files / pythonizeyaml-0.5.0-cp310-abi3-macosx_11_0_arm64.whl

Download URL pythonizeyaml-0.5.0-cp310-abi3-macosx_11_0_arm64.whl
Size 502.1 kB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
071fb7e14cc2e587eff7b074e89d259c1a6e7d044c175fbe0c98a78ece49fc40
BLAKE2b-256 checksum
How to use checksums
e616d91c971ef66d4aa6b81702064002809ec4becc83575c2cfeee1075f2649a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.

Transparency log

Release history Release notifications | RSS feed

0.6.1

4 release files

This release

0.5.0 This release

4 release files

0.4.0

4 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page