Languages: English · Русский · 简体中文
All notable changes to the ktav Python package are documented here.
The format is based on Keep a Changelog;
this package adheres to Semantic Versioning with
the pre-1.0 convention that a MINOR bump is breaking.
For the format specification's own history, see
ktav-lang/spec. For the
underlying Rust implementation, see
ktav-lang/rust.
- Docs: rewrite all README examples to spec 0.6 syntax (bare numbers instead of removed
:i/:fmarkers;##comments instead of#).
Sync to Ktav 0.6.0 — keys now support escaping.
- Keys process the full §3.7 escape set, with two new escapes:
\.→.(literal dot — does not split a dotted path)\:→:(literal colon — does not act as the key/value separator)
- Examples:
a\.b: v→{"a.b": "v"},a\:b: v→{"a:b": "v"},x.y\.z: v→{"x": {"y.z": "v"}}.
- A literal backslash inside a key now requires
\\(previously\in a key was a plain byte). Rare in practice; per pre-1.0 SemVer this is a MINOR bump.
- Tracks ktav-rust 0.6.0 / Ktav spec 0.6.0. Binding source unchanged — the escape change is internal to the Rust core and transparent across the PyO3 boundary.
Breaking release implementing Ktav specification 0.5.0.
- Typed markers
:iand:fremoved. Numbers, booleans, andnullare inferred from the scalar's lexical form (spec §§ 3.6, 5.2).port: 8080now yieldsint(8080); useport:: 8080to keep a String. - Comments use
##(line-start only). A single#byte is content —color: #FF0000is a valid string value. - Inline compounds
{k: v, …}/[i, …]are now valid (spec § 5.8). TheInlineNonEmptyCompounderror is no longer emitted by the parser.
ktav.emit_canonical(obj)— emit the normalised (spec § 5.9) byte-deterministic canonical form of a Python value.- Number literal grammar — hex (
0x), octal (0o), binary (0b), decimal, and underscore separators; i64 overflow falls back to String. - Eight escape sequences in inline scalars (spec § 3.7):
\\,\,,\},\],\{,\[,\n,\r.
- License:
MIT→MIT OR Apache-2.0. AddedLICENSE-APACHE; renamedLICENSE→LICENSE-MIT. - Spec submodule pinned to
v0.5.0. - Picked up
ktav 0.5.0.
Backward-compatible feature release: top-level Arrays and a new
dumps_force_strings entry point.
- Top-level Array support (spec 0.1.1, § 5.0.1) — the parser now
recognises documents whose first content line is an array-item
shape (a bare scalar,
:: text,:i 42,:f 3.14, a lone{/[, or a multi-line opener(/(() as a root-level Array.ktav.loads(":i 1\n:i 2")returns[1, 2]. Object documents are unchanged. The serialiser accepts top-levellist/tupleand emits items bare, one per line, with no surrounding[...]. ktav.dumps_force_strings(obj)— render every leaf scalar as a String (typed integers, typed floats, booleans, andNoneare flattened to their textual form via the raw::marker so the output round-trips back as the same string scalars). Compounds preserve their structure; only leaves are coerced. The Python-idiomatic snake_case parallel todumps/loads.
- Picked up
ktav 0.3.1— adds the format-level top-level Array support and theto_string_force_stringsAPI the new Python entry point delegates to. See thektavcrate CHANGELOG. ktav.dumps(list_or_tuple)no longer raises — it now renders a top-level Array per spec § 5.0.1.__spec_version__bumped to0.1.1.
- spec submodule synced to
7256816(Ktav 0.1.1 — top-level Array fixtures underversions/0.1/tests/valid/top_level_array/andversions/0.1/tests/invalid/top_level/).
- Picked up
ktav 0.3.0— the upstream Rust crate's reject-paren-strings change. Inline paren-wrapped scalars likea: (hello)anda: ((wrapped))are now decode errors. The PyO3 binding inherits this behaviour transparently. See thektavcrate CHANGELOG.
- spec submodule synced to
46d94a7(new invalid fixturesinline_paren_string_doubleandinline_paren_string_single, tightenedpartial_parensvalid-fixture).
-
Picked up
ktav 0.2.0— multi-line strings now serialize in the indented stripped( ... )form by default.:f 42accepts integer literals (parsed as42.0). See thektavcrate CHANGELOG.Code comparing serialized output byte-for-byte to a baked-in
((...))literal must be updated. Round-trip is unchanged.
- spec submodule synced (typed_float_integer_body fixture; oracle 42.0).
- Picked up
ktav 0.1.5— the upstream Rust crate's structured errors API (Error::Structured(ErrorKind)with byte-offset spans), retroactive#[non_exhaustive]on the error enums, and the publicktav::thinevent-based parser. The PyO3 binding's user-visible behaviour is unchanged:KtavDecodeError/KtavEncodeErrorstill carry the same human-readable messages (Display strings for the seven canonical categories are byte-identical to ktav 0.1.4). Mappingktav::ErrorKindto a structured Python exception hierarchy (MissingSeparatorSpace,DuplicateKey, etc.) is separate follow-up work tracked in the workspace'sSTRUCTURED_ERRORS.md.
PyPI: ktav==0.1.2.
- Picked up
ktav 0.1.4— the upstream Rust crate's untypedparse() → Valuepath (which the PyO3 binding uses) is now ~30% faster on small documents and ~13% faster on large ones, just from a one-lineFrame::Objectcapacity tweak (4 → 8). Everyktav.loadscall benefits transparently.
PyPI: ktav==0.1.1.
Initial release. Implements Ktav spec 0.1.0 via PyO3 bindings over the reference Rust implementation.
ktav.loads(s)— parse a Ktav string (or UTF-8bytes) into native Python values.ktav.dumps(obj)— serialise a native Python value into Ktav text.ktav.load(fp)/ktav.dump(obj, fp)— file-like wrappers that work for both text-mode and binary-mode files.- Exception hierarchy:
KtavError(base),KtavDecodeError,KtavEncodeError. - Type mapping honouring Ktav's "no magic types" principle:
- bare scalars →
str; :imarker →int(arbitrary precision round-trips);:fmarker →float(decimal point always present on output);- keywords
null/true/false→None/bool; [ ... ]→list;{ ... }→dict(insertion order preserved).
- bare scalars →
NaN/±Infinityrejected by the serialiser — Ktav 0.1.0 does not represent them.- Bundled
.pyitype stubs andpy.typedmarker (PEP 561). ktav.__version__— package version.ktav.__spec_version__— Ktav format version these bindings implement.
Prebuilt wheels:
- Linux (manylinux + musllinux) —
x86_64,aarch64 - macOS —
x86_64,arm64 - Windows —
x64,arm64
Wheels use the stable ABI (abi3-py39); one wheel per platform serves
every supported CPython release.
Rust 1.70 or newer — matches the underlying ktav crate.