labnotes 0.0.39__tar.gz → 0.0.41__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 (94) hide show
  1. {labnotes-0.0.39 → labnotes-0.0.41}/PKG-INFO +1 -1
  2. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/context.md +5 -6
  3. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/models.py +1 -1
  4. labnotes-0.0.41/src/labnotes/runner/new_stamped_run_id.py +9 -0
  5. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/read_experiment_config.py +1 -1
  6. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/run_experiment.py +3 -3
  7. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/summarize_config.py +3 -3
  8. {labnotes-0.0.39 → labnotes-0.0.41}/.gitignore +0 -0
  9. {labnotes-0.0.39 → labnotes-0.0.41}/CHANGELOG.md +0 -0
  10. {labnotes-0.0.39 → labnotes-0.0.41}/MIGRATIONS.md +0 -0
  11. {labnotes-0.0.39 → labnotes-0.0.41}/README.md +0 -0
  12. {labnotes-0.0.39 → labnotes-0.0.41}/pyproject.toml +0 -0
  13. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/__init__.py +0 -0
  14. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/asset_url.py +0 -0
  15. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/cell_progress.py +0 -0
  16. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/check_counts.py +0 -0
  17. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/cli.py +0 -0
  18. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/context_guide.py +0 -0
  19. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/count_runs.py +0 -0
  20. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/create_app.py +0 -0
  21. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/create_experiment.py +0 -0
  22. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/data_html.py +0 -0
  23. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/default_config_text.py +0 -0
  24. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/default_counts.py +0 -0
  25. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/drain_watch.py +0 -0
  26. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/experiment_notes.py +0 -0
  27. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/experiment_progress.py +0 -0
  28. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/experiment_runs.py +0 -0
  29. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/experiments.py +0 -0
  30. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/format_value.py +0 -0
  31. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/init.py +0 -0
  32. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/list_experiments.py +0 -0
  33. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/list_runs.py +0 -0
  34. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/load_config.py +0 -0
  35. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/load_experiment.py +0 -0
  36. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/notebook_kernel.py +0 -0
  37. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/output_html.py +0 -0
  38. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/parse_run_view.py +0 -0
  39. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/pivot_cells.py +0 -0
  40. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/print_rows.py +0 -0
  41. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/python_blocks.py +0 -0
  42. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/read_config.py +0 -0
  43. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/read_path.py +0 -0
  44. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/render_markdown.py +0 -0
  45. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/__init__.py +0 -0
  46. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/describe_event.py +0 -0
  47. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/execute_run.py +0 -0
  48. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/hold_folder.py +0 -0
  49. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/new_invocation_id.py +0 -0
  50. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/new_run_id.py +0 -0
  51. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/param_args.py +0 -0
  52. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/param_grid.py +0 -0
  53. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/plan_runs.py +0 -0
  54. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/run_folder.py +0 -0
  55. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/run_headless.py +0 -0
  56. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/runs_parent.py +0 -0
  57. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/shell_command.py +0 -0
  58. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/start_experiment.py +0 -0
  59. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/stop_then_kill.py +0 -0
  60. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/wait_for_group.py +0 -0
  61. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/runner/write_run_json.py +0 -0
  62. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/saved_outputs.py +0 -0
  63. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/serve_app.py +0 -0
  64. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/server.py +0 -0
  65. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/sort_href.py +0 -0
  66. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/sql_quote.py +0 -0
  67. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/static/labnotes.css +0 -0
  68. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/static/row-link.js +0 -0
  69. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/static/run-cell.js +0 -0
  70. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/static/view-toggle.js +0 -0
  71. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/stop_idle_kernels.py +0 -0
  72. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/tables/__init__.py +0 -0
  73. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/tables/experiment_rows.py +0 -0
  74. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/tables/file_prefix.py +0 -0
  75. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/tables/iso_time.py +0 -0
  76. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/tables/list_experiment_runs.py +0 -0
  77. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/tables/open_tables.py +0 -0
  78. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/tables/path_glob.py +0 -0
  79. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/tables/path_pattern.py +0 -0
  80. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/tables/read_experiment.py +0 -0
  81. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/tables/read_file.py +0 -0
  82. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/tables/read_run.py +0 -0
  83. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/tables/summarize_experiments.py +0 -0
  84. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/templates/base.html +0 -0
  85. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/templates/experiment.html +0 -0
  86. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/templates/index.html +0 -0
  87. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/templates/macros.html +0 -0
  88. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/tui/__init__.py +0 -0
  89. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/tui/dim.py +0 -0
  90. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/tui/format_elapsed.py +0 -0
  91. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/tui/run_app.py +0 -0
  92. {labnotes-0.0.39 → labnotes-0.0.41}/src/labnotes/tui/run_tui.py +0 -0
  93. {labnotes-0.0.39 → labnotes-0.0.41}/testing-conventions.toml +0 -0
  94. {labnotes-0.0.39 → labnotes-0.0.41}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: labnotes
3
- Version: 0.0.39
3
+ Version: 0.0.41
4
4
  Summary: Browse experiment designs, notes, and run data from a folder.
5
5
  Project-URL: Repository, https://github.com/thekevinscott/labnotes
