samplekit 0.1.2__tar.gz → 1.0.0rc1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. samplekit-1.0.0rc1/CHANGELOG.md +356 -0
  2. samplekit-1.0.0rc1/Cargo.lock +3318 -0
  3. samplekit-1.0.0rc1/Cargo.toml +78 -0
  4. samplekit-1.0.0rc1/LICENSE +21 -0
  5. samplekit-1.0.0rc1/PKG-INFO +116 -0
  6. samplekit-1.0.0rc1/README.md +90 -0
  7. samplekit-1.0.0rc1/THIRD-PARTY-LICENSES.md +2493 -0
  8. samplekit-1.0.0rc1/build.rs +87 -0
  9. samplekit-1.0.0rc1/examples/brewing/01-first-brews/.samplekitrc +10 -0
  10. samplekit-1.0.0rc1/examples/brewing/01-first-brews/README.md +139 -0
  11. samplekit-1.0.0rc1/examples/brewing/01-first-brews/brews/citra-ipa.md +14 -0
  12. samplekit-1.0.0rc1/examples/brewing/01-first-brews/brews/farmhouse-saison.md +14 -0
  13. samplekit-1.0.0rc1/examples/brewing/01-first-brews/brews/oatmeal-stout.md +14 -0
  14. samplekit-1.0.0rc1/examples/brewing/02-measuring/.samplekitrc +44 -0
  15. samplekit-1.0.0rc1/examples/brewing/02-measuring/README.md +160 -0
  16. samplekit-1.0.0rc1/examples/brewing/02-measuring/brews/citra-ipa.md +20 -0
  17. samplekit-1.0.0rc1/examples/brewing/02-measuring/brews/farmhouse-saison.md +19 -0
  18. samplekit-1.0.0rc1/examples/brewing/02-measuring/brews/oatmeal-stout.md +20 -0
  19. samplekit-1.0.0rc1/examples/brewing/03-selecting/.samplekitrc +98 -0
  20. samplekit-1.0.0rc1/examples/brewing/03-selecting/README.md +133 -0
  21. samplekit-1.0.0rc1/examples/brewing/03-selecting/brews/blonde-saison.md +19 -0
  22. samplekit-1.0.0rc1/examples/brewing/03-selecting/brews/citra-ipa.md +20 -0
  23. samplekit-1.0.0rc1/examples/brewing/03-selecting/brews/double-ipa.md +20 -0
  24. samplekit-1.0.0rc1/examples/brewing/03-selecting/brews/dry-stout.md +20 -0
  25. samplekit-1.0.0rc1/examples/brewing/03-selecting/brews/english-pale.md +19 -0
  26. samplekit-1.0.0rc1/examples/brewing/03-selecting/brews/farmhouse-saison.md +19 -0
  27. samplekit-1.0.0rc1/examples/brewing/03-selecting/brews/hazy-pale.md +20 -0
  28. samplekit-1.0.0rc1/examples/brewing/03-selecting/brews/hefeweizen.md +19 -0
  29. samplekit-1.0.0rc1/examples/brewing/03-selecting/brews/oatmeal-stout.md +20 -0
  30. samplekit-1.0.0rc1/examples/brewing/03-selecting/brews/robust-porter.md +20 -0
  31. samplekit-1.0.0rc1/examples/brewing/03-selecting/brews/session-ipa.md +20 -0
  32. samplekit-1.0.0rc1/examples/brewing/03-selecting/brews/smoked-porter.md +18 -0
  33. samplekit-1.0.0rc1/examples/brewing/04-computing/.samplekitrc +147 -0
  34. samplekit-1.0.0rc1/examples/brewing/04-computing/README.md +183 -0
  35. samplekit-1.0.0rc1/examples/brewing/04-computing/brews/blonde-saison.md +19 -0
  36. samplekit-1.0.0rc1/examples/brewing/04-computing/brews/citra-ipa.md +53 -0
  37. samplekit-1.0.0rc1/examples/brewing/04-computing/brews/double-ipa.md +53 -0
  38. samplekit-1.0.0rc1/examples/brewing/04-computing/brews/dry-stout.md +53 -0
  39. samplekit-1.0.0rc1/examples/brewing/04-computing/brews/english-pale.md +52 -0
  40. samplekit-1.0.0rc1/examples/brewing/04-computing/brews/farmhouse-saison.md +52 -0
  41. samplekit-1.0.0rc1/examples/brewing/04-computing/brews/hazy-pale.md +53 -0
  42. samplekit-1.0.0rc1/examples/brewing/04-computing/brews/hefeweizen.md +52 -0
  43. samplekit-1.0.0rc1/examples/brewing/04-computing/brews/oatmeal-stout.md +53 -0
  44. samplekit-1.0.0rc1/examples/brewing/04-computing/brews/robust-porter.md +53 -0
  45. samplekit-1.0.0rc1/examples/brewing/04-computing/brews/session-ipa.md +53 -0
  46. samplekit-1.0.0rc1/examples/brewing/04-computing/brews/smoked-porter.md +37 -0
  47. samplekit-1.0.0rc1/examples/brewing/04-computing/model/brew.py +65 -0
  48. samplekit-1.0.0rc1/examples/brewing/04-computing/model/hydrometer.py +18 -0
  49. samplekit-1.0.0rc1/examples/brewing/05-fermentation/.samplekitrc +215 -0
  50. samplekit-1.0.0rc1/examples/brewing/05-fermentation/README.md +130 -0
  51. samplekit-1.0.0rc1/examples/brewing/05-fermentation/brews/blonde-saison.md +134 -0
  52. samplekit-1.0.0rc1/examples/brewing/05-fermentation/brews/citra-ipa.md +132 -0
  53. samplekit-1.0.0rc1/examples/brewing/05-fermentation/brews/double-ipa.md +132 -0
  54. samplekit-1.0.0rc1/examples/brewing/05-fermentation/brews/dry-stout.md +132 -0
  55. samplekit-1.0.0rc1/examples/brewing/05-fermentation/brews/english-pale.md +131 -0
  56. samplekit-1.0.0rc1/examples/brewing/05-fermentation/brews/farmhouse-saison.md +131 -0
  57. samplekit-1.0.0rc1/examples/brewing/05-fermentation/brews/hazy-pale.md +135 -0
  58. samplekit-1.0.0rc1/examples/brewing/05-fermentation/brews/hefeweizen.md +134 -0
  59. samplekit-1.0.0rc1/examples/brewing/05-fermentation/brews/oatmeal-stout.md +135 -0
  60. samplekit-1.0.0rc1/examples/brewing/05-fermentation/brews/robust-porter.md +132 -0
  61. samplekit-1.0.0rc1/examples/brewing/05-fermentation/brews/session-ipa.md +135 -0
  62. samplekit-1.0.0rc1/examples/brewing/05-fermentation/brews/smoked-porter.md +74 -0
  63. samplekit-1.0.0rc1/examples/brewing/05-fermentation/model/brew.py +130 -0
  64. samplekit-1.0.0rc1/examples/brewing/05-fermentation/model/hydrometer.py +33 -0
  65. samplekit-1.0.0rc1/examples/brewing/06-figures/.samplekitrc +307 -0
  66. samplekit-1.0.0rc1/examples/brewing/06-figures/README.md +128 -0
  67. samplekit-1.0.0rc1/examples/brewing/06-figures/brews/blonde-saison.md +134 -0
  68. samplekit-1.0.0rc1/examples/brewing/06-figures/brews/citra-ipa.md +132 -0
  69. samplekit-1.0.0rc1/examples/brewing/06-figures/brews/double-ipa.md +132 -0
  70. samplekit-1.0.0rc1/examples/brewing/06-figures/brews/dry-stout.md +132 -0
  71. samplekit-1.0.0rc1/examples/brewing/06-figures/brews/english-pale.md +131 -0
  72. samplekit-1.0.0rc1/examples/brewing/06-figures/brews/farmhouse-saison.md +131 -0
  73. samplekit-1.0.0rc1/examples/brewing/06-figures/brews/hazy-pale.md +135 -0
  74. samplekit-1.0.0rc1/examples/brewing/06-figures/brews/hefeweizen.md +134 -0
  75. samplekit-1.0.0rc1/examples/brewing/06-figures/brews/oatmeal-stout.md +135 -0
  76. samplekit-1.0.0rc1/examples/brewing/06-figures/brews/robust-porter.md +132 -0
  77. samplekit-1.0.0rc1/examples/brewing/06-figures/brews/session-ipa.md +135 -0
  78. samplekit-1.0.0rc1/examples/brewing/06-figures/brews/smoked-porter.md +74 -0
  79. samplekit-1.0.0rc1/examples/brewing/06-figures/model/brew.py +142 -0
  80. samplekit-1.0.0rc1/examples/brewing/06-figures/model/hydrometer.py +33 -0
  81. samplekit-1.0.0rc1/examples/brewing/07-two-brewers/README.md +113 -0
  82. samplekit-1.0.0rc1/examples/brewing/07-two-brewers/ana/.samplekitrc +307 -0
  83. samplekit-1.0.0rc1/examples/brewing/07-two-brewers/ana/brews/blonde-saison.md +134 -0
  84. samplekit-1.0.0rc1/examples/brewing/07-two-brewers/ana/brews/dry-stout.md +132 -0
  85. samplekit-1.0.0rc1/examples/brewing/07-two-brewers/ana/brews/farmhouse-saison.md +131 -0
  86. samplekit-1.0.0rc1/examples/brewing/07-two-brewers/ana/brews/hazy-pale.md +135 -0
  87. samplekit-1.0.0rc1/examples/brewing/07-two-brewers/ana/brews/oatmeal-stout.md +135 -0
  88. samplekit-1.0.0rc1/examples/brewing/07-two-brewers/ana/brews/smoked-porter.md +74 -0
  89. samplekit-1.0.0rc1/examples/brewing/07-two-brewers/shared/brew.py +142 -0
  90. samplekit-1.0.0rc1/examples/brewing/07-two-brewers/shared/hydrometer.py +33 -0
  91. samplekit-1.0.0rc1/examples/brewing/07-two-brewers/tom/.samplekitrc +307 -0
  92. samplekit-1.0.0rc1/examples/brewing/07-two-brewers/tom/brews/citra-ipa.md +132 -0
  93. samplekit-1.0.0rc1/examples/brewing/07-two-brewers/tom/brews/double-ipa.md +132 -0
  94. samplekit-1.0.0rc1/examples/brewing/07-two-brewers/tom/brews/english-pale.md +47 -0
  95. samplekit-1.0.0rc1/examples/brewing/07-two-brewers/tom/brews/hefeweizen.md +134 -0
  96. samplekit-1.0.0rc1/examples/brewing/07-two-brewers/tom/brews/robust-porter.md +132 -0
  97. samplekit-1.0.0rc1/examples/brewing/07-two-brewers/tom/brews/session-ipa.md +135 -0
  98. samplekit-1.0.0rc1/examples/brewing/08-python/.samplekitrc +307 -0
  99. samplekit-1.0.0rc1/examples/brewing/08-python/README.md +90 -0
  100. samplekit-1.0.0rc1/examples/brewing/08-python/brews/blonde-saison.md +134 -0
  101. samplekit-1.0.0rc1/examples/brewing/08-python/brews/citra-ipa.md +132 -0
  102. samplekit-1.0.0rc1/examples/brewing/08-python/brews/double-ipa.md +132 -0
  103. samplekit-1.0.0rc1/examples/brewing/08-python/brews/dry-stout.md +132 -0
  104. samplekit-1.0.0rc1/examples/brewing/08-python/brews/english-pale.md +131 -0
  105. samplekit-1.0.0rc1/examples/brewing/08-python/brews/farmhouse-saison.md +131 -0
  106. samplekit-1.0.0rc1/examples/brewing/08-python/brews/hazy-pale.md +135 -0
  107. samplekit-1.0.0rc1/examples/brewing/08-python/brews/hefeweizen.md +134 -0
  108. samplekit-1.0.0rc1/examples/brewing/08-python/brews/oatmeal-stout.md +135 -0
  109. samplekit-1.0.0rc1/examples/brewing/08-python/brews/robust-porter.md +132 -0
  110. samplekit-1.0.0rc1/examples/brewing/08-python/brews/session-ipa.md +135 -0
  111. samplekit-1.0.0rc1/examples/brewing/08-python/brews/smoked-porter.md +74 -0
  112. samplekit-1.0.0rc1/examples/brewing/08-python/model/brew.py +142 -0
  113. samplekit-1.0.0rc1/examples/brewing/08-python/model/hydrometer.py +33 -0
  114. samplekit-1.0.0rc1/examples/brewing/08-python/scripts/brew_report.py +27 -0
  115. samplekit-1.0.0rc1/examples/brewing/08-python/scripts/yeast_comparison.py +27 -0
  116. samplekit-1.0.0rc1/examples/brewing/README.md +39 -0
  117. samplekit-1.0.0rc1/pyproject.toml +38 -0
  118. samplekit-1.0.0rc1/python/samplekit/__init__.py +350 -0
  119. samplekit-1.0.0rc1/python/samplekit/__init__.pyi +1913 -0
  120. samplekit-1.0.0rc1/python/samplekit/_figure.py +146 -0
  121. samplekit-1.0.0rc1/python/samplekit/_figures.py +1813 -0
  122. samplekit-1.0.0rc1/python/samplekit/_worker.py +1102 -0
  123. samplekit-1.0.0rc1/python/samplekit/py.typed +0 -0
  124. samplekit-1.0.0rc1/src/collection/computation.rs +216 -0
  125. samplekit-1.0.0rc1/src/collection/editing.rs +2176 -0
  126. samplekit-1.0.0rc1/src/collection/explanation.rs +422 -0
  127. samplekit-1.0.0rc1/src/collection/exports.rs +1036 -0
  128. samplekit-1.0.0rc1/src/collection/mod.rs +8 -0
  129. samplekit-1.0.0rc1/src/collection/named_queries.rs +147 -0
  130. samplekit-1.0.0rc1/src/collection/sample_list.rs +1508 -0
  131. samplekit-1.0.0rc1/src/collection/tagging.rs +177 -0
  132. samplekit-1.0.0rc1/src/collection/validation.rs +1786 -0
  133. samplekit-1.0.0rc1/src/config/configuration_edit.rs +465 -0
  134. samplekit-1.0.0rc1/src/config/discovery.rs +772 -0
  135. samplekit-1.0.0rc1/src/config/mod.rs +7 -0
  136. samplekit-1.0.0rc1/src/config/model_runtime/description.rs +1118 -0
  137. samplekit-1.0.0rc1/src/config/model_runtime.rs +1387 -0
  138. samplekit-1.0.0rc1/src/config/profiles.rs +287 -0
  139. samplekit-1.0.0rc1/src/config/project_config.rs +2347 -0
  140. samplekit-1.0.0rc1/src/config/project_setup.rs +868 -0
  141. samplekit-1.0.0rc1/src/config/project_template/brew.py +156 -0
  142. samplekit-1.0.0rc1/src/config/project_template/empty/model.py +52 -0
  143. samplekit-1.0.0rc1/src/config/project_template/empty/samplekitrc_existing_model +12 -0
  144. samplekit-1.0.0rc1/src/config/project_template/empty/samplekitrc_head +9 -0
  145. samplekit-1.0.0rc1/src/config/project_template/empty/samplekitrc_model +11 -0
  146. samplekit-1.0.0rc1/src/config/project_template/empty/samplekitrc_no_model +11 -0
  147. samplekit-1.0.0rc1/src/config/project_template/empty/samplekitrc_rest +28 -0
  148. samplekit-1.0.0rc1/src/config/project_template/helpers__init__.py +14 -0
  149. samplekit-1.0.0rc1/src/config/project_template/helpers_hydrometer.py +36 -0
  150. samplekit-1.0.0rc1/src/config/project_template/sample.md +38 -0
  151. samplekit-1.0.0rc1/src/config/project_template/samplekitrc +186 -0
  152. samplekit-1.0.0rc1/src/config/version_control.rs +1785 -0
  153. samplekit-1.0.0rc1/src/core/dependency_graph.rs +294 -0
  154. samplekit-1.0.0rc1/src/core/formatting.rs +499 -0
  155. samplekit-1.0.0rc1/src/core/identifier.rs +306 -0
  156. samplekit-1.0.0rc1/src/core/mod.rs +9 -0
  157. samplekit-1.0.0rc1/src/core/property.rs +1547 -0
  158. samplekit-1.0.0rc1/src/core/sample.rs +1737 -0
  159. samplekit-1.0.0rc1/src/core/statistics.rs +165 -0
  160. samplekit-1.0.0rc1/src/core/table.rs +2020 -0
  161. samplekit-1.0.0rc1/src/core/uncertainty.rs +160 -0
  162. samplekit-1.0.0rc1/src/core/value.rs +691 -0
  163. samplekit-1.0.0rc1/src/format/canonicalization.rs +642 -0
  164. samplekit-1.0.0rc1/src/format/document.rs +802 -0
  165. samplekit-1.0.0rc1/src/format/fingerprint.rs +1853 -0
  166. samplekit-1.0.0rc1/src/format/migration.rs +365 -0
  167. samplekit-1.0.0rc1/src/format/mod.rs +5 -0
  168. samplekit-1.0.0rc1/src/format/schema.rs +1577 -0
  169. samplekit-1.0.0rc1/src/interfaces/cli/completion.rs +548 -0
  170. samplekit-1.0.0rc1/src/interfaces/cli/compute.rs +1259 -0
  171. samplekit-1.0.0rc1/src/interfaces/cli/edit.rs +1891 -0
  172. samplekit-1.0.0rc1/src/interfaces/cli/history.rs +1712 -0
  173. samplekit-1.0.0rc1/src/interfaces/cli/init.rs +565 -0
  174. samplekit-1.0.0rc1/src/interfaces/cli/inspect.rs +1840 -0
  175. samplekit-1.0.0rc1/src/interfaces/cli/plot.rs +739 -0
  176. samplekit-1.0.0rc1/src/interfaces/cli/tables.rs +1661 -0
  177. samplekit-1.0.0rc1/src/interfaces/cli.rs +4997 -0
  178. samplekit-1.0.0rc1/src/lib.rs +41 -0
  179. samplekit-1.0.0rc1/src/presentation/changes.rs +482 -0
  180. samplekit-1.0.0rc1/src/presentation/export_formats.rs +393 -0
  181. samplekit-1.0.0rc1/src/presentation/mod.rs +6 -0
  182. samplekit-1.0.0rc1/src/presentation/opening.rs +155 -0
  183. samplekit-1.0.0rc1/src/presentation/plotting.rs +311 -0
  184. samplekit-1.0.0rc1/src/presentation/summaries.rs +353 -0
  185. samplekit-1.0.0rc1/src/presentation/terminal_rendering.rs +1743 -0
  186. samplekit-1.0.0rc1/src/python/mod.rs +8 -0
  187. samplekit-1.0.0rc1/src/python/pyo3_bridge.rs +1540 -0
  188. samplekit-1.0.0rc1/src/python/python_api.rs +11072 -0
  189. samplekit-1.0.0rc1/src/query/field_addressing.rs +1777 -0
  190. samplekit-1.0.0rc1/src/query/filter_language.rs +1655 -0
  191. samplekit-1.0.0rc1/src/query/mod.rs +3 -0
  192. samplekit-1.0.0rc1/src/query/ordering.rs +266 -0
  193. samplekit-1.0.0rc1/src/tui/mod.rs +11 -0
  194. samplekit-1.0.0rc1/src/tui/model.rs +8780 -0
  195. samplekit-1.0.0rc1/src/tui/run.rs +460 -0
  196. samplekit-1.0.0rc1/src/tui/start.rs +1796 -0
  197. samplekit-1.0.0rc1/src/tui/theme.rs +244 -0
  198. samplekit-1.0.0rc1/src/tui/typing.rs +382 -0
  199. samplekit-1.0.0rc1/src/tui/view.rs +3174 -0
  200. samplekit-0.1.2/LICENSE +0 -8
  201. samplekit-0.1.2/PKG-INFO +0 -422
  202. samplekit-0.1.2/README.md +0 -397
  203. samplekit-0.1.2/pyproject.toml +0 -32
  204. samplekit-0.1.2/samplekit/__init__.py +0 -20
  205. samplekit-0.1.2/samplekit/converters.py +0 -117
  206. samplekit-0.1.2/samplekit/property.py +0 -332
  207. samplekit-0.1.2/samplekit/report.py +0 -214
  208. samplekit-0.1.2/samplekit/sample.py +0 -322
  209. samplekit-0.1.2/samplekit/sample_list.py +0 -190
  210. samplekit-0.1.2/samplekit/table.py +0 -612
  211. samplekit-0.1.2/samplekit.egg-info/PKG-INFO +0 -422
  212. samplekit-0.1.2/samplekit.egg-info/SOURCES.txt +0 -15
  213. samplekit-0.1.2/samplekit.egg-info/dependency_links.txt +0 -1
  214. samplekit-0.1.2/samplekit.egg-info/requires.txt +0 -2
  215. samplekit-0.1.2/samplekit.egg-info/top_level.txt +0 -1
  216. samplekit-0.1.2/setup.cfg +0 -4
