PyTOON
PyTOON is a Python port of the excellent toon project by Johann Schopplich. It converts arbitrary Python data structures into the same concise, human-readable text representation produced by the original TypeScript encoder.
The goal of this repository is feature parity with the upstream project while providing a first-class experience for Python applications and tooling.
Contents
- Features
- Installation
- Quick Start
- Normalization Reference
- Encoding Behaviour
- Options
- Advanced Usage
- Testing
- Project Structure
- Versioning & Compatibility
- Contributing
- License
Features
- Normalises native Python types (dicts, lists, dataclasses, sets,
datetime, numeric edge cases, etc.) to a JSON-like value space before encoding. - Produces the familiar Toon text format with support for inline arrays, tabular object arrays, and deeply nested structures.
- Configurable indentation, row delimiter (
',','|','\t'), and optional length marker flag ([#N]style headers). - Safe string quoting and escaping rules that match the upstream implementation.
- Pure-Python, dependency-free package targeting Python 3.8+.
Installation
pip install pytoon-encoder
Working from a clone of this repository? Install in editable mode:
pip install -e .
Quick Start
from pytoon import encode
payload = {
"user": {
"id": 123,
"name": "Ada",
"tags": ["reading", "gaming"],
"active": True,
"prefs": [],
}
}
print(encode(payload))
Output:
user:
id: 123
name: Ada
tags[2]: reading,gaming
active: true
prefs[0]:
Normalization Reference
PyTOON first normalises values into a JSON-compatible shape. The table below mirrors the upstream Toon rules:
| Python value | Normalised result | Notes |
|---|---|---|
None |
None |
Encodes as null. |
bool, int, float |
Same numeric/boolean value | Floats that are NaN, ±inf become None; -0.0 becomes 0. |
str |
Same string | Subject to quoting/escaping rules during encoding. |
datetime, date |
ISO-8601 string | Uses .isoformat(). |
set, frozenset |
List of normalised elements | Order is the iteration order of the set. |
list, tuple, other sequences (not bytes) |
List of normalised elements | Preserves order. |
dict, Mapping |
Dict with stringified keys | Keys are coerced with str(key); values normalised recursively. |
dataclass instances |
Dict via dataclasses.asdict |
Deep conversion, then recurses. |
| Unsupported objects, functions, generators | None |
Matches behaviour of upstream encoder. |
Encoding Behaviour
PyTOON selects the most legible format while preserving structure:
- Objects render as
key: valuelines in insertion order. Empty objects emit justkey:. - Arrays of primitives appear inline:
tags[3]: a,b,c. - Arrays of objects become tabular if every object shares identical primitive keys. Otherwise, items are rendered as
-list entries. - Arrays of arrays with primitive inner arrays become nested lists; mixed or non-primitive inner arrays fall back to expanded list items.
- Mixed arrays (primitives, objects, arrays combined) always degrade to list entries.
- Strings remain unquoted only if they contain no structural characters, delimiters, leading/trailing whitespace, or ambiguous literals (
"true","42", etc.). Otherwise, they are quoted and escaped.
See examples/basic_usage.py for ready-to-run scenarios.
Options
encode accepts an optional EncodeOptions dictionary that mirrors the TypeScript API:
from pytoon import encode, DELIMITERS
encode(
{"items": [{"id": 1, "name": "Ada"}, {"id": 2, "name": "Bob"}]},
{
"indent": 4,
"delimiter": DELIMITERS["pipe"], # or ',' / '\t'
"length_marker": "#", # renders headers as [#N]
},
)
Output:
items[#2|]{id|name}:
1|Ada
2|Bob
Option reference:
| Option | Type | Default | Description |
|---|---|---|---|
indent |
int |
2 |
Spaces per indentation level for nested structures. |
delimiter |
',', `' |
', '\t'` |
',' |
length_marker |
'#' or False |
False |
When '#', emits headers like [#3]; helpful when the consumer expects marked lengths. |
Advanced Usage
- Pre-normalisation: Import
normalize_valuefrompytoon.normalizeto convert data once, then reuse the normalised structure across multiple encodings or transport layers. - Direct value encoding:
pytoon.encoders.encode_valueaccepts a pre-normalised JSON value plus resolved options, allowing integration with custom line writers or alternative indentation strategies. - Custom delimiters: The
DELIMITERSconstant exposes the supported delimiter characters. Pass alternate values (e.g.DELIMITERS["tab"]) to match TSV-style pipelines. - Examples: The
examples/directory contains scripts that highlight default behaviour and option combinations. Extend these for domain-specific onboarding material. - Automation:
.github/workflows/ci.ymlruns unit tests on every push and publishes tagged releases (v*) to PyPI once tests pass.
Testing
Tests use Python's built-in unittest framework:
python3 -m unittest discover -s tests
When porting new behaviour from toon, add corresponding tests here to keep parity strong.
Project Structure
pytoon/– Core encoder modules (constants,normalize,primitives,encoders,writer).tests/– Unit tests covering primitives, objects, arrays, options, and edge cases.examples/– Runnable scripts that demonstrate practical usage patterns.
Versioning & Compatibility
PyTOON targets Python 3.8+ and strives to remain aligned with the latest upstream toon behaviour. Breaking format changes follow upstream and will be clearly documented in release notes.
Contributing
Contributions are welcome! To get started:
- Fork and clone the repository.
- Create a virtual environment for Python 3.8 or newer.
- Install in editable mode with dev extras:
pip install -e .[dev]. - Run
python3 -m unittest discover -s testsbefore submitting a pull request.
License
PyTOON retains the licensing of the original toon project. Refer to LICENSE for details.
Metadata
Release files for pytoon-encoder 0.1.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 | Provenance | Actions |
|---|---|---|---|---|
| pytoon_encoder-0.1.1.tar.gz | 15.0 kB | Without provenance | Details for pytoon_encoder-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pytoon_encoder-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for pytoon_encoder-0.1.1-py3-none-any.whl |
Total release size: 26.7 kB
Release files / pytoon_encoder-0.1.1.tar.gz
| Download URL | pytoon_encoder-0.1.1.tar.gz |
|---|---|
| Size | 15.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5ee3ad6984efe553953c3c282020386eeeade59658dc0cb5ead1853499a742de
|
|
BLAKE2b-256 checksum How to use checksums |
1b7e7d6ff1f0450a687d0c22f8539c319f100bd6bbb0cace33ef9f64fa0b6ed1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / pytoon_encoder-0.1.1-py3-none-any.whl
| Download URL | pytoon_encoder-0.1.1-py3-none-any.whl |
|---|---|
| Size | 11.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2720349f4cf342c6126451a329da2f3a6f3fa27574e24f50d987da1e12d877f6
|
|
BLAKE2b-256 checksum How to use checksums |
60401afc7e86b2d7afba2271c60721d3d259a54c4434ecccc3c6ad3f071c3604
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Security for pytoon-encoder 0.1.1
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.