labnotes 0.0.18__tar.gz → 0.0.19__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.
- {labnotes-0.0.18 → labnotes-0.0.19}/PKG-INFO +4 -1
- {labnotes-0.0.18 → labnotes-0.0.19}/README.md +3 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/context.md +3 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/count_runs.py +3 -3
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/list_runs.py +5 -4
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/load_experiment.py +4 -1
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/runner/run_experiment.py +5 -1
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/study_progress.py +4 -2
- labnotes-0.0.19/src/labnotes/study_runs.py +5 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/tables/list_experiment_runs.py +2 -1
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/tables/open_tables.py +2 -1
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/tables/read_run.py +2 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/.gitignore +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/CHANGELOG.md +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/MIGRATIONS.md +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/pyproject.toml +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/__init__.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/asset_url.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/cell_progress.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/cli.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/context_guide.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/create_app.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/create_experiment.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/data_html.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/default_config_text.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/drain_watch.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/experiments.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/format_value.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/init.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/list_experiments.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/load_config.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/models.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/notebook_kernel.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/open_experiments.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/open_runs.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/output_html.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/parse_run_view.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/pivot_cells.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/print_rows.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/python_blocks.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/read_config.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/read_design.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/read_note.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/read_path.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/render_markdown.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/run_columns.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/runner/__init__.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/runner/describe_event.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/runner/execute_run.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/runner/lock_path.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/runner/new_run_id.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/runner/param_args.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/runner/param_grid.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/runner/plan_runs.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/runner/read_experiment_config.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/runner/run_folder.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/runner/run_headless.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/runner/shell_command.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/runner/start_experiment.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/runner/stop_then_kill.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/runner/write_run_json.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/saved_outputs.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/serve_app.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/server.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/sort_href.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/sql_quote.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/static/labnotes.css +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/static/row-link.js +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/static/run-cell.js +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/static/view-toggle.js +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/stop_idle_kernels.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/summarize_design.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/tables/__init__.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/tables/experiment_rows.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/tables/file_prefix.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/tables/iso_time.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/tables/path_glob.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/tables/path_pattern.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/tables/read_experiment.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/tables/read_file.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/tables/summarize_experiments.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/templates/base.html +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/templates/experiment.html +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/templates/index.html +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/templates/macros.html +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/tui/__init__.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/tui/format_elapsed.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/tui/run_app.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/src/labnotes/tui/run_tui.py +0 -0
- {labnotes-0.0.18 → labnotes-0.0.19}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: labnotes
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.19
|
|
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>
|
|
@@ -98,6 +98,9 @@ Each param is appended as `--name value`, with the name as written (use
|
|
|
98
98
|
`source-language` for a `--source-language` flag), booleans as 0 or 1, and lists
|
|
99
99
|
and tables as JSON. labnotes writes `run.json` (params, created, ended, exit
|
|
100
100
|
code), `stdout.log` and `stderr.log` to the run folder.
|
|
101
|
+
To exclude a run, add `"excluded": true` and an optional `"reason"` to its
|
|
102
|
+
`run.json`. An excluded run doesn't count toward `repeats`, so the next `run`
|
|
103
|
+
replaces it; both show as columns in `runs`.
|
|
101
104
|
|
|
102
105
|
In a terminal, `run` shows a live table of runs (status and time) and stays
|
|
103
106
|
open when they finish; `q` quits. Elsewhere, or with `--no-tui`, it prints a
|
|
@@ -75,6 +75,9 @@ Each param is appended as `--name value`, with the name as written (use
|
|
|
75
75
|
`source-language` for a `--source-language` flag), booleans as 0 or 1, and lists
|
|
76
76
|
and tables as JSON. labnotes writes `run.json` (params, created, ended, exit
|
|
77
77
|
code), `stdout.log` and `stderr.log` to the run folder.
|
|
78
|
+
To exclude a run, add `"excluded": true` and an optional `"reason"` to its
|
|
79
|
+
`run.json`. An excluded run doesn't count toward `repeats`, so the next `run`
|
|
80
|
+
replaces it; both show as columns in `runs`.
|
|
78
81
|
|
|
79
82
|
In a terminal, `run` shows a live table of runs (status and time) and stays
|
|
80
83
|
open when they finish; `q` quits. Elsewhere, or with `--no-tui`, it prints a
|
|
@@ -65,6 +65,9 @@ Each param is appended as `--name value`, with the name as written (use
|
|
|
65
65
|
`source-language` for a `--source-language` flag), booleans as 0 or 1, and lists
|
|
66
66
|
and tables as JSON. labnotes writes `run.json` (params, created, ended, exit
|
|
67
67
|
code), `stdout.log` and `stderr.log` to the run folder.
|
|
68
|
+
To exclude a run, add `"excluded": true` and an optional `"reason"` to its
|
|
69
|
+
`run.json`. An excluded run doesn't count toward `repeats`, so the next `run`
|
|
70
|
+
replaces it; both show as columns in `runs`.
|
|
68
71
|
|
|
69
72
|
A script run by labnotes should:
|
|
70
73
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from dirsql import DirSQL
|
|
2
2
|
|
|
3
|
-
from labnotes.sql_quote import quote_identifier
|
|
3
|
+
from labnotes.sql_quote import quote_identifier
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
async def count_runs(
|
|
7
|
-
runs: DirSQL,
|
|
7
|
+
runs: DirSQL, source: str, completed_run: str, group_by: list[str] | None = None
|
|
8
8
|
) -> list[dict[str, object]]:
|
|
9
9
|
keys = [quote_identifier(key) for key in group_by or []]
|
|
10
10
|
columns = "".join(f"{key}, " for key in keys)
|
|
@@ -12,5 +12,5 @@ async def count_runs(
|
|
|
12
12
|
return await runs.query(
|
|
13
13
|
f"SELECT {columns}COUNT(*) AS runs,"
|
|
14
14
|
f" COALESCE(SUM(CASE WHEN ({completed_run}) THEN 1 ELSE 0 END), 0) AS completed"
|
|
15
|
-
f" FROM
|
|
15
|
+
f" FROM {source}{group}"
|
|
16
16
|
)
|
|
@@ -5,9 +5,9 @@ from labnotes.sql_quote import quote_identifier, quote_string
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
async def list_runs(
|
|
8
|
-
runs: DirSQL,
|
|
8
|
+
runs: DirSQL, source: str, completed_run: str, view: RunView
|
|
9
9
|
) -> list[dict[str, object]]:
|
|
10
|
-
where = [
|
|
10
|
+
where = []
|
|
11
11
|
if view.status:
|
|
12
12
|
negate = {"complete": "", "incomplete": "NOT "}[view.status]
|
|
13
13
|
where.append(f"{negate}({completed_run})")
|
|
@@ -16,6 +16,7 @@ async def list_runs(
|
|
|
16
16
|
f" lower({quote_string(value)})) > 0"
|
|
17
17
|
for column, value in view.filters.items()
|
|
18
18
|
]
|
|
19
|
+
filtered = f" WHERE {' AND '.join(where)}" if where else ""
|
|
19
20
|
direction = "DESC" if view.descending else "ASC"
|
|
20
21
|
if view.sort == "status":
|
|
21
22
|
order = f"labnotes_completed {direction}"
|
|
@@ -24,6 +25,6 @@ async def list_runs(
|
|
|
24
25
|
else:
|
|
25
26
|
order = "2 DESC"
|
|
26
27
|
return await runs.query(
|
|
27
|
-
f"SELECT ({completed_run}) AS labnotes_completed, * FROM
|
|
28
|
-
f"
|
|
28
|
+
f"SELECT ({completed_run}) AS labnotes_completed, * FROM {source}"
|
|
29
|
+
f"{filtered} ORDER BY {order}"
|
|
29
30
|
)
|
|
@@ -12,6 +12,7 @@ from labnotes.run_columns import run_columns
|
|
|
12
12
|
from labnotes.sort_href import sort_href
|
|
13
13
|
from labnotes.sql_quote import quote_string
|
|
14
14
|
from labnotes.study_progress import study_progress
|
|
15
|
+
from labnotes.study_runs import study_runs
|
|
15
16
|
from labnotes.summarize_design import summarize_design
|
|
16
17
|
|
|
17
18
|
|
|
@@ -46,7 +47,9 @@ async def load_experiment(
|
|
|
46
47
|
listed = (
|
|
47
48
|
[]
|
|
48
49
|
if study is None
|
|
49
|
-
else await list_runs(
|
|
50
|
+
else await list_runs(
|
|
51
|
+
runs, study_runs(study), str(summary["completed_run"]), view
|
|
52
|
+
)
|
|
50
53
|
)
|
|
51
54
|
return {
|
|
52
55
|
"name": row["name"],
|
|
@@ -23,7 +23,11 @@ async def run_experiment(
|
|
|
23
23
|
listen: Listen,
|
|
24
24
|
) -> list[dict[str, object]]:
|
|
25
25
|
runs = await list_experiment_runs(open_tables(config), name)
|
|
26
|
-
finished = [
|
|
26
|
+
finished = [
|
|
27
|
+
json.loads(str(run["params"]))
|
|
28
|
+
for run in runs
|
|
29
|
+
if run["exit_code"] == 0 and not run["excluded"]
|
|
30
|
+
]
|
|
27
31
|
plan = plan_runs(param_grid(experiment.params), experiment.repeats, finished)
|
|
28
32
|
report({"event": "planned", "runs": len(plan), "concurrency": concurrency})
|
|
29
33
|
running: set[asyncio.subprocess.Process] = set()
|
|
@@ -4,6 +4,7 @@ from dirsql import DirSQL
|
|
|
4
4
|
|
|
5
5
|
from labnotes.cell_progress import cell_progress
|
|
6
6
|
from labnotes.count_runs import count_runs
|
|
7
|
+
from labnotes.study_runs import study_runs
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
async def study_progress(
|
|
@@ -22,11 +23,12 @@ async def study_progress(
|
|
|
22
23
|
}
|
|
23
24
|
if study is None:
|
|
24
25
|
return progress
|
|
25
|
-
|
|
26
|
+
source = study_runs(study)
|
|
27
|
+
[totals] = await count_runs(runs, source, completed_run)
|
|
26
28
|
progress.update(totals)
|
|
27
29
|
if missing:
|
|
28
30
|
return progress
|
|
29
|
-
grouped = await count_runs(runs,
|
|
31
|
+
grouped = await count_runs(runs, source, completed_run, group_by=list(varies))
|
|
30
32
|
cells = cell_progress(varies, grouped)
|
|
31
33
|
progress["cells"] = cells
|
|
32
34
|
if isinstance(runs_per_cell, int):
|
|
@@ -5,6 +5,7 @@ from labnotes.sql_quote import quote_string
|
|
|
5
5
|
|
|
6
6
|
async def list_experiment_runs(tables: DirSQL, name: str) -> list[dict[str, object]]:
|
|
7
7
|
return await tables.query(
|
|
8
|
-
"SELECT id, created, ended, exit_code, error, params, folder
|
|
8
|
+
"SELECT id, created, ended, exit_code, error, excluded, reason, params, folder"
|
|
9
|
+
" FROM runs"
|
|
9
10
|
f" WHERE experiment = {quote_string(name)} ORDER BY created, id"
|
|
10
11
|
)
|
|
@@ -31,7 +31,8 @@ CREATE TABLE files (
|
|
|
31
31
|
RUNS = """
|
|
32
32
|
CREATE TABLE runs (
|
|
33
33
|
experiment TEXT, id TEXT, folder TEXT, created TEXT, ended TEXT,
|
|
34
|
-
exit_code INTEGER, error TEXT,
|
|
34
|
+
exit_code INTEGER, error TEXT, excluded INTEGER, reason TEXT,
|
|
35
|
+
stdout TEXT, stderr TEXT, params TEXT,
|
|
35
36
|
PRIMARY KEY (experiment, id)
|
|
36
37
|
)
|
|
37
38
|
"""
|
|
@@ -20,6 +20,8 @@ def read_run(root: Path, template: str, path: str) -> list[dict[str, object]]:
|
|
|
20
20
|
"ended": run.get("ended"),
|
|
21
21
|
"exit_code": run.get("exit_code"),
|
|
22
22
|
"error": run.get("error"),
|
|
23
|
+
"excluded": run.get("excluded") is True,
|
|
24
|
+
"reason": run.get("reason"),
|
|
23
25
|
"stdout": f"{folder}/stdout.log",
|
|
24
26
|
"stderr": f"{folder}/stderr.log",
|
|
25
27
|
"params": json.dumps(run.get("params", {})),
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|