6
6
  Author-email: Kevin Scott <me@thekevinscott.com>
@@ -56,12 +56,11 @@ effort = ["low", "high"]
56
56
  `name` is optional: a display name for the experiment, shown in the live view
57
57
  and as `display_name` in `experiments`. The folder name stays the key, so
58
58
  renaming the experiment means editing `name`.
59
- Each combination of `[params]` runs `repeats` times, round-robin. Only runs
60
- that count fill a combination, so running again fills in what failed or never
61
- ran.
62
- `mode = "adhoc"` skips that: every `run` runs each combination `repeats` times
63
- again, whatever is already on disk. The default is `mode = "fill"`.
64
- Each run gets a new run folder. `command` runs in a shell from the root, with
59
+ Each combination of `[params]` runs `repeats` times, round-robin, on every
60
+ `run`, whatever is already on disk. That is `mode = "adhoc"`, the default.
61
+ `mode = "fill"` counts what is there: only runs that count fill a combination,
62
+ so running again fills in what failed or never ran.
63
+ Each run gets a new run folder, named for the UTC time it was planned (`20261020-000429-brave-fox`), so folder listings sort by start. `command` runs in a shell from the root, with
65
64
  `{run_dir}` replaced by the run folder's absolute path. Pass it to the
66
65
  script so it writes its outputs there.
67
66
  Each param is appended as `--name value`, with the name as written (use
@@ -47,4 +47,4 @@ class ExperimentConfig:
47
47
  params: dict[str, list[object]]
48
48
  name: str | None = None
49
49
  counts: str = DEFAULT_COUNTS
50
- mode: str = "fill"
50
+ mode: str = "adhoc"
@@ -0,0 +1,9 @@
1
+ from collections.abc import Callable
2
+ from datetime import UTC, datetime
3
+
4
+ from labnotes.runner.new_run_id import new_run_id
5
+
6
+
7
+ def new_stamped_run_id(taken: Callable[[str], bool]) -> str:
8
+ stamp = datetime.now(UTC).strftime("%Y%m%d-%H%M%S")
9
+ return f"{stamp}-" + new_run_id(lambda name: taken(f"{stamp}-{name}"))
@@ -40,7 +40,7 @@ def read_experiment_config(path: Path) -> ExperimentConfig:
40
40
  counts = values.get("counts", DEFAULT_COUNTS)
41
41
  if not isinstance(counts, str) or not counts.strip():
42
42
  raise ValueError(f"{path}: counts must be a SQL condition")
43
- mode = values.get("mode", "fill")
43
+ mode = values.get("mode", "adhoc")
44
44
  if mode not in MODES:
45
45
  raise ValueError(f"{path}: mode must be fill or adhoc")
46
46
  return ExperimentConfig(command, repeats, params, name, counts, mode)
@@ -13,7 +13,7 @@ from labnotes.models import (
13
13
  )
14
14
  from labnotes.runner.execute_run import execute_run
15
15
  from labnotes.runner.new_invocation_id import new_invocation_id
16
- from labnotes.runner.new_run_id import new_run_id
16
+ from labnotes.runner.new_stamped_run_id import new_stamped_run_id
17
17
  from labnotes.runner.param_grid import param_grid
18
18
  from labnotes.runner.plan_runs import plan_runs
19
19
  from labnotes.runner.run_folder import run_folder
@@ -49,7 +49,7 @@ async def run_experiment(
49
49
  for params in plan_runs(
50
50
  param_grid(experiment.params), experiment.repeats, finished
51
51
  ):
52
- run = new_run_id(taken)
52
+ run = new_stamped_run_id(taken)
53
53
  planned.add(run)
54
54
  plan.append((run, params))
55
55
  runs = [{"run": run, "params": params} for run, params in plan]
@@ -131,7 +131,7 @@ async def run_experiment(
131
131
  def retry(run: str) -> None:
132
132
  if stopping.is_set() or run not in ended:
133
133
  return
134
- again = new_run_id(taken)
134
+ again = new_stamped_run_id(taken)
135
135
  planned.add(again)
136
136
  plan.append((again, ended[run]))
137
137
  report({"event": "retried", "run": run, "retry": again, "params": ended[run]})
@@ -15,14 +15,14 @@ def summarize_config(config: dict[str, object] | None) -> dict[str, object]:
15
15
  cells = prod(len(values) for values in varies.values())
16
16
  command = config.get("command")
17
17
  counts = config.get("counts")
18
- adhoc = config.get("mode") == "adhoc"
18
+ fill = config.get("mode") == "fill"
19
19
  return {
20
20
  "fixed": {},
21
21
  "varies": varies,
22
22
  "cell_count": cells,
23
23
  "runs_per_cell": repeats,
24
- "target": cells * repeats if repeats is not None and not adhoc else None,
24
+ "target": cells * repeats if repeats is not None and fill else None,
25
25
  "completed_run": counts if isinstance(counts, str) else DEFAULT_COUNTS,
26
- "mode": "adhoc" if adhoc else "fill",
26
+ "mode": "fill" if fill else "adhoc",
27
27
  "other": {} if command is None else {"command": command},
28
28
  }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes