math_spec.serialisation
The waist as a value another language can read.
A consumer written in Python imports :class:~math_spec.program.Program and is
done. A consumer written in anything else has, until now, had one way to reach
the same model: implement the language a second time — a second parser, a second
name resolution, a second dim algebra — which is the one thing hard rule 1
exists to forbid. Two implementations of name resolution is the failure the
whole design is built to prevent, and shipping the waist only as importable
Python quietly guarantees it.
So the program is written as JSON, and read back from it. Everything in a program is already resolved, so the form carries no grammar, no expression strings and nothing to parse: a reader dispatches on a tag and builds a node.
Every node is tagged with its class name and nothing else is. A dataclass or
named tuple becomes an object carrying $; a mapping becomes an object
without one; a tuple becomes an array. That is the whole encoding, and it is
reflective rather than hand-written so a node added to the program is
serialisable the day it exists — tests/test_program_nodes.py already refuses
a node no file reaches, so the round trip covers every node by construction.
Reading is closed. A tag is looked up in a registry built from the two modules that define nodes; nothing is imported, evaluated or constructed by name from the document. An unknown tag is refused naming it, which is what lets a reader of a newer document say so rather than guess.
NOT_FINITE = {'inf': math.inf, '-inf': -math.inf, 'nan': math.nan}
module-attribute
#
TAG = '$'
module-attribute
#
WIRE_VERSION = 0
module-attribute
#
from_json(text)
#
The program a document holds.
Nothing is imported or evaluated: a tag names a class in a closed registry or the document is refused.
| PARAMETER | DESCRIPTION |
|---|---|
text
|
What :func:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Program
|
The same :class: |
| RAISES | DESCRIPTION |
|---|---|
LanguageError
|
The document is not one this release can read — a wire version it does not know, or a tag naming no node. |
Source code in src/math_spec/serialisation.py
to_json(model, *, indent=None)
#
A model as the JSON a consumer in any language reads.
| PARAMETER | DESCRIPTION |
|---|---|
model
|
Whatever every other verb takes — a YAML path, a mapping, a
loaded :class: |
indent
|
Passed to :func:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
str
|
Strict JSON — no |
str
|
in another language refuses. |
| RAISES | DESCRIPTION |
|---|---|
LanguageError
|
The model is not one, named with its rewrite. |