Skip to content

Releases: zelyph/SampleKit

SampleKit 1.0.0-rc.1

SampleKit 1.0.0-rc.1 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 28 Sep 08:34

The first release candidate of SampleKit 1.0, and a new SampleKit. Version
0.2.0 was a pure Python package for writing samples from a script. 1.0 keeps
its idea — a sample is a Markdown file, with its data at the top — and is
built around a command line and a full-screen terminal interface, written in
Rust, with a Python package beside them for your formulas and your scripts.
Both come from one source and carry one version (1.0.0rc1 for Python).

It does not read the files 0.2.0 wrote, and no command converts them: see
Upgrading from 0.2.0 below.

Added

The command line, samplekit, a program with no Python inside. Reading,
selecting, showing, checking and exporting samples never start Python.

  • samplekit FOLDER prints the path of each sample; with -c it shows a
    table of the columns you name, and with --profile a table declared in
    .samplekitrc. -f filters (-f 'og > 1.050 && tags has medal'), -s
    sorts, --group makes a table per value of a field, --summary summarises
    each column. --csv, --tsv and --json print the same table as data,
    and -o FILE --write writes it.
  • list enumerates what a collection holds and declares: its fields, tags,
    queries, profiles, exports, figures, a sample's own files, and the files it
    skipped and why.
  • view shows a sample whole: its values, then its tables, and its note with
    --note.
  • status lists every computed value that is not current, and why;
    status --exit-code makes it a check for continuous integration.
  • compute runs the model's formulas: alone it says what would run, with
    --try it computes and shows the results without writing, and with
    --write it writes each sample as soon as it is done. explain FILE FIELD
    says where one value came from, and prints a formula's error.
  • validate reports the defects of sample files and changes nothing.
  • new creates a sample from what the project already knows, set changes
    its values (set brew.md og=1.052 og.u=0.001, readings, table cells, the
    name), and tag add, tag remove and tag rename change its tags. Each
    shows what it would change and writes only with --write.
  • export NAME writes a table declared in .samplekitrc as CSV, TSV or
    JSON, after a preview; --status adds a column holding each row's state.
  • plot draws a figure with matplotlib, in a window or to a file: one
    declared in .samplekitrc or by the model, or one given by its axes
    (-x, -y), over properties, attributes or a table's columns.
  • open opens a sample's own files — photos, reports, raw data — which
    [collection] files says where to find.
  • init sets a project up: its .samplekitrc, a model to fill in or the
    one you name with --model PATH, and a Python environment, .venv/, with
    the SampleKit package installed in it. At a terminal it asks; --example
    writes a project that runs, one formula of every kind.
  • tui opens the full-screen interface on a folder, and samplekit alone,
    in a terminal, opens its start page.
  • completions sets up tab completion for bash, zsh, fish, elvish and
    PowerShell.
  • Every command has --help, with examples, and -h for a short summary.
    Errors name what was asked, what exists instead, and the nearest name. Exit
    codes tell a usage error (1) from a data error (2) and a file the system
    refused (3).

A history of every change. Before SampleKit writes to a project, it keeps
what the project held, in .samplekit/history/, beside .samplekitrc: the
sample files, the configuration and the model's source. There is nothing to
set up, and no Git to install.

  • log lists the snapshots, diff compares two states value by value
    (abv 6.8 ± 0.1 % → 7.2 ± 0.1 %), and restore puts files back: the last
    change taken back, or the state of a given snapshot.
  • --at reads the whole project as it was at a snapshot or on a date:
    samplekit brews -c name,abv --at 2026-09-12. An export made again this
    way is the same file, byte for byte.
  • A change made in your text editor is kept as a snapshot of its own, so it
    is never credited to the command that follows.
  • A Python script's writes are one snapshot, with the script's source: log --script N prints the script as it ran, and keep() marks a snapshot of
    its own from inside a script.
  • Every export and figure SampleKit writes is recorded. explain FILE finds
    it again, even copied into a manuscript's folder and renamed: what made it,
    from which samples, whether it is still current, and the command that makes
    it again.
  • log --export writes the history as Markdown, to share beside the samples.
  • One history over several computers: each writes its own branch in
    .samplekit/history/, and the next snapshot joins another computer's once
    your files hold its state — no command merges. log shows a machine
    column where more than one wrote, and an undo takes back only this
    computer's change. A synchronised folder shares it as it is; git, once the
    history's own .gitignore stops ignoring everything.

Current and outdated values. Every computed value carries a short record
of what it was computed from. SampleKit compares it with the file as it is
now, and knows — from the files alone, without running Python — which values
are outdated (an input changed), edited (typed by hand over the formula),
failed (the formula raised an error) or never computed. Your computer also
keeps a digest of each formula, so that editing a formula makes outdated only
the values it computed, and a comment or a docstring changes nothing. A value
whose input nobody entered yet waits for it, and is not an error.

  • The states appear in the same words everywhere: status, marks in tables
    (⚠ outdated, ✎ edited, ✗ failed), the TUI, Python. state is also a
    field: -f 'state == outdated', -c name,state.
  • A value typed over its formula is an override: compute leaves it
    alone until compute --force gives it back to its formula.
  • A formula that fails does not stop the run: the other values are computed,
    the file records the error's type, and the full traceback is kept for
    explain. An interrupted run loses only the sample in progress.

