Skip to main content

Yapyon (やぴょん)

「YAMLちゃうで。やぴょんやぴょん」 ( It ain't YAML. It's Yapyon.🐇)

Yapyon is a Python-style typed literals with YAML-like block structure, including...

# Comments!

features:
  explicit_literal_types: True        # 'no' != False... or Norway
  lexeme_preserving_templates: True   # 3.10 is displayed 3.10, not 3.1!

ambiguous_conversions: None

builtin:
  - 'byte_encodings'           # Standard, base64, crockford32, hex, etc...
  - 'serializers'              # To JSON, YAML, TOML, and of course Yapyon!

types:
  scalar: ['bool', 'int', 'float', 'str (always quoted!)', 'None']
  containers: ['list', 'dict', 'multimap', 'bytes', 'template strings']

encodings:
  + bytes: b'Python-style' # Same as it ever was...
  + bytes: dna'GATTACA'    # Base-4... and more!
  + int: 0z1A              # Crockford base32 (42, naturally)

The pitch: the same bytes with the same inputs yield the same data, to every parser, on every machine, always. There's no implicit typing: no is not False, and strings are always quoted; there are no anchors or tags, one null spelling, and one document per file. A repeated key in a map is an error, never an uncaught typo silently overwriting data.

Quick-Start Guide

Yapyon is just a pip / pipx / uv install away:

$ pip install yapyon

It can be quickly tested, too:

>>> import yapyon
>>> yapyon.loads('name: "gw"\nport: 8080\naddr: y"{name}:{port}"\n')
{'name': 'gw', 'port': 8080, 'addr': 'gw:8080'}

The loads and load functions return plain Python. Types include builtin Python types as well as OrderedMultimap (+-syntax) and Template (yt-string).

Some other quick commands:

$ python -m yapyon record examples/registry.yap  # A Yapyon record
$ python -m yapyon lexer  examples/gateway.yap   # token dump
$ python -m yapyon parser examples/gateway.yap   # AST dump
$ python -m yapyon tier   examples/gateway.yap   # tier 3 — it carries a yt
$ python -m yapyon expand examples/bridge.yap    # a ledger in, a record out

Diagnostic Terminology

shiran: (warning) → akan: (error) → yakamashiwa: (internal bug). Verbose success prints ええやん.

Document Variants

