Document exports — _export#
A calculation document computes values that later stages need. For example, beam capacities feed a utilization check. Rather than the document writing a file as a side effect, it declares what it produces, and YMPrint writes it.
Declaring exports#
# 5-validation/beams/calc.yml
_export:
Vr: $V_r
Mr: $M_r
section: "{{ design[member_name].section }}"
Beam design – {{ member_name }}:
- _hc: |
V_r = 0.66 * phi * f_y * A_w
...
Exports are evaluated after the document’s content is built, so every _py and _hc
block has run. A $var exports the object itself; any other string is a Jinja template
(its result is text). Mappings and lists can nest. A missing variable is an authoring error
that names the document and its parameter set.
The value a reviewer reads in the PDF and the value the next stage uses are the same computation.
Exports as a data source#
A _data entry names its producers with from:. Consumers read it by name like any other
source; they never see a path. A producer can also be a Python script, which calls
publish() instead of declaring _export; see
Produced data — from: for the two side by side.
# project.ymprint.yml
_data:
capacities:
from:
- 5-validation/beams/calc.yml
- 5-validation/columns/calc.yml
_render:
5-validation/beams/calc.yml:
for_each: "[m for m in design if m.startswith('B')]"
as: member_name
output: build/beams/{{ member_name }}.pdf
# 5-validation/utilizations.yml
Utilizations:
- _py: |
dcr = {m: loads[m]["Vf"] / capacities[m]["Vr"] for m in capacities}
A document rendered once per parameter set produces one entry per set, under its key:
{"B01": {"Vr": ..., ...}, "B02": {...}}. A document without parameter sets produces its_exportmapping as is.Each producer’s output is written whole on every full render (
ym convert,Ymprint.render_all), so a deleted member disappears and render order doesn’t matter. Nothing needs to exist beforehand.Each producer has its own file, under
build/.ym/exports/. Consumers see the union of the producers’ mappings. Two producers giving the same key is an error: every value has exactly one author.Files are written atomically (to a temporary file, then renamed).
The
from:declaration is the only place the relationship is stated;ym builduses it to order the build.
Exports are not written when only some parameter sets were rendered (--only), or by
ym live and --var renders. If any parameter set fails, the producer’s previous output is
removed rather than left stale, so consumers fail loudly instead of reading old values.
A single producer at a fixed path#
A source with one producer can give a path, to put the file somewhere visible:
_data:
beam_capacities:
path: build/data/beam_capacities.json
from: 5-validation/beams/calc.yml
The build directory#
Produced data is stored under <project root>/build. Change it in the project config:
_build:
dir: _build
From Python#
run = app.render_all("5-validation/beams/calc.yml")
run.exports # {"B01": {"Vr": ..., "section": "W310x74"}, ...}
run.written # the export files written
event = load_report("calc.yml", "calc.pdf", vars={"member_name": "B01"})
event.exports # {"Vr": ..., "Mr": ..., "section": "W310x74"}
event.pdf # Path
Serialization#
JSON-native values are written as they are. Paths become strings, sets become lists, and
real numbers (including numpy’s) become numbers. Any other object is an error until a
serializer is registered for it. This includes a units quantity: its float() may be a
scaled display value (30.2 for 30.2 kN, 500.0 for 0.5 kN), so writing it would record a
wrong number.
A plugin registers richer types. A serializer that tags its output with "$type", together
with a decoder for that tag, makes the value round-trip, so whoever reads the data gets a
quantity back rather than a dict:
from ymprint import register_decoder, register_serializer
from ymprint.exports import TYPE_KEY
register_serializer(Quantity, lambda q: {TYPE_KEY: "mypkg.Quantity", "si": q.si, "unit": q.unit})
register_decoder("mypkg.Quantity", lambda m: Quantity(m["si"], m["unit"]))
See Plugins to register serializers when a package is installed.