@@ -0,0 +1,356 @@
1
+ # Changelog
2
+
3
+ What changed in SampleKit from one version to the next, newest first. Each
4
+ version says what was added, changed, removed and fixed, for someone who uses
5
+ SampleKit rather than works on it.
6
+
7
+ A version ending in `-rc.N` is a release candidate: tried before the version
8
+ of that number is published, and replaced by it.
9
+
10
+ ## [1.0.0-rc.1] — 2026-09-28
11
+
12
+ The first release candidate of SampleKit 1.0, and a new SampleKit. Version
13
+ 0.2.0 was a pure Python package for writing samples from a script. 1.0 keeps
14
+ its idea — a sample is a Markdown file, with its data at the top — and is
15
+ built around a command line and a full-screen terminal interface, written in
16
+ Rust, with a Python package beside them for your formulas and your scripts.
17
+ Both come from one source and carry one version (`1.0.0rc1` for Python).
18
+
19
+ It does not read the files 0.2.0 wrote, and no command converts them: see
20
+ [Upgrading from 0.2.0](#upgrading-from-020) below.
21
+
22
+ ### Added
23
+
24
+ **The command line**, `samplekit`, a program with no Python inside. Reading,
25
+ selecting, showing, checking and exporting samples never start Python.
26
+
27
+ - `samplekit FOLDER` prints the path of each sample; with `-c` it shows a
28
+ table of the columns you name, and with `--profile` a table declared in
29
+ `.samplekitrc`. `-f` filters (`-f 'og > 1.050 && tags has medal'`), `-s`
30
+ sorts, `--group` makes a table per value of a field, `--summary` summarises
31
+ each column. `--csv`, `--tsv` and `--json` print the same table as data,
32
+ and `-o FILE --write` writes it.
33
+ - `list` enumerates what a collection holds and declares: its fields, tags,
34
+ queries, profiles, exports, figures, a sample's own files, and the files it
35
+ skipped and why.
36
+ - `view` shows a sample whole: its values, then its tables, and its note with
37
+ `--note`.
38
+ - `status` lists every computed value that is not current, and why;
39
+ `status --exit-code` makes it a check for continuous integration.
40
+ - `compute` runs the model's formulas: alone it says what would run, with
41
+ `--try` it computes and shows the results without writing, and with
42
+ `--write` it writes each sample as soon as it is done. `explain FILE FIELD`
43
+ says where one value came from, and prints a formula's error.
44
+ - `validate` reports the defects of sample files and changes nothing.
45
+ - `new` creates a sample from what the project already knows, `set` changes
46
+ its values (`set brew.md og=1.052 og.u=0.001`, readings, table cells, the
47
+ name), and `tag add`, `tag remove` and `tag rename` change its tags. Each
48
+ shows what it would change and writes only with `--write`.
49
+ - `export NAME` writes a table declared in `.samplekitrc` as CSV, TSV or
50
+ JSON, after a preview; `--status` adds a column holding each row's state.
51
+ - `plot` draws a figure with matplotlib, in a window or to a file: one
52
+ declared in `.samplekitrc` or by the model, or one given by its axes
53
+ (`-x`, `-y`), over properties, attributes or a table's columns.
54
+ - `open` opens a sample's own files — photos, reports, raw data — which
55
+ `[collection] files` says where to find.
56
+ - `init` sets a project up: its `.samplekitrc`, a model to fill in or the
57
+ one you name with `--model PATH`, and a Python environment, `.venv/`, with
58
+ the SampleKit package installed in it. At a terminal it asks; `--example`
59
+ writes a project that runs, one formula of every kind.
60
+ - `tui` opens the full-screen interface on a folder, and `samplekit` alone,
61
+ in a terminal, opens its start page.
62
+ - `completions` sets up tab completion for bash, zsh, fish, elvish and
63
+ PowerShell.
64
+ - Every command has `--help`, with examples, and `-h` for a short summary.
65
+ Errors name what was asked, what exists instead, and the nearest name. Exit
66
+ codes tell a usage error (1) from a data error (2) and a file the system
67
+ refused (3).
68
+
69
+ **A history of every change.** Before SampleKit writes to a project, it keeps
70
+ what the project held, in `.samplekit/history/`, beside `.samplekitrc`: the
71
+ sample files, the configuration and the model's source. There is nothing to
72
+ set up, and no Git to install.
73
+
74
+ - `log` lists the snapshots, `diff` compares two states value by value
75
+ (`abv 6.8 ± 0.1 % → 7.2 ± 0.1 %`), and `restore` puts files back: the last
76
+ change taken back, or the state of a given snapshot.
77
+ - `--at` reads the whole project as it was at a snapshot or on a date:
78
+ `samplekit brews -c name,abv --at 2026-09-12`. An export made again this
79
+ way is the same file, byte for byte.
80
+ - A change made in your text editor is kept as a snapshot of its own, so it
81
+ is never credited to the command that follows.
82
+ - A Python script's writes are one snapshot, with the script's source: `log
83
+ --script N` prints the script as it ran, and `keep()` marks a snapshot of
84
+ its own from inside a script.
85
+ - Every export and figure SampleKit writes is recorded. `explain FILE` finds
86
+ it again, even copied into a manuscript's folder and renamed: what made it,
87
+ from which samples, whether it is still current, and the command that makes
88
+ it again.
89
+ - `log --export` writes the history as Markdown, to share beside the samples.
90
+ - One history over several computers: each writes its own branch in
91
+ `.samplekit/history/`, and the next snapshot joins another computer's once
92
+ your files hold its state — no command merges. `log` shows a `machine`
93
+ column where more than one wrote, and an undo takes back only this
94
+ computer's change. A synchronised folder shares it as it is; git, once the
95
+ history's own `.gitignore` stops ignoring everything.
96
+
97
+ **Current and outdated values.** Every computed value carries a short record
98
+ of what it was computed from. SampleKit compares it with the file as it is
99
+ now, and knows — from the files alone, without running Python — which values
100
+ are *outdated* (an input changed), *edited* (typed by hand over the formula),
101
+ *failed* (the formula raised an error) or *never computed*. Your computer also
102
+ keeps a digest of each formula, so that editing a formula makes outdated only
103
+ the values it computed, and a comment or a docstring changes nothing. A value
104
+ whose input nobody entered yet *waits* for it, and is not an error.
105
+
106
+ - The states appear in the same words everywhere: `status`, marks in tables
107
+ (`⚠` outdated, `✎` edited, `✗` failed), the TUI, Python. `state` is also a
108
+ field: `-f 'state == outdated'`, `-c name,state`.
109
+ - A value typed over its formula is an **override**: `compute` leaves it
110
+ alone until `compute --force` gives it back to its formula.
111
+ - A formula that fails does not stop the run: the other values are computed,
112
+ the file records the error's type, and the full traceback is kept for
113
+ `explain`. An interrupted run loses only the sample in progress.
114
+
115
+ **The full-screen interface, the TUI**, for a project you work in every day.
116
+
117
+ - A **start page**: recent projects, a new project set up by a few questions,
118
+ a folder opened or configured, and the guide and demo.
119
+ - **The collection**: filter, sort, group, choose columns, summarise, and
120
+ save what it shows as a query, a profile or an export of the project.
121
+ - **A sample**: its values, tables, readings and note, each value editable;
122
+ its own files opened; a value computed, or everything not current.
123
+ - **The history**: the snapshots, what each changed, and `u` to take the last
124
+ change back.
125
+ - **The configuration** edited from the TUI, and the colours set by role in
126
+ `[tui.colors]`.
127
+ - **Editing as in a text editor**, wherever you type — the filter, a value,
128
+ a name, a setting, the note: the mouse selects, by word on a double click;
129
+ `Shift` and the arrows select; `Ctrl` and the arrows move by word;
130
+ `Ctrl+Backspace` and `Ctrl+Delete` take a word out; `Ctrl+Z` undoes,
131
+ `Ctrl+Shift+Z` redoes; `Ctrl+C` copies a selection, `Ctrl+X` cuts, and a
132
+ paste goes where the cursor is. In the note, Markdown by keys: `*`, `_` or
133
+ `~` around a selection, `Alt+1` to `Alt+6` a heading, `Alt+L` a link,
134
+ `Alt+I` an image, `Alt+C` a code block.
135
+ - `?` lists every key of the screen you are on.
136
+
137
+ **A demo**: a home brewer's notebook in eight steps, from three brews written
138
+ by hand to a model, tables, figures, two projects and Python. The start page
139
+ writes it for you (`g`), and it is also in the source, in `examples/brewing/`.
140
+
141
+ **Several projects in one command.** `samplekit status ana/brews tom/brews`
142
+ reads both; each sample keeps its own project's units, precisions, model,
143
+ queries and profiles, and the terminal shows one table per project.
144
+
145
+ **New in the sample file** (the format itself is under *Changed*):
146
+
147
+ - **`n/a`**, not applicable: a value that does not apply to this sample, as
148
+ distinct from one nobody has measured yet. A formula reading it gives `n/a`
149
+ too, without running.
150
+ - **Attributes**: facts about a sample — a style, a supplier, a date, a list
151
+ of hops — with no unit and no uncertainty, filtered and shown like
152
+ properties.
153
+ - **Tags**, a deliberate label on a sample (`tags: [medal]`), reached by a
154
+ filter (`tags has medal`).
155
+ - **A sample's own files** — photos, reports, raw data — found by the
156
+ sample's name where `[collection] files` says, and opened from the command
157
+ line, the TUI or Python.
158
+
159
+ **A project's configuration**, `.samplekitrc`, in the project's folder: the
160
+ model; queries, profiles, exports and figures by name; how a unit is shown in
161
+ a table, in LaTeX and on a figure (`[unit.*]`); the precision, symbol and unit
162
+ of each quantity, declared once (`[property.*]`); matplotlib's settings;
163
+ which files are samples. Every key is checked: a misspelt one is an error
164
+ that names the line and the nearest valid key.
165
+
166
+ - **`import = ".."`** takes the configuration of the folder named, merged key
167
+ by key beneath this one: what several collections share is declared once,
168
+ at their common root, and each collection keeps its model and what is its
169
+ own. Imports chain; a loop is refused. A relative path reads from the file
170
+ that declares it, and `{collection}` names a sample's collection folder in
171
+ `[collection] files` and an export's `output`.
172
+ - **What the current folder offers**: `list profiles`, `queries`, `exports`
173
+ and `figures`, the completion and the TUI's `f` show the configuration of
174
+ the folder a command runs from, with what it imports, each name marked
175
+ `local` or with the file it comes from. A sample still follows its own
176
+ collection's configuration wherever the command runs from.
177
+ - `validate` notes a declaration identical to the one imported, a copy to
178
+ remove, and `--show-rc` names the files imported.
179
+
180
+ **One warning a command.** A command that would warn several times of one
181
+ thing — samples a profile or an export several projects lack, targets that
182
+ are not Markdown, histories not kept, what a model logged — says it once, in
183
+ one line counting them and ending *-v shows them*; `-v` lists each.
184
+
185
+ **The documentation**, in four parts: a tutorial that follows the demo;
186
+ explanations, a page per notion; how-to guides for a task you have in mind;
187
+ and a reference — every command and option, the Python API, the TUI's keys,
188
+ every key of `.samplekitrc`, the sample file format, the exit codes.
189
+
190
+ ### Changed
191
+
192
+ **The note below the data is yours.** 0.2.0 wrote the body of a file from the
193
+ model's `template()` at every save. SampleKit now never writes, reformats or
194
+ reads the note: not a character, not a line ending. Tables for a reader are
195
+ what the command line, the TUI and exports show.
196
+
197
+ **The sample file.** A sample is still one Markdown file with its data in a
198
+ YAML block at the top, written differently:
199
+
200
+ ```yaml
201
+ ---
202
+ schema_version: 1
203
+ style: stout
204
+ properties:
205
+ og: {v: 1.058, u: 0.001, readings: [1.057, 1.058, 1.059]}
206
+ volume: {v: 19.5, unit: L}
207
+ tables:
208
+ fermentation:
209
+ index: day
210
+ columns:
211
+ day: {unit: d}
212
+ gravity: {}
213
+ rows:
214
+ - {day: 1, gravity: 1.041}
215
+ ---
216
+ ```
217
+
218
+ - `schema_version: 1` heads the file. Quantities go under `properties:`,
219
+ tables under `tables:`, and any other top-level key is an attribute.
220
+ - A quantity is a bare number or a short mapping: `v` for the value (was
221
+ `value`), `u` for the standard uncertainty in the value's unit (was
222
+ `uncertainty`), `readings` for the repeated measurements (was `data`), and
223
+ `unit`. `og.v` and `og.u` are also how a filter, a column, `set` and Python
224
+ name the two numbers.
225
+ - A table has `index`, `columns` as a mapping and `rows` (was `_index`,
226
+ `_columns` as a list, `_rows`), an index of one column or several, and
227
+ cells that are quantities. `fermentation.gravity[3]` names the gravity on
228
+ day 3.
229
+ - A precision and a LaTeX spelling are no longer written in each file
230
+ (`precision`, `precision_unc`, `symbol_math`, `unit_math`): they are
231
+ declared once in `.samplekitrc`, where a quantity's unit and symbol can be
232
+ too. A formula is never written in a file.
233
+ - `name:` is optional: without it, the file's name without its extension
234
+ stands for the sample's name.
235
+ - A computed value carries a short record of what it was computed from
236
+ (`computed:`, `fingerprint:`), which is how SampleKit tells it is current.
237
+ - Names of properties, attributes, tables, columns and tags start with a
238
+ letter or `_` and hold letters, digits and `_`, in any alphabet: `température` and
239
+ `bière` are names, `dry-hopped` is not.
240
+ - The data is written in one fixed form: the first write to a file written
241
+ by hand may change more lines than the value, and after that only what
242
+ changed. A write goes to a temporary file first, and is refused if the file
243
+ changed on disk since it was read.
244
+
245
+ **Readings and their statistic.** In 0.2.0, a list of measurements gave the
246
+ mean and the sample standard deviation on its own. The value of readings is
247
+ now **the statistic the model declares** — mean, median, minimum, maximum or
248
+ a quartile, and standard error or a standard deviation for the uncertainty —
249
+ or a value written beside them. Readings with neither have no value, and
250
+ every surface says so rather than taking a mean nobody chose. The file notes
251
+ which statistic gave the numbers (`statistics: {v: mean, u: standard_error}`).
252
+
253
+ **Units, symbols and precision** are the project's. A unit is a label, never
254
+ converted; `[unit."degC"]` says how it is shown in a table (`°C`), in LaTeX
255
+ and on a figure. Two samples writing different units for one quantity are
256
+ reported rather than put side by side. A declared precision rounds alike on
257
+ the screen and in an export.
258
+
259
+ **The model and computing.** A project names its model, a subclass of
260
+ `samplekit.Sample`, in `.samplekitrc` (`[model] path` and `class`), and every
261
+ tool uses it. Each computed value has a formula of its own and names what it
262
+ reads:
263
+
264
+ ```python
265
+ self.abv = sk.Property(unit="%", compute_quantity=self._abv, depends_on=["og", "fg"])
266
+ ```
267
+
268
+ - `compute=` gives the value, `compute_uncertainty=` (was `compute_unc`) the
269
+ uncertainty beside a value you enter, and `compute_quantity=` both. A
270
+ table's cells are computed a row at a time (`compute_rows`) or a column at
271
+ once (`compute_columns`).
272
+ - `depends_on` names the inputs by name (`"og"`, `"fermentation.gravity"`),
273
+ not as `Property` objects, and it is required: a model with a formula
274
+ that declares nothing is refused before any formula runs.
275
+ - **A model declares no symbol and no precision**: both are the project's,
276
+ in `[property.*]`, as the unit's display is. `sk.Property` and `sk.Column`
277
+ refuse `symbol=` and `precision=`, saying where each is declared.
278
+ - **Nothing is computed when a value is read.** Values are computed when you
279
+ ask — `samplekit compute`, `C` or `c` in the TUI, `compute()` in Python —
280
+ and only what is not current, in the order the inputs require. A change to
281
+ an input marks what reads it as outdated; it does not recompute it.
282
+ - **A value set over a formula is an override**: the formula stays in the
283
+ model, and the value is marked edited, where 0.2.0 dropped the formula.
284
+ - The command line runs the model in the Python of the nearest `.venv/`
285
+ above the samples, or the interpreter `[model] python` names, where the
286
+ SampleKit package must be installed in the same version. It runs without
287
+ asking, as `python` runs a script you give it, and names the configuration
288
+ and the model file before it starts.
289
+ - The model is described once, in `.samplekit/model.json`, written whenever
290
+ it is imported and again when its files change: what only reads the model's
291
+ declarations — `status`, `new` and `set`, a `state` filter, the TUI — reads
292
+ the description and starts no Python. Python runs to compute and to draw.
293
+ - What a model prints goes to a log file; its warnings are shown during the
294
+ run.
295
+ - Uncertainties are never propagated on their own: a formula that should give
296
+ one returns it.
297
+
298
+ **The Python package** is built from the same Rust code as the command line,
299
+ and changes its shape:
300
+
301
+ - `sk.load(path)` reads a sample or a folder, with the project's model
302
+ (was `SampleList(path, sample_class=…)` and `Sample.load`); `sk.load(a, b)`
303
+ reads several folders into one list.
304
+ - `Sample.new(path)` makes a sample, `save()` writes it, `compute()` computes
305
+ what is not current, and `not_current()` lists what `status` would.
306
+ - A `SampleList` filters with the command line's language
307
+ (`brews.filter("og > 1.050")`) as well as a function, sorts, groups
308
+ (`group_by`), selects with a query of the project, and writes CSV, TSV or
309
+ JSON at the project's precisions (`to_csv`, `to_tsv`, `to_json`,
310
+ `to_dict`).
311
+ - `sk.stats` names the statistics readings can stand for, and
312
+ `sk.plot` draws the same figures as the command line.
313
+ - Reading a value that is not current returns it, with a warning saying why.
314
+ - The package ships type stubs that carry its documentation, so that an
315
+ editor shows both.
316
+ - Python 3.11 or newer is required (was 3.10), and neither PyYAML nor pandas
317
+ is needed.
318
+
319
+ **Performance.** The package is built in Rust. Reading and writing sample
320
+ files is 25 to 35 times faster than 0.2.0, and the statistics of readings
321
+ about 3 times faster. A value computed costs a little more — some 15 µs per
322
+ formula run — for the record of what it read, which is how SampleKit knows
323
+ afterwards that it is still current; beside a formula that takes seconds, it
324
+ does not show. `status`, `new`, `set` and the TUI start no Python while the
325
+ model's description is current.
326
+
327
+ ### Removed
328
+
329
+ - **Reading 0.2.0 files.** Every command names such a file, says why, reads
330
+ the rest and exits with code 2.
331
+ - **The long spellings `value:` and `uncertainty:`.** They are not read, in a
332
+ property, a table's cell or anywhere else in a sample file: such a file is
333
+ not read, and every command names the key and what it is written now —
334
+ `'value' is written 'v' since schema 1: rename it`.
335
+ - **`template()` and the `report` module**: the note is no longer generated.
336
+ Tables for a paper are profiles and exports; figures are drawn with `plot`.
337
+ - **pandas**: `to_dataframe()`, `stats()` on a list and the `converters`
338
+ module. `to_csv()` or `to_dict()` give data pandas reads, and `--summary`,
339
+ `Summary` and `sk.stats` summarise.
340
+ - **Computing on read**, and the cache a changed input cleared.
341
+ - **The automatic mean and standard deviation of a list**: a statistic is
342
+ declared.
343
+
344
+ ### Upgrading from 0.2.0
345
+
346
+ No command converts a 0.2.0 sample: the model has to be rewritten by hand
347
+ anyway, and a tool that did half the work would take all the risk of writing
348
+ to your files. [Upgrade from an older SampleKit](docs/how-to/upgrade.md)
349
+ shows how to carry each sample across — its values, uncertainties, readings,
350
+ tables and text — with both versions installed side by side, into a new
351
+ folder, and how to check the result.
352
+
353
+ ## [0.2.0]
354
+
355
+ The previous SampleKit, a Python package published on the Python Package
356
+ Index. Its changes are not recorded here.