Skip to main content

ktav (Python)

PyPI CI License: MIT OR Apache-2.0 Playground

Python bindings for Ktav — a plain configuration format. JSON-shape, no required quotes, no commas, dotted keys. Powered by Rust under the hood.

Languages: English · Русский · 简体中文

Playground: convert JSON / YAML / TOML / INI ⇄ Ktav in your browser at ktav-lang.github.io.

Specification: this package implements Ktav. The format is versioned and maintained independently of this package — see ktav-lang/spec for the formal document.


Install

pip install ktav

Wheels are published for every major platform and every supported Python version:

  • Linux (manylinux + musllinux) — x86_64, aarch64
  • macOS — x86_64, arm64 (Apple Silicon)
  • Windows — x64, arm64

Python 3.9+ is required. The wheels target the stable ABI (abi3-py39), so a single wheel per platform serves every supported CPython release.

If no prebuilt wheel matches your platform, pip falls back to the source distribution and compiles it locally — you need a Rust toolchain (rustup) and the Python development headers.

Quick start

Parse — read typed fields straight off the dict

import ktav

src = """
service: web
port: 8080
ratio: 0.75
tls: true
tags: [
    prod
    eu-west-1
]
db.host: primary.internal
db.timeout: 30
"""

cfg = ktav.loads(src)

service: str = cfg["service"]
port: int = cfg["port"]
ratio: float = cfg["ratio"]
tls: bool = cfg["tls"]
tags: list[str] = cfg["tags"]
db_host: str = cfg["db"]["host"]
db_timeout: int = cfg["db"]["timeout"]

Walk — dispatch on the runtime type

for k, v in cfg.items():
    if v is None:
        kind = "null"
    elif isinstance(v, bool):
        kind = f"bool={v}"  # bool first — True is also an int!
    elif isinstance(v, int):
        kind = f"int={v}"
    elif isinstance(v, float):
        kind = f"float={v}"
    elif isinstance(v, str):
        kind = f"str={v!r}"
    elif isinstance(v, list):
        kind = f"array({len(v)})"
    elif isinstance(v, dict):
        kind = f"object({len(v)})"
    print(f"{k} -> {kind}")

Build & render — construct a document in code

doc = {
    "name": "frontend",
    "port": 8443,
    "tls": True,
    "ratio": 0.95,
    "upstreams": [
        {"host": "a.example", "port": 1080},
        {"host": "b.example", "port": 1080},
    ],
    "notes": None,
}
text = ktav.dumps(doc)
# name: frontend
# port: 8443
# tls: true
# ratio: 0.95
# upstreams: [
#     { host: a.example  port: 1080 }
#     { host: b.example  port: 1080 }
# ]
# notes: null

A complete runnable version lives in examples/basic.py.

Format — normalise a file, keep the comments

import ktav

print(ktav.format(open("config.ktav").read()))

ktav.format rewrites a document in canonical form (spec § 5.9) while preserving every comment verbatim. Blank-line runs collapse to one and blank padding inside brackets is dropped, so formatting is a fixed point — safe to run in a pre-commit hook. Key order is never changed.

Three functions produce canonical output and they differ in what they accept and what they keep:

input comments blank lines
ktav.format(src) source text kept kept (runs collapse to one)
ktav.canonical_from_source(src) source text dropped dropped
ktav.emit_canonical(obj) a Python object none to keep none to keep

Pick by what you are holding: emit_canonical when you have an object, canonical_from_source when you have text and want no Python value built in between, format when you want the document's own comments and grouping to survive.

Unlike the JavaScript bindings, canonical_from_source buys you no extra numeric fidelity here — Python distinguishes int from float, so the Ktav Integer/Float distinction survives loads, and emit_canonical(loads(src)) produces the same bytes as canonical_from_source(src). Both spell a float by the canonical rule (§ 5.9.8) rather than by copying the source, so 1.23456789012345678901 becomes 1.2345678901234567 down either path.

ktav.dumps_force_strings(obj) renders like dumps but coerces every leaf scalar — integer, float, bool, null — to a String via the raw :: marker. Compounds keep their structure.

Four entry points mirror the standard library json module:

Function Purpose
ktav.loads(s) Parse a Ktav string (or UTF-8 bytes).
ktav.dumps(obj) Serialise a native Python value.
ktav.load(fp) Parse from a file-like object.
ktav.dump(obj, fp) Serialise to a file-like object.

load / dump accept both text-mode and binary-mode files.

For validation at trust boundaries, ktav.loads_strict(s) applies the specification's canonical-scalar rules and raises KtavDecodeError for a lossy scalar spelling. Canonical writer forms such as 1e-3 and 1e10 are accepted and produce the same native values as loads.

Type mapping

Ktav Python
null None
true / false bool
bare integer int
bare decimal float
other scalar str
[ ... ] list
{ ... } dict

Ktav types numbers by lexical form — a bare port: 8080 is an int, ratio: 0.5 a float, and anything that isn't a bare number stays a str. Force a numeric-looking value to stay a string with :: (zip:: 01007).

