This release is a pre-release and may not be stable for production use.
Toony
TOON serialization for Python, powered by an independent Rust engine.
Toony turns Python data into TOON text and back, with a
json-style API and optional Pydantic integration. Use it to place structured
records in an LLM prompt without changing your models, tool schemas or JSON
protocols.
Status: release candidate 0.1.0rc3, implementing TOON 4.4.0.
This is an independent project, not the official TOON Python package.
Install
python -m pip install toony==0.1.0rc3
uv pip install toony==0.1.0rc3
poetry add toony==0.1.0rc3
For Pydantic integration:
python -m pip install 'toony[pydantic]==0.1.0rc3'
Requires CPython 3.11–3.15. A matching wheel does not require Rust. Where a wheel is unavailable, installation builds from source and requires Rust 1.88+. There are no mandatory Python runtime dependencies.
To install directly from source:
python -m pip install 'git+https://github.com/aeespinosao/toony.git@v0.1.0rc3'
A familiar API
import toony
value = {"users": [{"id": 1, "name": "Ana"}, {"id": 2, "name": "Bo"}]}
text = toony.dumps(value)
print(text)
# users[2]{id,name}:
# 1,Ana
# 2,Bo
assert toony.loads(text) == value
dump and load accept caller-owned streams. encode and decode are aliases.
Defaults are two-space indentation, comma delimiter, strict decoding and no trailing
newline. delimiter="\t" and delimiter="|" are also supported.
with open("users.toon", "w", encoding="utf-8") as file:
toony.dump(value, file)
with open("users.toon", encoding="utf-8") as file:
restored = toony.load(file)
Use existing Pydantic models
from pydantic import BaseModel
from toony.pydantic import ToonTypeAdapter
class User(BaseModel):
id: int
name: str
adapter = ToonTypeAdapter(list[User])
text = adapter.dump_toon([User(id=1, name="Ana")])
users = adapter.validate_toon(text, toon_strict=True, strict=True)
assert users == [User(id=1, name="Ana")]
The adapter uses public TypeAdapter.dump_json() and validate_json() APIs.
Existing serializers, aliases, context and compatible inclusion/exclusion options
continue through JSON mode. No custom model base class or monkey-patching is needed.
TOON grammar strictness (toon_strict) and Pydantic strictness (strict) are separate.
TOON normalizes values: 1.0 becomes 1 and negative zero becomes 0. This can
change numeric union selection or strict validation. Pydantic's Decimal-as-string
serialization remains a string. The adapter does not override a validator's own
numeric precision rules.
LLM context, without changing protocols
import toony
context = toony.dumps({"users": [{"id": 1, "name": "Ana"}]})
prompt = (
"Read TOON data: array headers declare counts and fields; rows follow field order.\n"
+ context
+ "\nReturn the user IDs as JSON."
)
# Pass prompt to your existing model client.
Keep tool arguments, schemas and protocol envelopes in their native JSON contracts. Send TOON as text when it helps. Avoid passing the same context twice as both TOON and a second JSON rendering.
Runnable recipes are provided for LangChain, Pydantic AI, Strands and MCP. These frameworks are optional application choices, not dependencies of the core package.
For independent chunks with a verified token budget (this example needs
pip install tiktoken; any token-counting function can be supplied):
import tiktoken
from toony.context import iter_chunks
encoding = tiktoken.get_encoding("o200k_base")
records = [{"id": i, "name": f"User {i}"} for i in range(1000)]
for chunk in iter_chunks(
records, max_tokens=2000, count_tokens=lambda text: len(encoding.encode(text))
):
assert len(encoding.encode(chunk)) <= 2000
Each chunk is a complete document with a valid header/count and preserved IDs.
A single record that exceeds the budget raises OversizedRecordError; it is not
silently truncated. Account for your surrounding instructions separately.
Precision, limits and errors
from decimal import Decimal
import toony
number = Decimal("0.123456789012345678901234567890")
assert toony.loads(toony.dumps(number), parse_float=Decimal) == number
assert toony.loads(toony.dumps(2**100 + 1)) == 2**100 + 1
limits = toony.Limits(max_input_bytes=1_048_576, max_depth=32)
restored = toony.loads("id: 1", limits=limits)
Supported inputs include JSON types, tuples (normalized to lists), finite Decimal
values and custom types normalized with default=. Dictionary keys must be strings.
Default float decoding follows Python floating-point behavior; use numeric hooks
when exact decimals are required. Non-finite host floats normalize to null;
non-finite Decimal values are rejected.
Default protections are 64 MiB input, 256 MiB output, depth 128, 1,000,000 value
nodes, 16,384 fields per object and 4,096 characters per number. Python's own integer
conversion limits still apply. User callbacks can allocate independently.
ToonDecodeError, ToonEncodeError, ToonLimitError, ToonNumberError and
ToonCycleError distinguish failure types. Syntax errors include a stable code,
one-based line and bounded excerpt.
Experimental from_json and to_json convert directly in Rust without creating a
Python value graph. to_json returns bytes; JSON duplicate keys are rejected.
These paths may materialize a native tree and are not streaming APIs.
ASGI / Uvicorn
Install the asgi extra and see the Starlette application.
toony.asgi provides content negotiation, bounded request bodies and helpers that
offload synchronous conversions from the event loop. Uvicorn serves the application:
python -m pip install 'toony[asgi]==0.1.0rc3'
# Run from a checkout of this repository:
uvicorn examples.asgi_app:app
Traversal of Python objects holds the GIL. A thread offload is not a guarantee of uninterrupted event-loop responsiveness for large CPU-heavy conversions; measure your workload and use process workers when appropriate. An already-started thread operation may continue after its awaiting task is cancelled.
Measured performance
Measurements below use a local release build of the 0.1.0rc3 sources, on an Apple M4 (10 CPU cores, 16 GiB), macOS ARM64, CPython 3.14.7. Ten independent processes per codec/operation, seven samples per process, randomized order; intervals are 95% bootstrap intervals over process medians. Codec and inference runs are separate. The measured native-library hash is recorded in the data. Published wheels are built in CI; these timings are not measurements of every platform or interpreter.
For 20,000 uniform records, Toony encoding is 6.36 ms
and decoding 7.31 ms. toons encodes in
2.89 ms; Toony does not demonstrate general speed
superiority. JSON codecs produce a different representation. Text outputs are
aligned; orjson's bytes-to-text conversion is included in its encoding time.
Native TOON → JSON text conversion is 8.02 ms
for Toony versus 10.66 ms for toons.to_json,
a 24.8% reduction in this workload. This is a
specific measured path, not an across-the-board claim. Total process RSS did not
demonstrate a material improvement.
The token chart counts the complete prompt, including the TOON explanation,
against compact JSON. Small and irregular inputs show negative savings.
o200k_base is a representation comparison, not either local model's tokenizer.
Exact counts, instructions, both tokenizers (o200k_base, cl100k_base), dependency
versions and raw timing samples are in metrics.json.
The serialized bytes were verified unchanged from the token-counting run.
Validation: 610 tests passed on the locally installed rc3 wheel with CPython 3.14.7. The release workflow tests installed wheels for Python 3.11–3.15 on Linux x86_64 and macOS ARM64 before publication. Windows remains unvalidated. Earlier Linux ARM64 tests were executed on rc2. The Rust runtime sources are unchanged; the rc2 ASAN smoke covered 227,963 executions in 181 seconds. Release CI also runs a fresh sanitizer smoke. A four-hour campaign on this candidate remains pending.
Local-model follow-up (executed on 0.1.0rc2): 336/336 tasks completed; allocated context 16,384, actual comprehension prompts 1012–15272 tokens, temperature zero, two repetitions and at most one syntax/schema repair.
-
qwen3:8bcomprehension: JSON 36/48; TOON 26/48 correct. -
llama3.2:3bcomprehension: JSON 28/48; TOON 12/48 correct. -
qwen3:8bgeneration: JSON text 24/24; TOON text 24/24; native JSON schema 24/24 correct. -
llama3.2:3bgeneration: JSON text 12/24; TOON text 0/24; native JSON schema 20/24 correct. -
qwen3:8b: 25.1% fewer input tokens; 3.7% more total tokens per correct comprehension task, including all attempts. -
llama3.2:3b: 34.2% fewer input tokens; 53.6% more total tokens per correct comprehension task, including all attempts.
These model results characterize the TOON representation; identical serialized text from another implementation produces the same prompt.
Live framework smokes produced the expected result in 3/8 calls. Other calls returned incorrect/empty data or no usable structured result. API contract tests passing does not guarantee model comprehension.
Whiskers are 95% bootstrap intervals clustered by source document, not questions or repetitions. First-prefix requests unload the isolated runner before each document, format and repetition; they include model loading. The next three questions share that document prefix. OS file caches are not flushed. Observed cached-token counters are retained in the data; these phases are not isolated cold-hardware versus warm-hardware tests.
The rc3 runtime code is unchanged apart from version metadata. Serialized inputs and parsing outcomes were checked against rc2; this model study was not rerun or relabeled as an rc3 execution.
There are only six independent source documents per model. The non-inferiority result at a two-percentage-point margin is inconclusive. Generation uses an explicit TOON syntax primer and is a distinct experiment. No energy or monetary savings were measured. Only one model was resident during scored inference; these are local-host measurements rather than isolated hardware or energy measurements.
Token reduction comes from the TOON representation, not the Rust implementation. Uniform tables can benefit; small or irregular documents can cost more tokens, especially after format instructions. A shorter prompt does not guarantee better model accuracy or lower end-to-end latency. Benchmark your data and model before switching a production workflow.
Build, test and benchmark
uv sync --frozen
uv run pytest -q
cargo test -p toony-core --locked
cargo fmt --all --check
cargo clippy --workspace --all-targets -- -D warnings
uv run mypy --follow-imports=silent tests/typing_check.py
uv run ruff check python tests examples benchmarks
uv build --wheel --sdist
The test suite includes all 564 pinned official fixtures, property tests, precision, limits, cycles, callbacks, Pydantic, chunking and HTTP integration. Run the benchmarks independently of model inference:
uv run python -m benchmarks.run --repeats 10
uv run --with matplotlib python -m benchmarks.plot
The benchmark harness currently measures RSS on macOS/Linux. It uses fresh processes, seven samples per process, seeded task order, bootstrap intervals and explicit compatibility exclusions. Raw JSON is retained; no performance threshold is used as a substitute for correctness.
The release workflow builds and tests installed wheels on Linux and macOS for
Python 3.11–3.15, publishes to TestPyPI, verifies installation, then publishes to
PyPI for matching v* tags. Credentials live in GitHub environment secrets.
Windows checks remain available through the manual test workflow; a configured
job does not mean that platform has been validated.
License and provenance
MIT. The Rust TOON engine is original to this project, written from the specification. Official compatibility fixtures are pinned in fixtures/manifest.json and retain their upstream license. Runtime/build dependency licenses are included in THIRD_PARTY_NOTICES.md.
Metadata
Release files for toony 0.1.0rc3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| toony-0.1.0rc3.tar.gz | 582.8 kB | Without provenance | Details for toony-0.1.0rc3.tar.gz |
Built distributions (wheels)
Total release size: 4.8 MB
Release files / toony-0.1.0rc3.tar.gz
| Download URL | toony-0.1.0rc3.tar.gz |
|---|---|
| Size | 582.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6c4efc50208751967b4f4bdc623d41c2be1c6f4fd56dd49fb24f05818adb803c
|
|
BLAKE2b-256 checksum How to use checksums |
ef4013f006236c002655c493b4a2613c74c54b0551b1d81724a899908656666b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / toony-0.1.0rc3-cp315-cp315-manylinux_2_28_x86_64.whl
| Download URL | toony-0.1.0rc3-cp315-cp315-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 444.3 kB |
| Tags | CPython 3.15 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
bc011be94ed3a5869d124e9324931d7922cde0832d245ee6f30b515b09982bda
|
|
BLAKE2b-256 checksum How to use checksums |
2d56cdadd1ec86452edd31642910efdcc36d6f413bcbe015037dd052399ac682
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / toony-0.1.0rc3-cp315-cp315-macosx_11_0_arm64.whl
| Download URL | toony-0.1.0rc3-cp315-cp315-macosx_11_0_arm64.whl |
|---|---|
| Size | 400.1 kB |
| Tags | CPython 3.15 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
e4975868630479ed666771217bf6782a0c698687a577a29e40d69dbc874a3a31
|
|
BLAKE2b-256 checksum How to use checksums |
657c034547c7c48d4fd07742eeea2653526a18ead12d9f700b5fcb0e5e441301
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / toony-0.1.0rc3-cp314-cp314-manylinux_2_28_x86_64.whl
| Download URL | toony-0.1.0rc3-cp314-cp314-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 444.1 kB |
| Tags | CPython 3.14 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
8edeea57eb1d3e0ebde9d6f29ad4ebaba8c62623194afc76488cc0a02a06223f
|
|
BLAKE2b-256 checksum How to use checksums |
337f4922e5e16f107ce759e7943fe9c506d3c8634f84f296e1a325ed4f641d64
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / toony-0.1.0rc3-cp314-cp314-macosx_11_0_arm64.whl
| Download URL | toony-0.1.0rc3-cp314-cp314-macosx_11_0_arm64.whl |
|---|---|
| Size | 399.9 kB |
| Tags | CPython 3.14 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
b551969ca6bc7f05ce5c77f446cab9a050f7382493ea2c3f3b384ee9653f9896
|
|
BLAKE2b-256 checksum How to use checksums |
c0f29e6d4791d82707aaade7cb63b25750e0253bd485ee18507c7d19064076ca
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / toony-0.1.0rc3-cp313-cp313-manylinux_2_28_x86_64.whl
| Download URL | toony-0.1.0rc3-cp313-cp313-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 444.0 kB |
| Tags | CPython 3.13 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
1b77aac83c77d9190d28406a113f68f0a7922163a4671d7450e0adba733eca6a
|
|
BLAKE2b-256 checksum How to use checksums |
1d4b8ebb0f3c6399d40db10d7efa6d227426f966ae77f5033c3efc31fbb4c5f4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / toony-0.1.0rc3-cp313-cp313-macosx_11_0_arm64.whl
| Download URL | toony-0.1.0rc3-cp313-cp313-macosx_11_0_arm64.whl |
|---|---|
| Size | 399.7 kB |
| Tags | CPython 3.13 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
4f0195c42e89c0e68547e2e8e633dffec6ba339357d4c862dc62b565115022f5
|
|
BLAKE2b-256 checksum How to use checksums |
61e62c004c8a0904f2499365ca4e0a751c3551e9422f1e80fbbea02c6d790df3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / toony-0.1.0rc3-cp312-cp312-manylinux_2_28_x86_64.whl
| Download URL | toony-0.1.0rc3-cp312-cp312-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 444.2 kB |
| Tags | CPython 3.12 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
3a02ef3e05c2334384400d3c7e854ad8c67f3294fe7ef95a1ee9d1b6a483efb8
|
|
BLAKE2b-256 checksum How to use checksums |
bd57b2860bda27935649d037a51a3561c54e3cfabb03d5b35c365e2181d1f18d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / toony-0.1.0rc3-cp312-cp312-macosx_11_0_arm64.whl
| Download URL | toony-0.1.0rc3-cp312-cp312-macosx_11_0_arm64.whl |
|---|---|
| Size | 400.0 kB |
| Tags | CPython 3.12 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
a67a2f46d68a2c89739bcdd73030ce83891a141576a830dce90d1b98af412f85
|
|
BLAKE2b-256 checksum How to use checksums |
1803e3a5acfc4e06d7c39e6a37849f3ba51e9ea1a88a0dfcfead2d9f45a0b8ec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / toony-0.1.0rc3-cp311-cp311-manylinux_2_28_x86_64.whl
| Download URL | toony-0.1.0rc3-cp311-cp311-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 444.9 kB |
| Tags | CPython 3.11 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
5a2c317226f3be258b154030f9e37f593c5a0ba292bab2eb10d0d2ba5cb9772e
|
|
BLAKE2b-256 checksum How to use checksums |
821de33c6650562633e0c4eae44a4f510bbc305ac99e96131dd801ef2ae45881
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / toony-0.1.0rc3-cp311-cp311-macosx_11_0_arm64.whl
| Download URL | toony-0.1.0rc3-cp311-cp311-macosx_11_0_arm64.whl |
|---|---|
| Size | 403.1 kB |
| Tags | CPython 3.11 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
7a37fc61e14d4c41e52f3e1243f1218fdb5b187f65387ddf8850fb75db94f072
|
|
BLAKE2b-256 checksum How to use checksums |
744bbe095f6c87568dd4a8172a2b92f719809970009aff780f80f65b5b41b749
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Security for toony 0.1.0rc3
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.