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.6.1 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.6.1 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)

Command Line

Installing the wheel also installs a yaml command for quick path-based edits from the shell:

yaml config.yaml get service.port          # 8080
yaml config.yaml set service.port 9090     # rewrites only that scalar
yaml config.yaml set tls.enabled true      # creates the missing chain
yaml config.yaml del service.debug

Paths are dot-separated (foo.bar.jay); a numeric segment addresses an item of the sequence at that point (servers.0.host). set creates missing intermediate mappings automatically, and values are interpreted as YAML — true is a boolean, 123 an integer, null is null — so quote them ("'123'") to force a string. Everything the command does not touch keeps its original comments, indentation, and scalar styles. See the CLI chapter for details.

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.6.1

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.6.1
File Size Uploaded
pythonizeyaml-0.6.1.tar.gz 114.7 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for pythonizeyaml 0.6.1
File Interpreter ABI Platform
pythonizeyaml-0.6.1-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
pythonizeyaml-0.6.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details
pythonizeyaml-0.6.1-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.6.1.tar.gz

Download URL pythonizeyaml-0.6.1.tar.gz
Size 114.7 kB
Tags Source
SHA-256 checksum
How to use checksums
09f51e08a66a0bf29ef7c0345770162b9275a708fd00c7f39f4fee953da722d9
BLAKE2b-256 checksum
How to use checksums
c62c2e54b4484f6585bb1da9bad6e60f6456a1e51c6d0eedfb794e40ee104c71
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 Oct 3, 2026.

Transparency log

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

Download URL pythonizeyaml-0.6.1-cp310-abi3-win_amd64.whl
Size 433.4 kB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
43d06e13ae398ccfb4b7525b2fd0be21f08c0f1fb99750032692fd418f144c7d
BLAKE2b-256 checksum
How to use checksums
cc90cf51daa6fb2b5d1b5abbc1a1f6709bf4b9b4e1ebdb612b999ee7551deab3
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 Oct 3, 2026.

Transparency log

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

Download URL pythonizeyaml-0.6.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 553.9 kB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
421a335b713899711dd73d8a30379d4141373c40d6a3f8efd692c3ba17457ee1
BLAKE2b-256 checksum
How to use checksums
9b8cc4a5b3b14a9b161c59e9c0dedc2fb7463e6bc10db7dbc8d8ed8482e7b872
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 Oct 3, 2026.

Transparency log

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

Download URL pythonizeyaml-0.6.1-cp310-abi3-macosx_11_0_arm64.whl
Size 514.1 kB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
f62d191c42b2254dab85bc4499271f12bf9ba3ed8b804d11dc36d3e8d22f0fb5
BLAKE2b-256 checksum
How to use checksums
c26e9f1c67675e98cd3bdad3d1d5e365aecda1efcd870f7419c68b63d66b38fe
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 Oct 3, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.6.1 This release

4 release files

0.5.0

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