dict preserves insertion order (Python 3.7+ guarantee), matching the ordered-object semantics of Ktav.

Serialisation is the inverse:

  • Python int → bare integer (including arbitrary-precision bigints).
  • Python float → bare decimal (decimal point always present; NaN / ±Infinity are rejected — Ktav does not represent them).
  • Python tuple is accepted as an array, for symmetry with list.
  • Non-str keys in a dict raise KtavEncodeError.

Key escaping

Since spec 0.6.4 a literal . or : inside a key segment is written with a backslash:

a\.b: v
a\:b: v
x.y\.z: v
a."b.c".d: v
"\u0041": v

A literal backslash in a key is \\. Since spec 0.7, a whole segment may instead use double quotes, single quotes or backticks. Quotes only delimit key segments, not values; \uXXXX decodes a Unicode code point.

Errors

import ktav

try:
    ktav.loads("x: [")
except ktav.KtavDecodeError as e:
    print("decode:", e)

try:
    ktav.dumps({"v": float("nan")})
except ktav.KtavEncodeError as e:
    print("encode:", e)

# Catching the base class catches either.
try:
    ktav.loads("a: 1\na: 2")
except ktav.KtavError:
    ...
Exception Raised by Base
KtavError (base) Exception
KtavDecodeError loads / load KtavError
KtavEncodeError dumps / dump KtavError

Since 0.7.1 every raised instance also carries the structured error envelope as attributes: error, reason, line, line_text, span, path, body, canonical, spec_section. Absent information is None, never a missing attribute. span is {"start": …, "end": …} byte offsets into the UTF-8 source; path is the list of exact decoded key segments (a key literally named a.b is one segment, never split). str(e) stays a human-readable message — the raw envelope is never substituted for it.

e.message carries that same text as an attribute, so str(e) == e.message. It is redundant here by design: this binding has always used the core's own rendering for str(e), and the attribute exists so the envelope has the same ten-field shape in Python that it has in every other language — where message is the only way to reach the text. Use it rather than rebuilding a sentence from error, line and body: a reassembled message differs between bindings, and this one does not.

Philosophy

Ktav is intentionally small. Its five design principles (from spec/CONTRIBUTING.md):

  1. Locality — a line's meaning does not depend on another line.
  2. One sentence — any new rule fits in one sentence of the spec.
  3. No whitespace sensitivity (line breaks aside).
  4. No magic types — the format never decides "8080" means a number.
  5. Explicit over clever — :: is verbose on purpose.

The Python bindings honour this: they add no schema inference, no auto-casting, no defaulting. If you want typing, you do it at the boundary with your own tool — pydantic, dataclasses, attrs — against the native Python structures this library returns.

Other Ktav implementations

  • spec — specification + conformance suite
  • rust — reference Rust crate (cargo add ktav); these Python bindings are a thin PyO3 wrapper around it
  • csharp — C# / .NET (dotnet add package Ktav)
  • golang — Go (go get github.com/ktav-lang/golang)
  • java — Java / JVM (io.github.ktav-lang:ktav on Maven Central)
  • js — JS / TS (npm install @ktav-lang/ktav)
  • php — PHP (composer require ktav-lang/ktav)

Versioning

This package follows Semantic Versioning with the pre-1.0 convention that a MINOR bump is breaking. The package version and the ktav crate version move together. ktav.__spec_version__ reports the Ktav format version this binding supports.

Development

See CONTRIBUTING.md for the dev setup, test layout, and the contribution workflow.

Support the project

The author has many ideas that could be broadly useful to IT worldwide — not limited to Ktav. Realizing them requires funding. If you'd like to help, please reach out at phpcraftdream@gmail.com.

License

MIT OR Apache-2.0. See LICENSE-MIT and LICENSE-APACHE.

Metadata

Release files for ktav 0.8.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 ktav 0.8.0
File Size Uploaded
ktav-0.8.0.tar.gz 69.2 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for ktav 0.8.0
File
ktav-0.8.0-cp39-abi3-win_arm64.whl CPython 3.9 abi3 Windows ARM64 Details
ktav-0.8.0-cp39-abi3-win_amd64.whl CPython 3.9 abi3 Windows x86-64 Details
ktav-0.8.0-cp39-abi3-musllinux_1_2_x86_64.whl CPython 3.9 abi3 Linux musl 1.2+ x86-64 Details
ktav-0.8.0-cp39-abi3-musllinux_1_2_aarch64.whl CPython 3.9 abi3 Linux musl 1.2+ ARM64 Details
ktav-0.8.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.9 abi3 Linux glibc 2.17+ x86-64 Details
ktav-0.8.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.9 abi3 Linux glibc 2.17+ ARM64 Details
ktav-0.8.0-cp39-abi3-macosx_11_0_arm64.whl CPython 3.9 abi3 macOS 11.0+ ARM64 Details
ktav-0.8.0-cp39-abi3-macosx_10_12_x86_64.whl CPython 3.9 abi3 macOS 10.12+ x86-64 Details

