0.0.16 cohort: tabular data, schemas and developer views¶
Published on 2026-10-06. Every workstream in the
0.0.16 plan is merged, the release test below passed
on the integrated tree, and every package is on crates.io and PyPI,
published from main at c287f1f; see Publication.
0.0.16 makes data, schemas and the developer's own artefacts readable in the terminal:
- Tabular data, in a new crate,
rs-rich-data: one row-source contract with CSV/TSV (the readerrich --csvuses, now shared), JSON Lines, serde and Arrow adapters; type inference with its evidence; column statistics; profiles with distributions and a missing-value map; data-quality reports; SQL result sets; and windows of sources too large to hold. - Large tables, in
rich_ext::table: a virtualised table that draws one window of millions of rows in constant memory, and conditional style rules. - Schemas: a format-neutral schema model read from JSON Schema, SQL DDL and
Arrow; trees, diffs with breaking changes marked across formats, and a
timeline of versions; ER diagrams through
rs-rich-diagram, whose layout now draws DOT cluster frames and honoursrank=same. - Developer views: merge-conflict views (
rich diff --conflicts), a record inspector, and Cargo supply-chain reports from what Cargo and its tools already wrote (rich deps --features/--timings/--audit/--licenses). - From the shell and Python:
rich profile,rich schemafor SQL and Arrow with--er,--inferfor file tables, andrs_rich.data.
A default build of rs-rich is unchanged, still 0.0.9, and still renders
exactly like upstream rich 15.0.0.
Independent package versions¶
| Package | Version | Release role |
|---|---|---|
rs-rich-data |
0.0.1 (new) | Row sources, CSV/TSV, JSON Lines, serde and Arrow (arrow) adapters, inference, statistics, profiles, quality reports, SQL result sets, windows, ER bridge (er) |
rs-rich-diagram |
0.0.2 | Cluster frames, rank=same, rich_diagram::er |
rs-rich-mermaid |
0.0.5 | Manifest only: requires diagram 0.0.2 |
rs-rich-ext |
0.0.14 | Schema model, virtualised tables, style rules, record inspector, conflicts, supply-chain reports |
rs-rich-micro |
0.0.3 | Manifest only: requires ext 0.0.14 |
rs-rich-record |
0.0.4 | record::write_selected; requires ext 0.0.14 |
rs-rich-interact |
0.0.4 | Manifest only: requires ext 0.0.14 |
rs-rich-cli |
0.0.16 | rich profile, rich schema SQL/Arrow/--er, --infer, rich deps reports, rich diff --conflicts; new off-by-default arrow feature |
rs-rich on PyPI |
0.0.5 | rs_rich.data and the new views |
rs-rich 0.0.9, rs-rich-macros 0.0.3, rs-rich-plugin-api 0.0.3,
rs-rich-art 0.0.12 and rs-rich-lumis 0.0.3 do not change.
What changed¶
The changelog has the full list. By workstream:
| Workstream | Pull request |
|---|---|
| Plan | #661 |
1. Tabular foundation: rs-rich-data, the shared CSV reader, JSON Lines, serde and Arrow, inference, statistics, style rules |
#662 |
| 2. Large and SQL-shaped tables (#260, #235) | #667 |
3. Profiling and data quality, rich profile (#343–#346, #269) |
#667 |
| 4. Schemas: the model, SQL DDL, Arrow, diffs, timeline, ER diagrams, DOT cluster frames (#268, #342, #347, #247, #240) | #666 |
5. Records and conflicts (rich diff --conflicts) |
#663 |
| 6. Cargo and the supply chain (#419, #420, #421, #330, #418, #331) | #664 |
| 7. The CLI, Python and docs | #668 |
rs-rich-record integration feedback (write_selected) |
#665 |
| Release test | this release's release-test pull request |
Migration¶
SchemaTree::schema()returnsOption<&Value>(Nonefor a tree built from a model).SchemaTree::newand JSON Schema output are unchanged.rich schemasanitizes by default, likerich viewand the textrich diff: terminal controls in schema names show as inert text.--no-sanitizelets them through.rich deps --duplicatesadds the consolidation summary after its existing output.- DOT clusters are framed. A DOT graph with
subgraph cluster_*now draws its frames instead of a note; graphs without clusters orrank=samedraw exactly as before. - New feature flags:
rs-rich-data'sarrowander, andrs-rich-cli'sarrow(Arrow IPC schemas inrich schema), all off by default.
Release test¶
Run on the integrated tree (main at 5f1aca5 plus this release test's
fixes) on 2026-10-06:
| Check | Result |
|---|---|
scripts/validate_release.py --tag rs-rich-cli-v0.0.16 |
passed: 3,251 tests in 223 suites, 2 ignored |
| Golden fixtures | regenerated byte-identically against Python rich 15.0.0 |
scripts/diff_rich.py |
57 cases match Python rich 15.0.0 |
release_cohort.py check and tag --dry-run |
every manifest matches; would tag exactly the 9 packages above, skipping the 5 already published |
Docs tapes (rich record --check) |
29 tapes, 85 screenshots unchanged |
| CLI reference, manifest-version tables, micro gallery, Python API pages | all up to date (13 micro assets, 102 API pages) |
| MSRV | Rust 1.90: the workspace, and the CLI with every feature including arrow; Rust 1.91: rs-rich-lumis and the CLI with all features |
Python wheel (rs_rich-0.0.5, abi3) in a fresh virtualenv |
1,259 passed, 1 skipped (no mmdc); rich-rs --version is 0.0.16 |
Python sdist (rs_rich-0.0.5.tar.gz) |
builds and installs from source in a fresh virtualenv; rs_rich.data reads CSV, profiles it and reads SQL DDL; rich-rs profile works |
Consumer install (cargo install --path crates/rich-cli --features arrow) |
rich 0.0.16; rich profile, rich schema --er and Arrow schemas work |
| Docs sites | mkdocs build --strict passes for both sites |
| Security | cargo audit clean for the workspace (401 crates) and rich-py (324 crates) |
What the release test found and fixed¶
Three independent audits covered the whole 0.0.16 delta: rs-rich-data
with rich profile and --infer; the schema model, SQL DDL, diffs,
timeline, DOT clusters, ER diagrams and rich schema (correctness and
security); and the conflict and record views, virtualised tables, style
rules, the Cargo supply-chain reports, rs-rich-record's
write_selected and rs_rich.data. They found 36 issues, and all are
fixed. Each was reproduced first, then fixed with a regression test that
failed, hung or panicked before the fix. The main ones:
- Panics on untrusted input. An Arrow IPC file whose footer lists a
dictionary block with a negative length panicked inside
arrow-ipc(arrow::read_schemanow reads only the footer's schema and checks its length), andCREATE TABLE t (a INT, FOREIGN KEY REFERENCES u)panicked the SQL reader. - Time and memory from small inputs. One JSON Lines record of 40,000
keys took 16 s (a 64 MiB line would have taken days); keys first seen after
the sample were kept without limit; a 6 MB file of mismatched conflict
markers took 144 s;
rich depsover 30,000 workspace members took 95 s; the SQL reader held every token at once (a 16 MB file peaked at 2.3 GB) and placed tables and key columns quadratically (100,000 tables took 272 s); andSchemaDiff,SchemaTimeline, nested DOT clusters and ER key resolution had quadratic paths (one ran past 20 minutes). Each is now linear or bounded, with the new limits documented. - Terminal escapes. Text from a crafted
cargo audit,--timings, licence or metadata file reached the terminal raw through the supply-chain reports (retitling it, clearing it, or forging a link); it is now sanitized when drawn.rich schemaignored--sanitize, and now, likerich viewand the textrich diff, sanitizes by default. Review of this release test also made it sanitize the file's name everywhere, keep DDL whitespace intact, and keep JSON property names that collide once sanitized. - Wrong results. SQL columns named
key,indexorperiodwere dropped; PostgreSQL$$function bodies were read as SQL; DDL without semicolons silently lost every table after the first; SQL Server'sPRIMARY KEY CLUSTEREDfailed the file;rich schema /dev/stdinlost its first six bytes; statistics went to NaN or infinity on huge or infinite floats; streamed CSV and whole-file CSV disagreed on byte-order marks; a CVSS vector repeating a metric was scored; lower-case SPDX copyleft identifiers went unrecognised; and integer style rules compared throughf64. - Layout.
rich profiledrew wider than its width between about 40 and 80 columns, and the schema timeline's "N more fields" count never showed. - Python.
Profile(bins=10**9)hung the interpreter,VirtualTablecopied every row on each call, and a JSON SchemaSchemaErrorlacked thelineits stub promised.
The micro-doctor docs tape also lost a keystroke once, typing before the
shell's prompt returned; it now waits for the prompt.
Known limits¶
- Cross-format schema diffs are noisy. Types compare by their source
names, so JSON
stringagainst SQLTEXT, orintagainstinteger, is a type change, andINT → BIGINTor a newNOT NULLcolumn with a default counts as breaking. Unquoted SQL names are case-sensitive. - SQL dialects. The reader covers a
CREATE TABLEsubset; MySQL backslash escapes in strings are not read, andCHECKconstraints, indexes and other statements are skipped with a note. - Mermaid subgraphs are still not framed (DOT clusters are). ER edges attach to a table's box, not the column's row.
- Narrow widths. Below roughly 8 to 36 columns, depending on the data,
core
Tableborders draw wider than the width; zero-width characters in cells can measure one or two cells off. Both are core behaviour. - Library renderables pass text through.
ConflictViewcontent,VirtualTablecells and the record view's title render input as given, like corerich; the CLI sanitizes at its own boundary. - Cargo metadata files have no input-size cap (nesting is capped at 128 levels), and feature requests miss crates whose library name differs from the package name.
- Python has no Arrow and no conditional table styles yet.
- Real graphics terminals. As before, the PTY tests check the bytes and cells around each graphics protocol, not the images.
Publication¶
RELEASES.toml lists every package's version in publication order. Tag what
is due on the merged commit on main:
python3 scripts/release_cohort.py status # what is published, tagged, or due
python3 scripts/release_cohort.py tag --dry-run # what it would tag
python3 scripts/release_cohort.py tag # tag and wait, one at a time
tag skips the packages already on crates.io and pushes one annotated tag at
a time, waiting for each version to appear on its registry before the next:
rs-rich-diagram-v0.0.2;rs-rich-mermaid-v0.0.5;rs-rich-ext-v0.0.14;rs-rich-micro-v0.0.3;rs-rich-record-v0.0.4;rs-rich-interact-v0.0.4;rs-rich-data-v0.0.1, the new crate, then its Trusted Publishing entry;rs-rich-cli-v0.0.16;python-v0.0.5.
crates.io offers Trusted Publishing only on a crate that already exists, so
rs-rich-data 0.0.1 uploads with the crates-io environment's
CARGO_REGISTRY_TOKEN: the workflow sees that the crate is new and uses it
for that upload only; add its Trusted Publishing entry afterwards. See
Registry authentication.