labnotes 0.0.129__tar.gz → 0.0.130__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.129 → labnotes-0.0.130}/PKG-INFO +1 -1
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/context.md +13 -10
- labnotes-0.0.129/src/labnotes/runner/fill_ids.py → labnotes-0.0.130/src/labnotes/runner/fill_dirs.py +2 -2
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/fill_experiment_env.py +10 -7
- labnotes-0.0.130/src/labnotes/runner/hook_dirs.py +21 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/run_experiment.py +32 -23
- labnotes-0.0.129/src/labnotes/runner/hook_ids.py +0 -14
- {labnotes-0.0.129 → labnotes-0.0.130}/.gitignore +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/CHANGELOG.md +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/MIGRATIONS.md +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/README.md +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/pyproject.toml +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/__init__.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/__main__.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/asset_url.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/check_counts.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/cli.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/compose_experiment.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/context_guide.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/count_groups.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/count_runs.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/create_app.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/create_experiment.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/create_note.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/__init__.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/control_run.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/daemon_app.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/daemon_client.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/daemon_running.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/daemon_server.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/describe_status.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/ensure_daemon.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/exit_when_idle.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/finalize_lost_runs.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/last_stderr.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/remote_start.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/run_daemon.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/run_logs.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/serve_daemon.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/socket_path.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/stop_runs.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/watch_daemon.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon/watch_status.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/daemon_command.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/data_html.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/default_config_text.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/default_counts.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/drain_watch.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/experiment_notes.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/experiment_runs.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/experiments.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/file_changes.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/format_duration.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/format_started.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/format_value.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/grid_cell.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/group_runs.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/init.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/invocation_started.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/is_non_negative_int.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/is_non_negative_number.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/is_positive_int.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/list_experiments.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/list_runs.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/load_config.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/load_experiment.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/load_run.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/log.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/log_path.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/memory_interval.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/models.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/modes.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/nests_runs.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/note_path.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/notebook_kernel.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/output_html.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/parse_run_view.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/parse_subset.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/pivot_runs.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/print_rows.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/python_blocks.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/read_config.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/read_path.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/render_markdown.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/retries.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/run_command.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/run_control.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/run_output.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/run_status.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/__init__.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/cgroup_memory.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/check_args.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/check_subset.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/container_cgroup.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/container_memory.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/describe_event.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/docker_output.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/execute_run.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/exit_signal.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/flag_name.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/hold_folder.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/in_subset.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/invocation_hook.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/invocation_meta.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/new_param_run_id.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/new_run_id.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/new_stamped_run_id.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/param_args.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/param_grid.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/param_run_name.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/plan_runs.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/prepare_experiment.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/read_experiment_config.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/record_memory.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/run_folder.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/run_headless.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/runs_parent.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/shell_command.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/signal_tree.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/stop_then_kill.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/wait_for_tree.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runner/write_run_json.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/runs_view_command.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/save_conflict_copy.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/save_note.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/saved_outputs.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/serve_app.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/server.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/shared_params.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/sort_href.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/sql_quote.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/static/elapsed.js +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/static/experiment.js +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/static/labnotes.css +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/static/local-time.js +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/static/new-note.js +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/static/note-edit.js +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/static/note-editor.js +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/static/row-link.js +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/static/run-cell.js +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/static/run-output.js +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/static/view-toggle.js +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/summarize_config.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/__init__.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/experiment_rows.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/experiment_run_ids.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/experiment_toml.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/experiments_ddl.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/file_prefix.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/file_text.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/iso_time.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/list_experiment_runs.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/note_text.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/open_tables.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/path_glob.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/path_pattern.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/read_blocks.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/read_experiment.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/read_file.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/read_log.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/read_memory.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/read_run.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/read_run_file.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/runs_columns.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tables/summarize_experiments.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/templates/base.html +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/templates/editor_imports.html +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/templates/experiment.html +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/templates/index.html +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/templates/note.html +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/templates/run.html +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/__init__.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/browse_app.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/browse_tui.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/check_view_response.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/config.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/dim.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/experiment_screen.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/experiments_screen.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/fill_table.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/format_cell.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/format_elapsed.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/group_cells.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/invocation_columns.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/invocation_rows.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/leave_prompt.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/log_block.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/log_blocks.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/native_rows.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/reload_on_change.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/run_app.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/run_cells.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/run_output.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/run_screen.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/run_tui.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/runs_table.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/runs_view.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/stopped_title.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/view_column.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/tui/view_process.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/utils/__init__.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/utils/format_bytes.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/utils/process_alive.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/utils/run_usage.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/utils/tree_rss.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/utils/tree_usage.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/view/__init__.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/view/answer.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/view/build.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/view/respond.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/view/serve.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/wait_for_note.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/src/labnotes/watch_rows.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/testing-conventions.toml +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/tests/integration/conftest.py +0 -0
- {labnotes-0.0.129 → labnotes-0.0.130}/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.130
|
|
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>
|
|
@@ -72,10 +72,9 @@ Each run gets a new run folder. In `matrix` mode it is named for the UTC time it
|
|
|
72
72
|
its folder the same way. One that plans more gets one folder named that way, and its runs nest
|
|
73
73
|
inside it (`runs/20261020-000429-brave-fox/quiet-river`); the run id is that path under `runs/`. Either way, folder listings sort by start. `command` runs in a shell from the root, with
|
|
74
74
|
`{run_dir}` replaced by the run folder's absolute path. Pass it to the
|
|
75
|
-
script so it writes its outputs there. `{
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
stamped id that names no folder. All three are shell-quoted.
|
|
75
|
+
script so it writes its outputs there. `{invocation_dir}` is the shared adhoc
|
|
76
|
+
group folder's absolute path when several runs are planned; otherwise it equals
|
|
77
|
+
each run's `{run_dir}`. Both placeholders are shell-quoted.
|
|
79
78
|
Each param is appended as `--name value`, with the name as written (use
|
|
80
79
|
`source-language` for a `--source-language` flag), booleans as 0 or 1, and lists
|
|
81
80
|
and tables as JSON. labnotes writes `run.json` (params, `command`, created,
|
|
@@ -96,16 +95,20 @@ the value from the start, even if the code changed while they waited.
|
|
|
96
95
|
commands run once per `run` from the root: setup before the first run starts,
|
|
97
96
|
teardown after the last one ends, even if runs failed, were stopped, or setup
|
|
98
97
|
failed (so teardown must cope with a partial setup). A failing setup starts no
|
|
99
|
-
run; a failing teardown fails the invocation. Both get `{
|
|
100
|
-
|
|
101
|
-
|
|
98
|
+
run; a failing teardown fails the invocation. Both get `{invocation_dir}` only:
|
|
99
|
+
the shared folder for a multi-run adhoc invocation, or the run folder when one
|
|
100
|
+
run is planned. That folder exists before setup starts. In matrix mode with
|
|
101
|
+
several runs there is no shared folder, so `{invocation_dir}` in a hook fails.
|
|
102
|
+
`{run_dir}` is never filled in hooks; use `{invocation_dir}` instead. An
|
|
103
|
+
unavailable placeholder fails before anything starts.
|
|
102
104
|
`[env]` in `experiment.toml` sets string environment values for `command`,
|
|
103
105
|
`meta`, `setup`, and `teardown`. `[experiment.env]` in `.labnotes.toml`
|
|
104
106
|
provides shared values; experiment values replace them by name. Variables in
|
|
105
107
|
the environment that starts `labnotes experiments NAME run` win over both,
|
|
106
|
-
including inline assignments. Values can use raw `{run_dir}
|
|
107
|
-
`{
|
|
108
|
-
|
|
108
|
+
including inline assignments. Values can use raw `{run_dir}` and
|
|
109
|
+
`{invocation_dir}` placeholders. In hooks and meta, only `{invocation_dir}` is
|
|
110
|
+
available, and it requires one planned run in matrix mode.
|
|
111
|
+
`LABNOTES_*` names are reserved for labnotes.
|
|
109
112
|
A run counts when it exited 0 and its `run.json` doesn't hold
|
|
110
113
|
`"excluded": true`, so excluding a run by hand means adding that key; the next
|
|
111
114
|
`run` replaces it. Other keys you add to `run.json` are kept and show in `run`.
|
labnotes-0.0.129/src/labnotes/runner/fill_ids.py → labnotes-0.0.130/src/labnotes/runner/fill_dirs.py
RENAMED
|
@@ -2,7 +2,7 @@ import shlex
|
|
|
2
2
|
from collections.abc import Mapping
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
def
|
|
6
|
-
for name, value in
|
|
5
|
+
def fill_dirs(command: str, dirs: Mapping[str, str], *, quote: bool = True) -> str:
|
|
6
|
+
for name, value in dirs.items():
|
|
7
7
|
command = command.replace(f"{{{name}}}", shlex.quote(value) if quote else value)
|
|
8
8
|
return command
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
from collections.abc import Mapping
|
|
2
2
|
|
|
3
|
-
from labnotes.runner.
|
|
3
|
+
from labnotes.runner.fill_dirs import fill_dirs
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def fill_experiment_env(
|
|
7
7
|
configured: Mapping[str, str],
|
|
8
8
|
inherited: Mapping[str, str],
|
|
9
|
-
|
|
9
|
+
dirs: Mapping[str, str],
|
|
10
10
|
*,
|
|
11
11
|
hook: str | None = None,
|
|
12
12
|
runs: int = 1,
|
|
@@ -20,12 +20,15 @@ def fill_experiment_env(
|
|
|
20
20
|
for key, value in configured.items():
|
|
21
21
|
if key in caller:
|
|
22
22
|
continue
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
if hook is not None and "{run_dir}" in value:
|
|
24
|
+
raise ValueError(
|
|
25
|
+
f"{hook} env.{key} uses {{run_dir}}; use {{invocation_dir}} instead."
|
|
26
|
+
)
|
|
27
|
+
for name in ("run_dir", "invocation_dir"):
|
|
28
|
+
if f"{{{name}}}" in value and name not in dirs:
|
|
25
29
|
raise ValueError(
|
|
26
30
|
f"{hook} env.{key} uses {{{name}}}, but this invocation plans "
|
|
27
|
-
f"{runs} runs. {{{name}}} needs exactly one
|
|
28
|
-
"use {invocation_id} instead."
|
|
31
|
+
f"{runs} runs. {{{name}}} needs exactly one run in this mode."
|
|
29
32
|
)
|
|
30
|
-
filled[key] =
|
|
33
|
+
filled[key] = fill_dirs(value, dirs, quote=False)
|
|
31
34
|
return {**filled, **caller}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
def hook_dirs(
|
|
2
|
+
hooks: dict[str, str | None], invocation_dir: str | None, run_dirs: list[str]
|
|
3
|
+
) -> dict[str, str]:
|
|
4
|
+
match run_dirs:
|
|
5
|
+
case [run_dir]:
|
|
6
|
+
invocation_dir = invocation_dir or run_dir
|
|
7
|
+
available = {"invocation_dir": invocation_dir} if invocation_dir is not None else {}
|
|
8
|
+
for hook, command in hooks.items():
|
|
9
|
+
if command is None:
|
|
10
|
+
continue
|
|
11
|
+
if "{run_dir}" in command:
|
|
12
|
+
raise ValueError(
|
|
13
|
+
f"{hook} command {command} uses {{run_dir}}; "
|
|
14
|
+
"use {invocation_dir} instead."
|
|
15
|
+
)
|
|
16
|
+
if "{invocation_dir}" in command and invocation_dir is None:
|
|
17
|
+
raise ValueError(
|
|
18
|
+
f"{hook} command {command} uses {{invocation_dir}}, but this "
|
|
19
|
+
f"invocation plans {len(run_dirs)} runs and has no shared folder."
|
|
20
|
+
)
|
|
21
|
+
return available
|
|
@@ -2,6 +2,7 @@ import asyncio
|
|
|
2
2
|
import json
|
|
3
3
|
import os
|
|
4
4
|
import signal
|
|
5
|
+
from pathlib import Path
|
|
5
6
|
|
|
6
7
|
import psutil
|
|
7
8
|
|
|
@@ -15,8 +16,8 @@ from labnotes.models import (
|
|
|
15
16
|
from labnotes.retries import RETRY_EXIT_CODE, RETRY_SECONDS
|
|
16
17
|
from labnotes.runner.execute_run import execute_run
|
|
17
18
|
from labnotes.runner.fill_experiment_env import fill_experiment_env
|
|
18
|
-
from labnotes.runner.
|
|
19
|
-
from labnotes.runner.
|
|
19
|
+
from labnotes.runner.fill_dirs import fill_dirs
|
|
20
|
+
from labnotes.runner.hook_dirs import hook_dirs
|
|
20
21
|
from labnotes.runner.in_subset import in_subset
|
|
21
22
|
from labnotes.runner.invocation_hook import invocation_hook
|
|
22
23
|
from labnotes.runner.invocation_meta import invocation_meta
|
|
@@ -80,27 +81,24 @@ async def run_experiment(
|
|
|
80
81
|
run = new_id(params)
|
|
81
82
|
planned.add(run)
|
|
82
83
|
plan.append((run, params))
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
planned.add(invocation)
|
|
84
|
+
run_dirs = [
|
|
85
|
+
str(run_folder(config.root, config.runs, name, run).resolve())
|
|
86
|
+
for run, _ in plan
|
|
87
|
+
]
|
|
88
|
+
group_dir = (
|
|
89
|
+
str(run_folder(config.root, config.runs, name, group).resolve())
|
|
90
|
+
if group is not None
|
|
91
|
+
else None
|
|
92
|
+
)
|
|
93
93
|
hooks = {
|
|
94
94
|
"setup": experiment.setup,
|
|
95
95
|
"teardown": experiment.teardown,
|
|
96
96
|
"meta": experiment.meta,
|
|
97
97
|
}
|
|
98
|
-
|
|
99
|
-
if hook_run_dir is not None:
|
|
100
|
-
ids["run_dir"] = hook_run_dir
|
|
98
|
+
dirs = hook_dirs(hooks, group_dir, run_dirs)
|
|
101
99
|
hook_env = {
|
|
102
100
|
hook: fill_experiment_env(
|
|
103
|
-
experiment.env, inherited,
|
|
101
|
+
experiment.env, inherited, dirs, hook=hook, runs=len(plan)
|
|
104
102
|
)
|
|
105
103
|
for hook, command in hooks.items()
|
|
106
104
|
if command is not None
|
|
@@ -108,8 +106,10 @@ async def run_experiment(
|
|
|
108
106
|
meta = None
|
|
109
107
|
if experiment.meta is not None:
|
|
110
108
|
meta = await invocation_meta(
|
|
111
|
-
config.root,
|
|
109
|
+
config.root, fill_dirs(experiment.meta, dirs), hook_env["meta"]
|
|
112
110
|
)
|
|
111
|
+
if dirs:
|
|
112
|
+
Path(dirs["invocation_dir"]).mkdir(parents=True, exist_ok=True)
|
|
113
113
|
runs = [{"run": run, "params": params} for run, params in plan]
|
|
114
114
|
report(
|
|
115
115
|
{
|
|
@@ -238,14 +238,21 @@ async def run_experiment(
|
|
|
238
238
|
|
|
239
239
|
async def start(run: str, params: dict[str, object]) -> None:
|
|
240
240
|
folder = run_folder(config.root, config.runs, name, run)
|
|
241
|
-
folder.mkdir(parents=True)
|
|
241
|
+
folder.mkdir(parents=True, exist_ok=True)
|
|
242
|
+
run_invocation_dir = group_dir or str(folder.resolve())
|
|
242
243
|
report({"event": "started", "run": run, "params": params, "folder": folder})
|
|
243
244
|
running[run] = set()
|
|
244
245
|
trees[run] = set()
|
|
245
246
|
result = await execute_run(
|
|
246
247
|
config.root,
|
|
247
248
|
folder,
|
|
248
|
-
|
|
249
|
+
fill_dirs(
|
|
250
|
+
experiment.command,
|
|
251
|
+
{
|
|
252
|
+
"run_dir": str(folder.resolve()),
|
|
253
|
+
"invocation_dir": run_invocation_dir,
|
|
254
|
+
},
|
|
255
|
+
),
|
|
249
256
|
params,
|
|
250
257
|
running[run],
|
|
251
258
|
stopping,
|
|
@@ -262,8 +269,7 @@ async def run_experiment(
|
|
|
262
269
|
inherited,
|
|
263
270
|
{
|
|
264
271
|
"run_dir": str(folder.resolve()),
|
|
265
|
-
"
|
|
266
|
-
"invocation_id": invocation,
|
|
272
|
+
"invocation_dir": run_invocation_dir,
|
|
267
273
|
},
|
|
268
274
|
),
|
|
269
275
|
)
|
|
@@ -282,7 +288,7 @@ async def run_experiment(
|
|
|
282
288
|
await invocation_hook(
|
|
283
289
|
config.root,
|
|
284
290
|
"teardown",
|
|
285
|
-
|
|
291
|
+
fill_dirs(experiment.teardown, dirs),
|
|
286
292
|
hook_env["teardown"],
|
|
287
293
|
)
|
|
288
294
|
|
|
@@ -292,7 +298,10 @@ async def run_experiment(
|
|
|
292
298
|
if experiment.setup is not None:
|
|
293
299
|
report({"event": "setting up"})
|
|
294
300
|
await invocation_hook(
|
|
295
|
-
config.root,
|
|
301
|
+
config.root,
|
|
302
|
+
"setup",
|
|
303
|
+
fill_dirs(experiment.setup, dirs),
|
|
304
|
+
hook_env["setup"],
|
|
296
305
|
)
|
|
297
306
|
fill()
|
|
298
307
|
await done.wait()
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
def hook_ids(
|
|
2
|
-
hooks: dict[str, str | None], invocation: str, runs: list[str]
|
|
3
|
-
) -> dict[str, str]:
|
|
4
|
-
match runs:
|
|
5
|
-
case [run]:
|
|
6
|
-
return {"run_id": run, "invocation_id": invocation}
|
|
7
|
-
for hook, command in hooks.items():
|
|
8
|
-
if command is not None and "{run_id}" in command:
|
|
9
|
-
raise ValueError(
|
|
10
|
-
f"{hook} command {command} uses {{run_id}}, but this invocation plans "
|
|
11
|
-
f"{len(runs)} runs. {{run_id}} needs exactly one; "
|
|
12
|
-
"use {invocation_id} instead."
|
|
13
|
-
)
|
|
14
|
-
return {"invocation_id": invocation}
|
|
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
|
|
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
|
|
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
|