Total release size: 3.1 MB

Release files / ktav-0.8.0.tar.gz

Download URL ktav-0.8.0.tar.gz
Size 69.2 kB
Tags Source
SHA-256 checksum
How to use checksums
891b3b878be5cdca5caba2e366a31e602d66e23f4d04d2e8fec4102ec170d7ec
BLAKE2b-256 checksum
How to use checksums
cde1a8065aad2a008dd69434bbd4a023b59f96da37d04675e74e36974ec80b1e
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 24, 2026.

Transparency log

Release files / ktav-0.8.0-cp39-abi3-win_arm64.whl

Download URL ktav-0.8.0-cp39-abi3-win_arm64.whl
Size 271.5 kB
Tags CPython 3.9 Windows ARM64 abi3
SHA-256 checksum
How to use checksums
5cd802e32e987449b94b91b8a1ee31b95ec255421a0b3c07a1a0ffa232890a91
BLAKE2b-256 checksum
How to use checksums
e91fa08dfa906812f229fa54cd14f2442ee3e673dd5289a51e9f3d6147e59625
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 24, 2026.

Transparency log

Release files / ktav-0.8.0-cp39-abi3-win_amd64.whl

Download URL ktav-0.8.0-cp39-abi3-win_amd64.whl
Size 279.7 kB
Tags CPython 3.9 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
2c9fb6d87ed2df12bfeb55eb6a71253a763650fab9b63cbcfdb8e2c704eca6a4
BLAKE2b-256 checksum
How to use checksums
d2d9eb50586a6c488f3c2436a3fd32673c4023ef4a09b0eadbea2974bb9594fc
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 24, 2026.

Transparency log

Release files / ktav-0.8.0-cp39-abi3-musllinux_1_2_x86_64.whl

Download URL ktav-0.8.0-cp39-abi3-musllinux_1_2_x86_64.whl
Size 573.9 kB
Tags CPython 3.9 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
f1425c8ab02044b1544bbdda862a589c862660cb68675c24424191f8d79ae4bb
BLAKE2b-256 checksum
How to use checksums
95a332a1579e6afaba08564924f528b4e09decb47b68a09b1b4b6d53f506cd52
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 24, 2026.

Transparency log

Release files / ktav-0.8.0-cp39-abi3-musllinux_1_2_aarch64.whl

Download URL ktav-0.8.0-cp39-abi3-musllinux_1_2_aarch64.whl
Size 524.7 kB
Tags CPython 3.9 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
058bbfde01650cd24383136c18058ec020cdac56634f580dc0830f7decf51a39
BLAKE2b-256 checksum
How to use checksums
4a76d91e0450bf84e0dc5edd6e7bd365efeac2df57ada73829f6d5ba28626d51
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 24, 2026.

Transparency log

Release files / ktav-0.8.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL ktav-0.8.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 360.9 kB
Tags CPython 3.9 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
62c50ba14d04dd939956cdcb33d251bf7acf404ac262adbf1c7473392bb048d6
BLAKE2b-256 checksum
How to use checksums
abeab49ddc9894767dc6bf788533ac1a0ecc60b31b58916dd252ea3c9ae41022
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 24, 2026.

Transparency log

Release files / ktav-0.8.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL ktav-0.8.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 345.4 kB
Tags CPython 3.9 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
441f856499728021c843d09e47b3db75625d1ed1d4afb67b434351dd983409dc
BLAKE2b-256 checksum
How to use checksums
87d9e8062151fb55e39ae28dd565f2ae498ec8209f2aee81ab06b722e94b03c2
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 24, 2026.

Transparency log

Release files / ktav-0.8.0-cp39-abi3-macosx_11_0_arm64.whl

Download URL ktav-0.8.0-cp39-abi3-macosx_11_0_arm64.whl
Size 335.0 kB
Tags CPython 3.9 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
0d5037361f00a2f7d730731bc2aeeec7e4a16aa8cb83f2255344bce33251d546
BLAKE2b-256 checksum
How to use checksums
bc4842943e69fc9a6d4930bea2548cbc596286664bd74879578fc5b438ed8929
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 24, 2026.

Transparency log

Release files / ktav-0.8.0-cp39-abi3-macosx_10_12_x86_64.whl

Download URL ktav-0.8.0-cp39-abi3-macosx_10_12_x86_64.whl
Size 351.0 kB
Tags CPython 3.9 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
cd888398d3584e1df8ebe3b891e6c15656f603de437caeb20405077cba818fcd
BLAKE2b-256 checksum
How to use checksums
6078c476298e9d416af909b35265e31caecca68a5f73f76b039a6150e87d9b37
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 24, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.8.0 This release

9 release files

0.6.4

9 release files

0.6.1

9 release files

0.6.0

9 release files

0.5.0

9 release files

0.3.1

9 release files

0.3.0

9 release files

0.2.0

9 release files

0.1.2

9 release files

0.1.1

9 release files

0.1.0

9 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