Python-биндинги для Ktav — простого формата конфигов. Форма JSON, без кавычек, без запятых, вложенность через точки в ключах. Под капотом — Rust.
Языки: English · Русский · 简体中文
Спецификация: этот пакет реализует Ktav 0.1. Формат версионируется
и развивается отдельно — см.
ktav-lang/spec для нормативного
документа.
pip install ktavГотовые wheel-ы публикуются для всех основных платформ и поддерживаемых версий Python:
- Linux (manylinux + musllinux) —
x86_64,aarch64 - macOS —
x86_64,arm64(Apple Silicon) - Windows —
x64,arm64
Требуется Python 3.9+. Wheel-ы собраны под стабильный ABI
(abi3-py39), поэтому одного wheel на платформу хватает для всех
поддерживаемых версий CPython.
Если под вашу платформу нет готового wheel, pip откатится на sdist и
соберёт расширение локально — для этого нужен Rust toolchain
(rustup) и заголовочные файлы Python-разработчика.
import ktav
src = """
service: web
port:i 8080
ratio:f 0.75
tls: true
tags: [
prod
eu-west-1
]
db.host: primary.internal
db.timeout:i 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"]for k, v in cfg.items():
if v is None: kind = "null"
elif isinstance(v, bool): kind = f"bool={v}" # bool первым — True это 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}")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)Полный запускаемый пример — в examples/basic.py.
Четыре публичные функции — форма повторяет стандартный json:
| Функция | Назначение |
|---|---|
ktav.loads(s) |
Разобрать строку Ktav (или UTF-8 bytes). |
ktav.dumps(obj) |
Сериализовать нативное значение Python. |
ktav.load(fp) |
Разобрать из файла-подобного объекта. |
ktav.dump(obj, fp) |
Сериализовать в файл-подобный объект. |
load / dump принимают как текстовый, так и бинарный режим файла.
| Ktav | Python |
|---|---|
null |
None |
true / false |
bool |
:i <digits> |
int |
:f <number> |
float |
| скаляр без маркера | str |
[ ... ] |
list |
{ ... } |
dict |
Ktav живёт по принципу «никакой магии в типах» — голый port: 8080
на уровне парсера остаётся строкой. Нужны числа — используйте
маркеры :i / :f, либо приводите типы сами на прикладном уровне.
dict сохраняет порядок вставки (гарантия Python 3.7+), что совпадает с
семантикой упорядоченных объектов Ktav.
Сериализация — обратное соответствие:
- Python
int→ маркер:i(в том числе bigint произвольной точности). - Python
float→ маркер:f(точка всегда присутствует;NaN/±Infinityотвергаются — Ktav 0.1.0 их не представляет). - Python
tupleдопустим как массив, симметричноlist. - Ключ словаря не-
str→KtavEncodeError.
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)
# Ловля базового класса перехватывает оба варианта.
try:
ktav.loads("a: 1\na: 2")
except ktav.KtavError:
...| Исключение | Источник | База |
|---|---|---|
KtavError |
(базовое) | Exception |
KtavDecodeError |
loads / load |
KtavError |
KtavEncodeError |
dumps / dump |
KtavError |
Ktav намеренно маленький. Пять принципов проектирования
(из spec/CONTRIBUTING.md):
- Локальность — смысл строки не зависит от другой строки.
- Одно предложение — новое правило умещается в одну фразу спеки.
- Нет чувствительности к пробелам (кроме переноса строк).
- Никакой магии в типах — формат не решает, что
"8080"— число. - Явно лучше, чем хитро —
::избыточен намеренно.
Python-биндинги живут по тем же правилам: никакой inference-ы схемы,
никакого авто-каста, никаких defaults. Хотите типизацию — делайте её
на границе своим инструментом (pydantic, dataclasses, attrs)
поверх нативных Python-структур, которые вернула эта библиотека.
spec— спецификация + conformance-тестыrust— эталонный Rust crate (cargo add ktav); этот Python-биндинг — тонкая PyO3-обёртка над нимcsharp— C# / .NET (dotnet add package Ktav)golang— Go (go get github.com/ktav-lang/golang)java— Java / JVM (io.github.ktav-lang:ktavна Maven Central)js— JS / TS (npm install @ktav-lang/ktav)php— PHP (composer require ktav-lang/ktav)
Пакет следует Semantic Versioning с pre-1.0
соглашением: минорный bump — ломающий. Версия Python-пакета и версия
крейта ktav движутся вместе. ktav.__spec_version__ показывает
версию формата Ktav, которую поддерживает данный биндинг.
Dev-окружение, структура тестов и процесс вклада описаны в CONTRIBUTING.md (и в CONTRIBUTING.ru.md).
У автора много идей, которые могут быть полезны IT во всём мире, — и далеко не только для Ktav. Их реализация требует финансирования. Если вы хотите помочь — пишите на phpcraftdream@gmail.com.
MIT. См. LICENSE.