yeptris — YAML for Python at libleptris speed
An FFI-based (no C extension) YAML library over libyeptris — the YAML counterpart of libleptris. PyYAML-compatible semantics, one shared library, zero compilation at install.
Install (development)
# the sibling C checkout: ~/src/leptris/yeptris
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DYEPTRIS_BUILD_SHARED=ON
cmake --build build
cd ~/src/leptris/yeptris-py
YEPTRIS_LIB_PATH=../yeptris/build/src/libyeptris.dylib python3 -m pytest
Without YEPTRIS_LIB_PATH the loader falls back to a vendored
yeptris/_platform/<tag>/ copy, then to the sibling checkout's
build directory. Any libyeptris.{so,dylib,dll} path works.
Usage
import yeptris
from yeptris import yaml # PyYAML-compatible surface
yaml.safe_load("name: yeptris\nrating: 10\n")
# {'name': 'yeptris', 'rating': 10}
yaml.safe_load_all("--- 1\n--- two\n") # [1, 'two']
yaml.safe_dump({"b": 2, "a": [1, "x"]}) # 'a:\n - 1\n - x\nb: 2\n'
yeptris.load("k: v") # the neutral surface
yeptris.dump({"k": [1, 2]})
Typing follows PyYAML's SafeLoader (YAML 1.1 implicit typing):
yes/no/on/off booleans, 0x/leading-0/0b/sexagesimal integers,
dot-required floats, timestamps with offsets, merge keys, anchor
identity. Every deliberate divergence is pinned by a test.
Design
One parse, one bulk drain: the record array and string arena are
read in two FFI calls, then a pure-Python walk over the unpacked
records — the FFI tax is O(1) per document, never per event (the
same seam yeptris-ruby rides). The 36-byte record layout is
ABI-pinned in the C header and mirrored in _ffi.py.
Performance
python3 bench.py — same-process comparison against PyYAML (pure)
and CSafeLoader/CDumper (libyaml C extensions):
- load: 28-39x PyYAML pure, 3.8-6.1x CSafeLoader
- dump: ~1.7x PyYAML pure, ~2x behind CDumper (which walks the
tree entirely in C — a no-C-extension design's ceiling is the
Python walk itself; the tree raises through ONE
yeptris_document_buildcall)
Both directions are O(chunks) in FFI calls: loads drain records in two calls, dumps build through one flat entry array.
JSON (strict RFC 8259) — yeptris.json
yeptris.json.loads is json.loads-compatible (values, rejects,
types, json.JSONDecodeError — including stdlib's default NaN/
Infinity constant quirk) with two engines behind one contract:
- native — the opt-in extension
ext/yeptris_native.c: a fused scan-kernel descent over libyeptris (the same shape as the Ruby binding's materializer), with a 1024-slot interned-free key cache. Build it withYEPTRIS_LIB_PATH+YEPTRIS_SRCset (python3 setup.py build_ext --inplace); CI builds and gates it. - strict-ffi — the default pure path:
yeptris_parse_jsonis the validator gate, then the columnar value walk converts under JSON rules. No C extension, correct everywhere.
benchmark/json_profile.py is the referee (order-alternating
interleave vs the C scanner): the native engine runs 0.67-0.87x
json.loads mean (83-85% head-to-head) on the 144 KB reference
corpus; shape decomposition: int arrays 0.63x, float arrays 0.77x,
long strings 0.85x, unique-key maps 0.95x. The previous pure walk
was ~15x BEHIND — the fused materializer is the entire gap.
Installing the native JSON engine (platform wheels)
pip install yeptris on macOS (arm64) and manylinux (x86_64)
installs platform wheels that vendor libyeptris and the native
JSON materializer (abi3 — one wheel per platform serves CPython
3.9+): zero compiler, zero env vars, yeptris.json.engine() is
native out of the box. Every wheel is release-smoked in a clean
venv before publish. Other platforms install the pure package (the
strict-ffi JSON engine + YAML via libyeptris through the
YEPTRIS_LIB_PATH ladder); building the extension from source is
YEPTRIS_LIB_PATH=... YEPTRIS_SRC=... python3 setup.py build_ext --inplace.
Release files for yeptris 0.2.4.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| yeptris-0.2.4.1.tar.gz | 24.9 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| yeptris-0.2.4.1-py3-none-any.whl | Python 3 | none | any | Details |
| yeptris-0.2.4.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| yeptris-0.2.4.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| yeptris-0.2.4.1-cp39-abi3-macosx_11_0_x86_64.whl | CPython 3.9 | abi3 | macOS 11.0+ x86-64 | Details |
| yeptris-0.2.4.1-cp39-abi3-macosx_11_0_arm64.whl | CPython 3.9 | abi3 | macOS 11.0+ ARM64 | Details |
Total release size: 1.0 MB
Release files / yeptris-0.2.4.1.tar.gz
| Download URL | yeptris-0.2.4.1.tar.gz |
|---|---|
| Size | 24.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
56cf5e745e7aaa27e5582454201e9291889d5e8c9e9b462dbb82a6979aca9047
|
|
BLAKE2b-256 checksum How to use checksums |
506c6bbcf97d5ed30d0dd96eaaad324b341e2fb112864bad27323649336c6cfe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.5
|
Release files / yeptris-0.2.4.1-py3-none-any.whl
| Download URL | yeptris-0.2.4.1-py3-none-any.whl |
|---|---|
| Size | 18.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d0ace76a1038c49a1504cf119ae4ea02609cf1a9bc728cde5aec2422cf178a82
|
|
BLAKE2b-256 checksum How to use checksums |
93f9d98cd2da6223976f566113ad35c51fa7c425ea0bd20388fda169374bfebe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.5
|
Release files / yeptris-0.2.4.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
| Download URL | yeptris-0.2.4.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
|---|---|
| Size | 264.0 kB |
| Tags | CPython 3.9 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
37a712b2883b47dd2720a34032dfe5bd9374632740bc07770a366e8c864a49c9
|
|
BLAKE2b-256 checksum How to use checksums |
c1281a66f4e8dc7668161089c0ddb20b5c89d3e157ce65050ccd1f78e3c73f86
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.5
|
Release files / yeptris-0.2.4.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
| Download URL | yeptris-0.2.4.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl |
|---|---|
| Size | 269.9 kB |
| Tags | CPython 3.9 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
f257c4e4bf509bbd73e81d43f0ef56944e55f186e39c62a21b9875dc7cd975be
|
|
BLAKE2b-256 checksum How to use checksums |
6a7d4478097f064c01a32f15573369fc204b8afbce5b5970c932d8eefa6c5ac7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.5
|
Release files / yeptris-0.2.4.1-cp39-abi3-macosx_11_0_x86_64.whl
| Download URL | yeptris-0.2.4.1-cp39-abi3-macosx_11_0_x86_64.whl |
|---|---|
| Size | 227.9 kB |
| Tags | CPython 3.9 abi3 macOS 11.0+ x86-64 |
|
SHA-256 checksum How to use checksums |
e61da39bf897576cf5923f98ae07a5c5e72e651cdca3083308fc092ef94cb4ad
|
|
BLAKE2b-256 checksum How to use checksums |
31e919c8100cf62c29a29ca06a1fca91234dab7928f1a472744d4d2275a7d300
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.5
|
Release files / yeptris-0.2.4.1-cp39-abi3-macosx_11_0_arm64.whl
| Download URL | yeptris-0.2.4.1-cp39-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 219.9 kB |
| Tags | CPython 3.9 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
6c25778c487c28befd4c3923e5c84ea3186b1fe019419eea0c24dad5e6498021
|
|
BLAKE2b-256 checksum How to use checksums |
ba98c2aa77259f4dba859cdf2992d9bb0a7fae9a83c45030a2ed599dbcd030de
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.5
|