Releases: frenck/YAMLRocks
Release list
v0.6.1: No stone left behind 🪨
🪨 No stone left behind
A YAML mapping can carry the << merge key more than once, and most parsers accept it, merging every one in document order. YAMLRocks did too, right up until the values were something it could not merge itself, like a !include the host resolves later. Then the repeated << keys collapsed into a single slot and all but one quietly vanished before the host ever saw them. No error, just missing data.
v0.6.1 keeps them all. Repeated deferred << values now collect into a list in document order, the same shape the <<: [a, b] sequence form already produced, and the host runs its own merge over them. A single << still resolves exactly as before, so nothing that worked breaks.
That is the whole release: one bug, turned up by a real config, fixed and pinned with tests across every decode path (fast, annotated, includes, round-trip). A quoted "<<" stays a literal key, never swept into the list. Round-trip stays byte-for-byte.
pip install yamlrocks📚 Docs: https://yaml.rocks
Same rock. Nothing dropped. 🪨
../Frenck
Blogging my personal ramblings at frenck.dev
What's changed
🐛 Bug fixes
v0.6.0: Sharper edges 🪨
🪨 Sharper edges
v0.5.0 taught the round-trip cursor to point at any node by path. v0.6.0 is about speed, and about the surface you reach for to get it.
The speed came from measuring honestly. We had been benchmarking against payloads we wrote ourselves, and they flattered us. Pointed at 245 MB of real configuration files instead, the profiler lit up! All fixed, and a new just bench-corpus keeps us honest against real data from here on. YAMLRocks stays more than 10x faster than PyYAML's C loader, now measured on files people actually have.
The surface got a pass too, and two changes break. The dump-side tag registry is now serializers=, keyed by Python type, so it no longer shares a name with the load-side tags=, keyed by YAML tag, that does the opposite job. And the null_style= keyword on dumps is gone; null rendering is chosen with the OPT_NULL_AS_KEYWORD / OPT_NULL_AS_TILDE flags, one way instead of two. Both are quick renames, and the migration is in the changelog below.
New capability landed as well: opt-in PyYAML-style timestamp resolution (OPT_TIMESTAMPS, off by default), writable foot comments through node.comment_after, a much wider slice of JSON Schema (pattern, multipleOf, tuple items, and more), and async_loads_all to finish the async family.
And the usual long tail of correctness got shorter, a stack of parser and emitter bugs turned up by fuzzing and a real-world corpus audit, each fixed and pinned with a test. Round-trip stays byte-for-byte.
pip install yamlrocks📚 Docs: https://yaml.rocks
Same rock. Sharper edges. 🪨
../Frenck
Blogging my personal ramblings at frenck.dev
What's changed
🚨 Breaking changes
- ✨ Rename the dump-side tags= registry to serializers= @frenck (#222)
- ✨ Drop the null_style= dump kwarg in favor of the null-style flags @frenck (#223)
✨ New features
- ✨ Expand JSON Schema keyword support (pattern, multipleOf, tuple items, and more) @frenck (#190)
- ✨ Add writable foot comments via node.comment_after @frenck (#213)
- ✨ Add opt-in PyYAML-style timestamp resolution @frenck (#216)
- ✨ Resolve timestamps in round-trip mode under OPT_TIMESTAMPS @frenck (#218)
- ✨ Add async_loads_all to complete the async load family @frenck (#221)
🐛 Bug fixes
- 👷 Ignore zizmor impostor-commit on the pinned dtolnay toolchain @frenck (#161)
- 🐛 Make the PyYAML compat shim resolve scalars like PyYAML @frenck (#173)
- 🐛 Raise a YAMLRocksError, not a bare ValueError, on malformed input encoding @frenck (#175)
- 🐛 Keep leading-zero sexagesimal values as strings under YAML 1.1 @frenck (#174)
- 🐛 Emit compact scientific notation for large/small floats in to_json @frenck (#178)
- 🐛 Reject a lone-surrogate str in dumps instead of emitting U+FFFD @frenck (#176)
- 🐛 Preserve Decimal precision in dumps instead of routing through f64 @frenck (#177)
- 🐛 Clear anchors between documents in the implicit-document path @frenck (#181)
- 🐛 Preserve an explicit '?' mapping key on round-trip re-emit @frenck (#183)
- 🐛 Quote timestamp strings in a YAML 1.1 / PyYAML-compat dump @frenck (#179)
- 🐛 Parse an empty flow-mapping key as null instead of swapping key and value @frenck (#180)
- 🐛 Catch Python-equal numeric duplicate keys under OPT_DUPLICATE_KEYS_ERROR @frenck (#182)
- 🐛 Canonicalize a verbatim tag for handlers and passthrough @frenck (#184)
- 🐛 Guard against orphaning an alias when deleting an anchor target @frenck (#185)
- 🐛 Apply merge keys on the AST data paths, not just the fast path @frenck (#186)
- 🐛 Apply merge keys before schema validation @frenck (#188)
- 🐛 Quote an edited flow-unsafe scalar inside a flow collection @frenck (#189)
- 🐛 Order merged mapping keys by source position on the fast path @frenck (#193)
- 🐛 Validate anchors and aliases on the composer paths too @frenck (#194)
- 🐛 Use the last value of a duplicate key in a merge source @frenck (#195)
- 🐛 Check integer multipleOf exactly instead of via a lossy float @frenck (#196)
- 🐛 Sort non-string mapping keys under OPT_SORT_KEYS @frenck (#197)
- 🐛 Drop a null merge value on the composer paths, matching the fast path @frenck (#198)
- 🐛 Strip underscore separators from a big int in the schema numeric checks @frenck (#199)
- 🐛 Report file on an annotated load(path) without includes @frenck (#202)
- 🐛 Reject non-printable control characters in the input stream @frenck (#203)
- 🐛 Read a tagged empty block-sequence entry as an empty node @frenck (#205)
- 🐛 Reject an integer with more than one leading sign @frenck (#207)
- 🐛 Resolve a tag on an empty node in the AST-to-Python path @frenck (#206)
- 🐛 Escape C1 controls and non-characters, and fuzz the include engine @frenck (#212)
- 🐛 Keep a nested final-block foot comment at its indent on edit @frenck (#215)
🚀 Enhancements
- ⚡ Speed up loads: bulk space skipping and right-sized event reserve @frenck (#169)
- ⚡ Check the stack guard every eighth level, pre-size the key cache @frenck (#171)
- ⚡️ Slim annotated strings with slots and borrow node metadata @frenck (#201)
- ⚡ Borrow single-quoted scalars instead of copying char by char @frenck (#224)
- ⚡ Borrow double-quoted scalars instead of copying char by char @frenck (#225)
- ⚡ Bulk-scan quoted-scalar content instead of walking char by char @frenck (#226)
- ⚡ Share the interned-key cache across a multi-document stream @frenck (#227)
- ⚡ Find the single-quoted scalar end with SIMD memchr @frenck (#228)
- 👷 Benchmark loads/dumps throughput across the real-world corpus @frenck (#230)
- ⚡ Bulk-copy block scalar content lines instead of char by char @frenck (#231)
🧰 Maintenance
- 👷 Ignore zizmor impostor-commit on the pinned dtolnay toolchain @frenck (#161)
- 👷 Remove the sole-owner CODEOWNERS so write collaborators can merge @frenck (#160)
- ⬆️ Update gcr.io/oss-fuzz-base/base-builder-rust:latest Docker digest to cf0c9d5 @renovate[bot] (#162)
- ⬆️ Update real-world corpus submodules @renovate[bot] (#163)
- ✅ Pin that a self-referential alias is rejected, not cyclic @frenck (#187)
- ✅ Add a yamlrocks-vs-PyYAML differential oracle @frenck (#204)
- 🐛 Escape C1 controls and non-characters, and fuzz the include engine @frenck (#212)
📚 Documentation
- 📝 Document the expanded JSON Schema keyword support @frenck (#191)
- 📝 Document merging an included file with the << merge key @frenck (#192)
- 📊 Add cross-library comparison benchmark charts to the docs @frenck (#200)
- 📝 Scope the round-trip byte-for-byte promise to UTF-8 @frenck (#209)
- 📊 Add comparison pages for the rest of the YAML ecosystem @frenck (#210)
- 📝 Add a YAML/JSON recipe and llms.txt for AI tooling @frenck (#211)
- 📝 Note the timestamp resolution differences in the comparisons @frenck (#217)
- 📝 Correct ruamel migration doc: foot comments are writable @frenck (#220)
- 📝 Refresh benchmark charts and numbers for the current build @frenck (#232)
⬆️ Dependency updates
15 changes
- ⬆️ Update python:3.14-slim Docker digest to b877e50 @renovate[bot] (#156)
- ⬆️ Update gcr.io/oss-fuzz-base/base-builder-rust:latest Docker digest to cf0c9d5 @renovate[bot] (#162)
- ⬆️ Update real-world corpus submodules @renovate[bot] (#163)
- ⬆️ Update dependency astro to v7.0.4 @renovate[bot] (#159)
- ⬆️ Update dependency rust-just to v1.55.1 @renovate[bot] (#158)
- ⬆️ Lock file maintenance @renovate[bot] (#157)
- ⬆️ Update dependency astro to v7.0.5 @renovate[bot] (#165)
- ⬆️ Update dependency ty to v0.0.56 @renovate[bot] (#167)
- ⬆️ Update dependency sharp to v0.35.3 @renovate[bot] (#166)
- ⬆️ Update dependency @astrojs/starlight to v0.41.2 @renovate[bot] (#164)
- ⬆️ Update dependency typing-extensions to v4.16.0 @renovate[bot] (#168)
- ⬆️ Update github/codeql-action action to v4.36.3 @renovate[bot] (#170)
- ⬆️ Update dependency @astrojs/starlight to v0.41.3 @renovate[bot] (#208)
- ⬆️ Upda...
v0.5.0: X marks the spot 🪨
🪨 X marks the spot
Round-trip mode has always known where every node came from. v0.5.0 makes that reachable by data path.
document.locate(["servers", 1, "port"]) walks a path of mapping keys and list indices and hands back the node at that location, scalar leaves included, with its line, column, file, and exact range. Item access cannot do this: it unwraps a scalar to its bare value, leaving nowhere to hang a position. locate always returns a positioned handle, so a tool that validates the loaded data and reports a failure by its path into that data can turn the path into an exact file:line:column, right down to a leaf, and follow it through !include boundaries to the file the value actually lives in. Nodes also gained a range() for underlining the full span in an editor.
While wiring this up we found the round-trip cursor disagreed with the loader on a document with a duplicate mapping key: the loader keeps the last value, the cursor was reading the first. They now agree, so reads, locate, keys, len, set, and delete all act on the same effective entry loads returns. (Duplicate keys are still rejectable outright with OPT_DUPLICATE_KEYS_ERROR.)
pip install yamlrocks📚 Docs: https://yaml.rocks
Same rock. X marks the spot. 🪨
../Frenck
Blogging my personal ramblings at frenck.dev
What's changed
✨ New features
v0.4.1: The stone gods relent 🪨
🪨 Moving the stone.
v0.4.0 was done. Two more review passes, a stronger fuzzer, a long list of correctness fixes, and a hardened include system, all of it ready (the full story is in the changelog below). We tagged it, we pushed the button, and the release pipeline sat down at the foot of the hill and refused to move the stone.
The cause was small and stupid, the way these always are. The release bumps the version in Cargo.toml, but Cargo.lock did not follow, and the wheel builds run with --locked, so cargo took one look at the mismatch and gave up. Every wheel. Nothing shipped.
So we made our peace with the stone gods. set_version.py now rolls Cargo.lock along with the manifests, a test stands guard so it cannot forget again, and the boulder is finally over the hill.
v0.4.1 is v0.4.0 as it was always meant to arrive. Same payload, same rock, this time actually in your hands. The changelog below is the real news. This note is just how it got out the door.
pip install yamlrocks📚 Docs: https://yaml.rocks
The stone rolls. 🪨
../Frenck
Blogging my personal ramblings at frenck.dev
What's changed
🐛 Bug fixes
🧰 Maintenance
⬆️ Dependency updates
- ⬆️ Update dependency ty to v0.0.55 @renovate[bot] (#153)
v0.4.0: Harder to crack 🪨
🪨 A harder rock to crack.
v0.3.0 went looking for cracks. v0.4.0 went looking harder, and this time a few of the cracks turned out to be security holes.
We put YAMLRocks through two more independent review passes and taught the differential fuzzer to assert that every dumped document loads back identical, not merely that it does not crash. That flushed out a long tail of quiet correctness bugs: an emitter that could write a ... or a folded scalar that re-read as a document marker, a tagged sequence item that lost its tag in indentless mode, JSON Schema $ref that was silently ignored, a big integer over i64 that fell back to a string, base-60 floats that skipped their own validation. All fixed, all pinned with tests.
The same passes turned up real issues in the include system, and those got the most attention. A handful of tiny files that include each other can no longer fan out into billions of reads (a billion-laughs, but for !include). A misconfigured logger: line in your secrets.yaml no longer echoes into the logs. And writing includes back to disk now refuses to follow a symlink swapped in underneath it, so a write can never escape your config tree.
New along the way: dumps emits YAML 1.1-safe output under OPT_YAML_1_1, round-trip edits are quoted by the schema the document was loaded with, and JSON Schema $ref resolves against local pointers.
Still more than 10x faster than PyYAML's C loader on both load and dump. We benchmarked it after all of this, and the numbers did not budge.
pip install yamlrocks📚 Docs: https://yaml.rocks
Same rock. Harder to crack. 🪨
../Frenck
Blogging my personal ramblings at frenck.dev
What's changed
✨ New features
- ✨ Emit YAML 1.1-safe output under OPT_YAML_1_1 on dumps @frenck (#114)
- ✨ Quote round-trip edits by the document's loaded schema @frenck (#115)
- ✨ Resolve JSON Schema $ref against local pointers @frenck (#131)
🐛 Bug fixes
- 🐛 Treat an indented
---/...as a plain scalar, not a document marker @frenck (#112) - 🐛 Reject malformed block structure in the round-trip composer @frenck (#113)
- ✨ Resolve round-trip projection under the document's loaded schema @frenck (#116)
- 🐛 Report a missing relative include as not-found, not confinement @frenck (#122)
- 🐛 Guard the remaining round-trip AST traversals against stack overflow @frenck (#125)
- 🐛 Keep %TAG and %YAML directives on a round-trip edit @frenck (#127)
- 🐛 Discover and navigate an anchor on a mapping key @frenck (#128)
- 🐛 Keep a non-conforming explicit core tag as a string, not a wrong value @frenck (#126)
- 🐛 Reject malformed verbatim tags and block scalar headers @frenck (#129)
- 🐛 Compare full structure for schema const/enum on containers @frenck (#130)
- 🐛 Reject invalid anchor names and tags before emitting them @frenck (#132)
- 🐛 Validate base-60 segments of a sexagesimal float @frenck (#133)
- 🐛 Snapshot a container before converting it to a round-trip node @frenck (#137)
- 🐛 Resolve a non-decimal integer over i64 as a big integer @frenck (#138)
- 🐛 Match PyYAML float and underscore rules under PyYAML-compat @frenck (#140)
- 🐛 Emit an explicit null before a tagged mapping key @frenck (#141)
- 🐛 Emit a non-first tagged mapping key in explicit-key form @frenck (#143)
- 🐛 Quote a string that re-reads as a document-end marker @frenck (#144)
- 🐛 Indent a tagged sequence item under its dash when indentless @frenck (#146)
- 🐛 Keep a folded scalar off the start of a marker line @frenck (#145)
- 🐛 Stop echoing a secrets.yaml logger value into the log @frenck (#150)
- 🐛 Write includes back atomically without following a symlink @frenck (#151)
- 🐛 Bound include expansion to stop a diamond-lattice fan-out @frenck (#149)
🧰 Maintenance
- ✅ Check every document of a multi-document compliance case @frenck (#134)
- 👷 Build and test against the locked dependency graph @frenck (#136)
- ✅ Require a proper decode error for invalid compliance cases @frenck (#139)
- ✅ Bound an alias bomb by wall-clock time, not just "eventually" @frenck (#142)
- ✅ Assert the fast emitter's output always re-parses in differential fuzz @frenck (#148)
- 👷 Pin exact cargo tool versions in CI @frenck (#152)
📚 Documentation
- 📝 Frame the three scalar schemas and the strict-1.1 y/n sharp edge @frenck (#119)
- 📝 Fix documentation that did not match the API @frenck (#135)
⬆️ Dependency updates
8 changes
- ⬆️ Update CodSpeedHQ/action action to v4.18.1 @renovate[bot] (#111)
- ⬆️ Update release-drafter/release-drafter action to v7.5.0 @renovate[bot] (#117)
- ⬆️ Update dependency ty to v0.0.54 @renovate[bot] (#123)
- ⬆️ Update dependency @astrojs/starlight to v0.41.1 @renovate[bot] (#118)
- ⬆️ Update release-drafter/release-drafter action to v7.5.1 @renovate[bot] (#124)
- ⬆️ Update dependency ruff to v0.15.20 @renovate[bot] (#121)
- ⬆️ Update dependency astro to v7.0.3 @renovate[bot] (#120)
- ⬆️ Update actions/attest action to v4.1.1 @renovate[bot] (#147)
v0.3.0: No cracks in this rock 🪨
🪨 We went looking for cracks, and fixed them.
YAMLRocks now passes the complete official YAML test suite (after we found we missed a bunch 🙈): every case loads, round-trips, and matches its canonical JSON, with no baseline to quietly absorb a regression.
To get there and stay there, we built a differential fuzzer that re-emits a document under every formatting option and checks it loads back unchanged. It promptly found a string of subtle, silent-corruption bugs in the scanner and emitter (block scalars, indentless sequences, tagged nodes, plain-scalar line wrapping). They are all fixed and pinned with tests, exactly the bug class a "rock-solid" library cannot ship.
Loading got leaner along the way: doomed number parses are skipped, plain scalars are trimmed in one pass instead of per byte, and scalar text now moves straight out of the event stream with no throwaway copy.
New this release: you can delete keys from round-trip documents (thanks @pdecat for #59), and there are wheels for Python 3.15, both the standard and free-threaded builds.
pip install yamlrocks📚 Docs: https://yaml.rocks
Same rock. Fewer cracks. 🪨
../Frenck
Blogging my personal ramblings at frenck.dev
What's changed
✨ New features
🐛 Bug fixes
- 🐛 Decode escaped tabs in double-quoted scalars @frenck (#80)
- 🐛 Reject tabs that indent block collections, accept tabs that separate scalars @frenck (#82)
- 🐛 Fix empty block scalars and reject tab indentation in scalars @frenck (#83)
- 🐛 Reject a directive that does not start a document @frenck (#84)
- 🐛 Support compact block mappings and sequences as explicit keys @frenck (#86)
- 🐛 Clear the speculative simple key after a block scalar @frenck (#93)
- 🐛 Keep an empty indentless sequence entry before a sibling key @frenck (#96)
- 🐛 Wrap long plain scalars by quoting, not unsafe plain folding @frenck (#95)
- 🐛 Indent a tagged sequence under its tag in indentless mode @frenck (#97)
🚀 Enhancements
- ♻️ Share the single- and double-quoted scalar fetch tail @frenck (#89)
- ⚡ Skip doomed numeric parses and the merge pass on common loads @frenck (#90)
- ⚡ Trim plain-scalar trailing blanks after the scan, not per byte @frenck (#91)
- ⚡ Move scalar text out of events during decode, dropping the pre-pass @frenck (#92)
🧰 Maintenance
- ✅ Cover yaml-test-suite case variants in the compliance harness @frenck (#81)
- ✅ Assert full YAML test suite compliance without a baseline @frenck (#88)
- ✅ Add an emit-options differential fuzz target @frenck (#98)
- 👷 Give the coverage job more address-space headroom @frenck (#99)
- 👷 Build Python 3.15 wheels (GIL and free-threaded) on native legs @frenck (#101)
📚 Documentation
- 📝 State full YAML test suite compliance and document compact block keys @frenck (#87)
- 📝 Drop the stale scalar-string side table note from the decode fuzz docs @frenck (#94)
⬆️ Dependency updates
33 changes
- ⬆️ Update dependency pytest to v9.1.0 @renovate[bot] (#54)
- ⬆️ Update python:3.14-slim Docker digest to 44dd044 @renovate[bot] (#55)
- ⬆️ Update dependency astro to v6.4.7 @renovate[bot] (#57)
- ⬆️ Update python:3.14-alpine Docker digest to 9445797 @renovate[bot] (#58)
- ⬆️ Update dependency astro to v6.4.8 @renovate[bot] (#62)
- ⬆️ Update dependency ty to v0.0.50 @renovate[bot] (#63)
- ⬆️ Update dependency node to v24.17.0 @renovate[bot] (#64)
- ⬆️ Update dependency rust-just to v1.53.0 @renovate[bot] (#61)
- ⬆️ Update release-drafter/release-drafter action to v7.4.0 @renovate[bot] (#60)
- ⬆️ Update CodSpeedHQ/action action to v4.17.6 @renovate[bot] (#66)
- ⬆️ Update dependency ruff to v0.15.18 @renovate[bot] (#67)
- ⬆️ Update dependency maturin to v1.14.1 @renovate[bot] (#69)
- ⬆️ Update actions/checkout action to v7 @renovate[bot] (#71)
- ⬆️ Update dependency node to v24.17.0 @renovate[bot] (#70)
- ⬆️ Update dependency ty to v0.0.51 @renovate[bot] (#68)
- ⬆️ Update python:3.14-alpine Docker digest to 2673086 @renovate[bot] (#65)
- ⬆️ Update dependency sharp to v0.35.2 @renovate[bot] (#73)
- ⬆️ Update dependency pytest to v9.1.1 @renovate[bot] (#72)
- ⬆️ Update dependency zizmor to v1.26.0 @renovate[bot] (#74)
- ⬆️ Update dependency zizmor to v1.26.1 @renovate[bot] (#75)
- ⬆️ Update dependency numpy to v2.5.0 @renovate[bot] (#76)
- ⬆️ Pin dependencies @renovate[bot] (#78)
- ⬆️ Lock file maintenance @renovate[bot] (#56)
- ⬆️ Update dependency ty to v0.0.52 @renovate[bot] (#85)
- ⬆️ Update actions/setup-python action to v6.3.0 @renovate[bot] (#104)
- ⬆️ Update dependency rust-just to v1.54.0 @renovate[bot] (#105)
- ⬆️ Update python:3.14-slim Docker digest to f54c5f3 @renovate[bot] (#106)
- ⬆️ Update dependency ty to v0.0.53 @renovate[bot] (#107)
- ⬆️ Update dependency node to v24.18.0 @renovate[bot] (#103)
- ⬆️ Update dependency ruff to v0.15.19 @renovate[bot] (#102)
- ⬆️ Update python:3.14-slim Docker digest to 63a4c7f @renovate[bot] (#108)
- ⬆️ Update CodSpeedHQ/action action to v4.18.0 @renovate[bot] (#109)
- ⬆️ Upgrade docs to Astro 7 and Starlight 0.41 @frenck (#110)
v0.2.1: Lighter to load 🪨
🪨 A lighter rock to pick up.
v0.2.0 made YAMLRocks run in parallel. v0.2.1 makes it quicker to even get going.
It turns out import yamlrocks was quietly pulling in asyncio (and through it ssl, logging, and friends) just to keep the async_* helpers ready, even if you never touched them. On a one-shot run that loads a small config and exits, that single import was most of the wall-clock time: enough to make us the slowest library on tiny files despite having the fastest parser. A bit embarrassing for a rock that brags about speed.
asyncio is now imported lazily, only when you actually await one of the async helpers. import yamlrocks drops from roughly 25 ms to roughly 2.5 ms, about 10x quicker, and the sync path carries none of it. A regression test keeps it honest.
Big thanks to @pdecat for the sharp diagnosis, -X importtime receipts and a cross-library, fresh-process benchmark included.
pip install yamlrocks📚 Docs: https://yaml.rocks
Same rock. Quicker to pick up. 🪨
../Frenck
Blogging my personal ramblings at frenck.dev
What's changed
🚀 Enhancements
v0.2.0: No GIL holding it back 🪨
🪨 The rock learns to run without the GIL.
The 0.1.x line was about getting YAMLRocks off the ground, and, memorably, about getting it to actually ship. 0.2.0 is about what it does now that it is flying.
The headline: free-threaded CPython is a first-class, shipped target. No-GIL wheels (cp314t) for Linux, macOS, and Windows, on x86_64 and ARM, glibc and musl. Run a free-threaded interpreter and pip install yamlrocks just hands you a wheel: no compiler, no GIL, no asterisks. Parse and emit YAML from as many threads as you have, no lock of our own in the way.
It got quicker on the way, too: a faster hashing path for the parser's key cache, and a tighter integer formatter on the dump side. Pure speed, byte-for-byte identical output.
And the part you do not see: every single wheel we ship is now built and run against the full test suite on its own platform, architecture, and libc. x86_64, aarch64, armv7, ppc64le, Windows on ARM, Alpine/musl, all of it. There is also a security bump (PyO3 0.29) that quietly closed a couple of advisories. "Rock-solid" stopped being just the tagline and became the CI.
pip install yamlrocks📚 Docs: https://yaml.rocks
Same rock. Now it runs in parallel. 🪨
../Frenck
What's changed
✨ New features
- ⚡ Build, test, and ship free-threaded (cp314t) wheels @frenck (#48)
- ⚡ Build free-threaded wheels for emulated aarch64 and musllinux 64-bit @frenck (#51)
🚀 Enhancements
- ⚡ Speed up the decode key cache with ahash and grow the emit buffer @frenck (#37)
- ⚡ Format integers on the dumps path with itoa @frenck (#45)
🧰 Maintenance
- 👷 Consolidate testing into one build-and-test flow @frenck (#31)
- 👷 Test the musllinux wheels under a musl runtime (x86_64 native, ARM emulated) @frenck (#34)
- 👷 Run the suite against the manylinux i686 wheel natively @frenck (#38)
- 🔧 Refresh the oss-fuzz base image only once a month @frenck (#47)
- ⚡ Build, test, and ship free-threaded (cp314t) wheels @frenck (#48)
- 👷 Pin the in-container test pip installs for OpenSSF Scorecard @frenck (#50)
- ⬆️ Update gcr.io/oss-fuzz-base/base-builder-rust:latest Docker digest to c3b8c5a @renovate[bot] (#46)
- ⚡ Build free-threaded wheels for emulated aarch64 and musllinux 64-bit @frenck (#51)
⬆️ Dependency updates
13 changes
- ⬆️ Update gcr.io/oss-fuzz-base/base-builder-rust:latest Docker digest to ad58fbf @renovate[bot] (#30)
- ⬆️ Update dependency ubuntu to v24 @renovate[bot] (#33)
- ⬆️ Update dependency sharp to v0.35.1 @renovate[bot] (#35)
- ⬆️ Update CodSpeedHQ/action action to v4.17.5 @renovate[bot] (#32)
- ⬆️ Update dependency ruff to v0.15.17 @renovate[bot] (#36)
- ⬆️ Update python Docker tag to v3.14 @renovate[bot] (#39)
- ⬆️ Update Rust crate pyo3 to 0.29 @renovate[bot] (#44)
- ⬆️ Update gcr.io/oss-fuzz-base/base-builder-rust:latest Docker digest to b1e9615 @renovate[bot] (#42)
- ⬆️ Update dependency ty to v0.0.49 @renovate[bot] (#43)
- ⬆️ Update dependency maturin to v1.14.0 @renovate[bot] (#41)
- ⬆️ Update Rust crate smallvec to v1.15.2 @renovate[bot] (#40)
- ⬆️ Force esbuild >= 0.28.1 in the docs to clear two advisories @frenck (#49)
- ⬆️ Update gcr.io/oss-fuzz-base/base-builder-rust:latest Docker digest to c3b8c5a @renovate[bot] (#46)
v0.1.3: Now with pre-flight checks 🪨
🪨 The rock now checks the landing first.
v0.1.2 was going to be the one. Instead it sat in the queue forever, waiting for an Intel Mac runner that GitHub had quietly retired back in December, so the wheel build was politely holding out for a machine that no longer exists.
v0.1.3 fixes that (the macOS jobs moved to macOS 26) and, more to the point, it stops guessing: every wheel is now built and imported on its own platform and Python version before a tag is ever cut. So unlike the previous three attempts, this release was actually proven to work before you read this.
👉 What it is and everything it does: see the v0.1.0 release notes.
pip install yamlrocks📚 Docs: https://yaml.rocks
Fourth time's the charm. The rock has well and truly landed. 🪨
What's changed
🧰 Maintenance
- 👷 Reliable, continuously-tested wheel builds (fix retired macOS runners + shared build matrix) @frenck (#28)
⬆️ Dependency updates
- ⬆️ Update dependency ty to v0.0.48 @renovate[bot] (#29)
v0.1.2: Third rock's the charm 🪨
🪨 Third rock's the charm.
v0.1.1 was supposed to be "the one that actually ships." It was not. It tripped over s390x, an IBM mainframe architecture whose assembler is too old to recognize a CPU instruction from 2003, so a single wheel build face-planted and dragged the whole release down with it. So we dropped s390x, added Windows on ARM while we were in the neighborhood, and tried again.
v0.1.2 is that release, now actually on PyPI. For real this time.
👉 What it is and everything it does: see the v0.1.0 release notes.
pip install yamlrocks📚 Docs: https://yaml.rocks
The rock keeps rolling. 🪨
../Frenck
Blogging my personal ramblings at frenck.dev
What's changed
🚨 Breaking changes
✨ New features
🧰 Maintenance
- 🔧 Stop Renovate from pinning the setup-python python-version @frenck (#25)
- 👷 Build Windows arm64 wheels @frenck (#27)