A document is one of four kinds (discoverable via yapyon.tier_of():

  • record: literals only (no resolver / resolution process)
  • ledger: splices & calls built-ins; resolves internally
  • template: incorporates external data (e.g., environment variables)
  • assembly: calls functions that a contract declares; can be assembly from multiple files

Yapyon has no ambient scope nor includes and is built to be completely auditable / verifiable.

Element References

A hole names a value. The shortcut style a.b is syntactic sugar for(equivalent to) a["b"].

protocol: "messenger"
mind:
  endpoint: "https://api.server"
  dialects:
    messenger:
      api_uri: y"{endpoint}/v1"  # reaches its 'uncle' (mind.endpoint)
    icq:
      api_uri: y"{endpoint}/chat"
  chosen: y"{dialects[protocol].api_uri}"   # "https://api.server/v1"
Spelling Means
{a.b} the key b — canonical for identifiers
{a["b.c"]} a key a dot cannot reach
{xs[0]} a list position; brackets only, since 0 is no identifier
{d[p]} the key stored in p, resolved in the y-string's own scope
{mm.k} every value filed under k in a multimap, in order, as a list

{a["bar"]} where a dot would do is a shiran — legal, but say {a.bar}. Because the enclosing string's delimiter ends it, quote a key with the other mark: y"{a['b']}".

Relative References

__ROOT__ names an absolute position; __PARENT__ and __KEY__ name relative ones, so a block can refer to where it is:

store: "/cfg"
personas:
  kisama:
    id:     y"{__PARENT__.__KEY__}"              # -> "kisama"
    prompt: y"{__ROOT__.store}/{__PARENT__.__PARENT__.__KEY__}/{__PARENT__.__KEY__}.md"

The same text in every block, each resolving to its own name — without them a block cannot be renamed or moved without editing its contents. __PARENT__ repeats ({__PARENT__.__PARENT__.x}) and leads a reference; __KEY__ ends one. Bare {__KEY__} is the pair's own key, which is rarely what you want.

Serializers

A container cannot be spliced into text — there is no one text form and picking one would be guessing. Naming the encoding is how it crosses:

store:
  model: "m1"
  host: "https://api.example.com/v1"
body: y"{store.__AS_TOML__()}"
model = "m1"
host = "https://api.example.com/v1"

__AS_JSON__(), __AS_TOML__(), __AS_YAML__(), and __AS_YAPYON__() are the format's built-in functions, all written without a runtime dependency, and their output is fixed exactly by SPEC §14 — layout included, so every implementation writes the same text. Keys stay in document order and nothing is pruned. Where a format cannot carry a value directly, the serializer approximates it by that format's own means rather than refusing: bytes become base64url text and a 0xff its value, each with its yapyon spelling recorded beside it in an @_lexemes member; a multimap becomes a JSON-LD node, TOML dotted keys, or YAML !!pairs under a %TAG handle; TOML leaves out a None and records it. A reader that knows the conventions gets the yapyon value back; one that does not still gets correct plain data. YAML scalars are quoted unless every reader would read them as strings, so "no" and "3" survive as strings. {cfg.__AS_JSON__(lexemes=False)} writes the plain values alone.

__AS_YAPYON__() writes the block as a yapyon record, every value as written: 3.10 still spelled 3.10, multimaps and bytes as themselves. The only thing any serializer refuses is a yt, which has no record form, and __AS_TOML__() refuses what is not a table, since TOML has no top-level form for anything else.

A serializer names the value it encodes, so it cannot name a bare anchor: {__PARENT__.__AS_JSON__()} would have to encode the string it is computing, and is akan. Reach past the anchor — {__ROOT__.blk.__AS_JSON__()} — which is the shape you want anyway.

Functions and contracts

A hole may call a function — {match_first(supported, mind.dialects)}, or the receiver form {supported.match_first(mind.dialects)} — if the loader is given a contract declaring it. A contract is itself a record:

match_first:
  params:
    keys: "list[str]"
    items: "dict[str, dict[str, str]]"
  returns: "str"
  impl:
    python: {from: "persona_grata.dialects", symbol: "match_first"}
import yapyon

with open("functions.yap") as fp:
    contract = yapyon.load_contract(fp)
with open("persona.yap") as fp:
    data = yapyon.load(fp, contract=contract)

Without from, the loader supplies the code: provide={"match_first": fn}. Arguments may be named, as in Python — {match_first(supported, items=mind.dialects)} — by the contract's parameter names. Arguments are checked against the declared types before the call — deep, and reported where the offending value is written — and a container argument arrives as a read-only, ordered borrow of the document's node. The result is checked against returns and becomes fresh data. Calls nest and chain, and wait for their arguments like any hole, so two calls waiting on each other are reported as the cycle they are. A function that raises is akan naming it, never a traceback. The serializers are the format's built-in functions, called the same way and declared by the spec itself.

Resolving a reference from code

A consumer that assembles a tree from several loaded documents can resolve a reference against it by the same rules a hole uses, without writing its own copy of the search:

tree = yapyon.loads(base)
tree["harness"] = harness = yapyon.loads(harness_doc)
yapyon.lookup(tree, harness, "mind.dialects[protocol].api_uri")

current is the node you are holding, and the answer is the one a y"{...}" written inside it would get: its own keys first, then outward, nearest winning — which is why the tree comes too, since a dict does not know its parents. The whole hole grammar works, serializers included, and an indirect key like [protocol] resolves from current. It is the resolver's own search, so the two cannot disagree. A refusal is an AkanError naming where current sits.

Prefixes (Encodings)

Various binary representations are built into Yapyon to simplify data transfer.

bytes (byte strings)

Prefix Meaning Example Notes
b Standard bytes b'Python-style' Same as it ever was...
b64 RFC 4648 base64 b64'base64//RFC4648=' 4-symbol blocks (padded with '=')
c32 Crockford base32 c32'AllYerCrockford-base 0' Read c32'A11YERCR0CKF0RDBASE0'
hex Hexadecimal hex'badbeef' Read hex'badbeef0' (0-padded, right)
oct Octal oct'10111052' Read oct'10111052' (hex: 20 92 2A)
dna DNA Seq. (base4) dna'GATTACA' Read dna'GATTACAT' (hex E0 98) (0-padded, right)
bin Binary bin'100' Read bin'10000000' (hex 80) (0-padded, right)

int (integers)

Prefix Meaning Example Notes
None Base 10 4 Invented for counting on fingers
0b Binary 0b1000 Read 0b00001000 (0-padded, left)
0q Quaternary 0q33 Read 0q0033 (0-padded, left)
0o Octal 0o20 Read 0o020 (0-padded, left)
0x Hexadecimal 0x17 Read 0x17 (0-padded left; not shown)
0z Crockford base32 0z1A Read 0z01A (0-padded, left)

Variants: bytes / str

Prefix Meaning Example Pronunciation Notes
r Raw str r'chubby\bunny🐇' are-string Same as Python raw str
rb Raw bytes rb'Look\ma\no\escapes!' reeb string Same as Python raw bytes
y yapyon str y'Head like a {desc}' why-string str, spliced at parse
yb yapyon bytes yb'Head like a {desc}' yeeb-string bytes, spliced at parse (holes must be bytes or numbers)
yt yapyon template string yt'{part1}, {part2}' yeet-string Template, unjoined
ry raw yapyon string ry'{part1}{part2}' ree-string str, backslash literal

f"...", t"...", u"..." are errors with hints — their meaning depends on an enclosing scope, and a data file has none.

Metadata

Release files for yapyon 0.4.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for yapyon 0.4.1
File Size Uploaded Provenance
yapyon-0.4.1.tar.gz 302.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for yapyon 0.4.1
File Interpreter ABI Platform
yapyon-0.4.1-py3-none-any.whl Python 3 none any Details

Total release size: 428.2 kB

Release files / yapyon-0.4.1.tar.gz

Download URL yapyon-0.4.1.tar.gz
Size 302.5 kB
Tags Source
SHA-256 checksum
How to use checksums
6345a08444462f7c5f734262eb36d9d9c42f51a3cc3af1f997f5bb1194ec7892
BLAKE2b-256 checksum
How to use checksums
3e286a7bf1ef23a87b0dd2cffb52e21023a066530cad43339adb23611187a6b1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Release files / yapyon-0.4.1-py3-none-any.whl

Download URL yapyon-0.4.1-py3-none-any.whl
Size 125.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a93fb4edc8521951c8a945dfa3e8ac3f9e3311d8284e32382f138ebebddd1296
BLAKE2b-256 checksum
How to use checksums
f3b11ac8b7be4f35dec610274dc898c1d44d0e218c9b5e47688a08d2e8182d68
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Security for yapyon 0.4.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.

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