See what was available at the time, not only what a source says today. Historical rows include their source and availability timestamps. Training tables also include the decision cutoff. Live methods return the same core fields.
1from datetime import date 2from mostlyright import weather 3 4# official outcome + observed features, joined as-of time 5table = weather.training_table( 6 "KNYC", date(2025, 1, 6), date(2025, 1, 12) 7)
1import { trainingTable } from "mostlyright"; 2 3// parallel 2.0 call; inspect runtime-specific fields 4const { rows } = await trainingTable("KNYC", "2025-01-06", "2025-01-12");
Historical reads return source and availability times. Training tables add cutoff fields. Live methods return the same core fields.
Build a view from information available by the research cutoff, not later revisions.
Rows include their source and available timing fields. Training tables add decision and knowable-at cutoffs.
Pin normalized inputs locally so the same research window can produce the same rows.
Historical and live methods use the same parser and core fields.
Historical calls fetch and normalize upstream sources in your own runtime. They can
write a parquet or JSON cache under ~/.mostlyright/cache/
(Python) or ~/.mostlyright/cache-ts/ (Node), so a later rerun
does not silently change the inputs underneath the result.
# weather · shipping example cache/ ├─ weather/NYC/2025-01.parquet ├─ weather/AUS/2025-01.parquet └─ _manifest.json # contract + source ids # pin a single source (provenance) train = weather.observations("KNYC", ..., source="iem") validate_dataframe(train, "schema.observation.v1")
| Concern | Hand-rolled scrapers | Mostly Right |
|---|---|---|
| Reproducibility | drifts with live endpoints | byte-stable cache |
| Schema validation | ad-hoc per source | schema.*.v1 + validator |
| Training / live match | silent corruption | fails loudly on mismatch |
| Python ↔ TypeScript | two codebases | cross-SDK schema tests |