The full-screen interface, the TUI, for a project you work in every day.

  • A start page: recent projects, a new project set up by a few questions,
    a folder opened or configured, and the guide and demo.
  • The collection: filter, sort, group, choose columns, summarise, and
    save what it shows as a query, a profile or an export of the project.
  • A sample: its values, tables, readings and note, each value editable;
    its own files opened; a value computed, or everything not current.
  • The history: the snapshots, what each changed, and u to take the last
    change back.
  • The configuration edited from the TUI, and the colours set by role in
    [tui.colors].
  • Editing as in a text editor, wherever you type — the filter, a value,
    a name, a setting, the note: the mouse selects, by word on a double click;
    Shift and the arrows select; Ctrl and the arrows move by word;
    Ctrl+Backspace and Ctrl+Delete take a word out; Ctrl+Z undoes,
    Ctrl+Shift+Z redoes; Ctrl+C copies a selection, Ctrl+X cuts, and a
    paste goes where the cursor is. In the note, Markdown by keys: *, _ or
    ~ around a selection, Alt+1 to Alt+6 a heading, Alt+L a link,
    Alt+I an image, Alt+C a code block.
  • ? lists every key of the screen you are on.

A demo: a home brewer's notebook in eight steps, from three brews written
by hand to a model, tables, figures, two projects and Python. The start page
writes it for you (g), and it is also in the source, in examples/brewing/.

Several projects in one command. samplekit status ana/brews tom/brews
reads both; each sample keeps its own project's units, precisions, model,
queries and profiles, and the terminal shows one table per project.

New in the sample file (the format itself is under Changed):

  • n/a, not applicable: a value that does not apply to this sample, as
    distinct from one nobody has measured yet. A formula reading it gives n/a
    too, without running.
  • Attributes: facts about a sample — a style, a supplier, a date, a list
    of hops — with no unit and no uncertainty, filtered and shown like
    properties.
  • Tags, a deliberate label on a sample (tags: [medal]), reached by a
    filter (tags has medal).
  • A sample's own files — photos, reports, raw data — found by the
    sample's name where [collection] files says, and opened from the command
    line, the TUI or Python.

A project's configuration, .samplekitrc, in the project's folder: the
model; queries, profiles, exports and figures by name; how a unit is shown in
a table, in LaTeX and on a figure ([unit.*]); the precision, symbol and unit
of each quantity, declared once ([property.*]); matplotlib's settings;
which files are samples. Every key is checked: a misspelt one is an error
that names the line and the nearest valid key.

  • import = ".." takes the configuration of the folder named, merged key
    by key beneath this one: what several collections share is declared once,
    at their common root, and each collection keeps its model and what is its
    own. Imports chain; a loop is refused. A relative path reads from the file
    that declares it, and {collection} names a sample's collection folder in
    [collection] files and an export's output.
  • What the current folder offers: list profiles, queries, exports
    and figures, the completion and the TUI's f show the configuration of
    the folder a command runs from, with what it imports, each name marked
    local or with the file it comes from. A sample still follows its own
    collection's configuration wherever the command runs from.
  • validate notes a declaration identical to the one imported, a copy to
    ...
Read more

v0.2.0

Choose a tag to compare

@zelyph zelyph released this 15 Apr 16:32

Breaking changes

  • Sample signature: Sample(name, filepath) → Sample(path, name). path is now the first positional argument.
  • self.path is now a public attribute (was self._filepath).
  • save()/load() parameter renamed from filepath to path.

Install

pip install --upgrade samplekit

v0.1.2 - Bugfix

Choose a tag to compare

@zelyph zelyph released this 15 Apr 16:17

Fixes

  • Sample(filepath=...) not loading file: _auto_hydrate() was never called for direct Sample instances because __init_subclass__ only wraps subclass __init__. Added explicit call guarded by type(self) is Sample.

Install

pip install --upgrade samplekit

v0.1.1 - Bugfix

Choose a tag to compare

@zelyph zelyph released this 14 Apr 08:42

Fixes

  • precision_unc not propagated from columns: the order of operations in _apply_column_meta prevented precision_unc from being copied when precision was also defined on the column
  • Double-escaping of unit_math in reports: LaTeX special characters (%, #…) were escaped a second time in unit_math, which already contains valid LaTeX

Install

pip install --upgrade samplekit

v0.1.0

Choose a tag to compare

@zelyph zelyph released this 07 Apr 15:15

Initial public release of SampleKit.

Features

  • Property — Scalar scientific quantity with value, uncertainty, unit, symbols (text & LaTeX). Auto mean ± stdev from measurement lists. Lazy computed properties with dependency-based cache invalidation.
  • Table — Index-based tabular data with per-cell uncertainty. Row-wise and column-wise computed columns.
  • Sample — Named container of Properties and Tables. Bidirectional Markdown I/O with lossless YAML round-trip.
  • SampleList — Collection with filtering, multi-key sorting, batch saving, and pandas export.
  • report — Text and math (LaTeX) rendering for properties and tables.
  • converters — Export to dict, DataFrame, and descriptive statistics.

Install

pip install samplekit