labnotes 0.0.118__tar.gz → 0.0.119__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.118 → labnotes-0.0.119}/PKG-INFO +3 -1
- {labnotes-0.0.118 → labnotes-0.0.119}/README.md +2 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/context.md +8 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/daemon_app.py +2 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/remote_start.py +2 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/experiments.py +13 -2
- labnotes-0.0.119/src/labnotes/parse_subset.py +10 -0
- labnotes-0.0.119/src/labnotes/runner/check_subset.py +13 -0
- labnotes-0.0.119/src/labnotes/runner/in_subset.py +5 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/prepare_experiment.py +4 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/run_experiment.py +6 -1
- {labnotes-0.0.118 → labnotes-0.0.119}/testing-conventions.toml +4 -4
- {labnotes-0.0.118 → labnotes-0.0.119}/.gitignore +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/CHANGELOG.md +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/MIGRATIONS.md +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/pyproject.toml +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/__init__.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/__main__.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/asset_url.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/check_counts.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/cli.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/compose_experiment.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/context_guide.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/count_groups.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/count_runs.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/create_app.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/create_experiment.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/create_note.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/__init__.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/control_run.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/daemon_client.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/daemon_running.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/daemon_server.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/describe_status.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/ensure_daemon.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/exit_when_idle.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/finalize_lost_runs.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/last_stderr.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/run_daemon.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/run_logs.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/serve_daemon.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/socket_path.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/stop_runs.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/watch_daemon.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon/watch_status.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/daemon_command.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/data_html.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/default_config_text.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/default_counts.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/drain_watch.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/experiment_notes.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/experiment_runs.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/file_changes.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/format_duration.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/format_started.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/format_value.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/grid_cell.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/group_runs.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/init.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/invocation_started.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/is_non_negative_int.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/is_non_negative_number.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/is_positive_int.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/list_experiments.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/list_runs.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/load_config.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/load_experiment.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/load_run.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/log.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/log_path.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/memory_interval.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/models.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/modes.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/nests_runs.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/note_path.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/notebook_kernel.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/output_html.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/parse_run_view.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/pivot_runs.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/print_rows.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/python_blocks.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/read_config.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/read_path.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/render_markdown.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/retries.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/run_command.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/run_control.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/run_output.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/run_status.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/__init__.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/describe_event.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/execute_run.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/exit_signal.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/hold_folder.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/invocation_meta.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/new_param_run_id.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/new_run_id.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/new_stamped_run_id.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/param_args.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/param_grid.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/param_run_name.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/plan_runs.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/read_experiment_config.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/record_memory.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/run_folder.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/run_headless.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/runs_parent.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/shell_command.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/signal_tree.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/stop_then_kill.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/wait_for_tree.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runner/write_run_json.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/runs_view_command.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/save_conflict_copy.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/save_note.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/saved_outputs.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/serve_app.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/server.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/shared_params.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/sort_href.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/sql_quote.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/static/elapsed.js +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/static/experiment.js +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/static/labnotes.css +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/static/local-time.js +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/static/new-note.js +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/static/note-edit.js +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/static/note-editor.js +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/static/row-link.js +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/static/run-cell.js +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/static/run-output.js +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/static/view-toggle.js +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/summarize_config.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/__init__.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/experiment_rows.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/experiment_run_ids.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/experiment_toml.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/experiments_ddl.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/file_prefix.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/file_text.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/iso_time.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/list_experiment_runs.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/note_text.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/open_tables.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/path_glob.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/path_pattern.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/read_blocks.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/read_experiment.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/read_file.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/read_log.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/read_memory.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/read_run.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/read_run_file.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/runs_columns.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tables/summarize_experiments.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/templates/base.html +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/templates/editor_imports.html +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/templates/experiment.html +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/templates/index.html +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/templates/note.html +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/templates/run.html +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/__init__.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/browse_app.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/browse_tui.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/check_view_response.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/config.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/dim.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/experiment_screen.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/experiments_screen.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/fill_table.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/format_cell.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/format_elapsed.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/group_cells.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/invocation_columns.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/invocation_rows.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/leave_prompt.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/log_block.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/log_blocks.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/native_rows.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/reload_on_change.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/run_app.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/run_cells.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/run_output.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/run_screen.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/run_tui.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/runs_table.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/runs_view.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/stopped_title.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/view_column.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/tui/view_process.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/utils/__init__.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/utils/format_bytes.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/utils/process_alive.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/utils/run_usage.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/utils/tree_rss.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/utils/tree_usage.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/view/__init__.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/view/answer.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/view/build.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/view/respond.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/view/serve.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/wait_for_note.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/src/labnotes/watch_rows.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/tests/integration/conftest.py +0 -0
- {labnotes-0.0.118 → labnotes-0.0.119}/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.119
|
|
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>
|
|
@@ -120,6 +120,8 @@ line per event instead.
|
|
|
120
120
|
|
|
121
121
|
- `--concurrency N` runs N at a time (default 1).
|
|
122
122
|
- `-e PATH` reads another file instead of `experiment.toml`.
|
|
123
|
+
- `--PARAM=VALUE` runs only the cells where that param has that value, like
|
|
124
|
+
`--model=small`.
|
|
123
125
|
- With runs going, Ctrl-C asks first. Enter (or a second Ctrl-C) leaves them
|
|
124
126
|
running. `s` stops the running scripts and records their end, then kills any
|
|
125
127
|
still going 5 seconds later. Escape goes back. SIGTERM stops them like `s`.
|
|
@@ -95,6 +95,8 @@ line per event instead.
|
|
|
95
95
|
|
|
96
96
|
- `--concurrency N` runs N at a time (default 1).
|
|
97
97
|
- `-e PATH` reads another file instead of `experiment.toml`.
|
|
98
|
+
- `--PARAM=VALUE` runs only the cells where that param has that value, like
|
|
99
|
+
`--model=small`.
|
|
98
100
|
- With runs going, Ctrl-C asks first. Enter (or a second Ctrl-C) leaves them
|
|
99
101
|
running. `s` stops the running scripts and records their end, then kills any
|
|
100
102
|
still going 5 seconds later. Escape goes back. SIGTERM stops them like `s`.
|
|
@@ -151,6 +151,14 @@ going. Elsewhere, it prints a line per event instead.
|
|
|
151
151
|
in `experiment.toml` sets it, then `concurrency` under `[experiments]` in
|
|
152
152
|
`.labnotes.toml`, then 1.
|
|
153
153
|
- `-e PATH` reads another file instead of `experiment.toml`.
|
|
154
|
+
- `--PARAM=VALUE` runs only the cells where that param has that value, e.g.
|
|
155
|
+
`labnotes experiments NAME run --model=small`. PARAM must be a key in
|
|
156
|
+
`[params]` and VALUE one of its values, written as it shows in `runs`
|
|
157
|
+
(`true`, `2`); anything else is an error. One value per param; give several
|
|
158
|
+
params to narrow further (`--model=small --lang=en`). It changes only what
|
|
159
|
+
this `run` starts: counts, progress and `repeats` still cover the full
|
|
160
|
+
matrix, so a later plain `run` fills in the rest. Use it instead of editing
|
|
161
|
+
`experiment.toml` to run a slice.
|
|
154
162
|
- `--timeout SECONDS` stops any one run still going after that many seconds:
|
|
155
163
|
SIGTERM, then SIGKILL 5 seconds later. Its
|
|
156
164
|
`run.json` gets `"error": "timed out after ..."` and `"ended_by": "timeout"`
|
|
@@ -78,6 +78,7 @@ def daemon_app(config: LabnotesConfig) -> Starlette:
|
|
|
78
78
|
name,
|
|
79
79
|
None if path is None else Path(str(path)),
|
|
80
80
|
body.get("concurrency"), # type: ignore[arg-type]
|
|
81
|
+
body.get("only"), # type: ignore[arg-type]
|
|
81
82
|
)
|
|
82
83
|
except ValueError as error:
|
|
83
84
|
return refuse(400, str(error))
|
|
@@ -103,6 +104,7 @@ def daemon_app(config: LabnotesConfig) -> Starlette:
|
|
|
103
104
|
lambda event: record({**event, "experiment": name}),
|
|
104
105
|
listen,
|
|
105
106
|
body.get("timeout"), # type: ignore[arg-type]
|
|
107
|
+
only=body.get("only"), # type: ignore[arg-type]
|
|
106
108
|
)
|
|
107
109
|
# Clients hear why the session ended; the daemon keeps serving.
|
|
108
110
|
except Exception as failure: # noqa: BLE001
|
|
@@ -16,6 +16,7 @@ def remote_start(
|
|
|
16
16
|
experiment_config: Path | None,
|
|
17
17
|
concurrency: int | None,
|
|
18
18
|
timeout: float | None = None,
|
|
19
|
+
only: dict[str, str] | None = None,
|
|
19
20
|
) -> Start:
|
|
20
21
|
async def start(report: Report, listen: Listen) -> list[dict[str, object]]:
|
|
21
22
|
try:
|
|
@@ -46,6 +47,7 @@ def remote_start(
|
|
|
46
47
|
else str(experiment_config.resolve()),
|
|
47
48
|
"concurrency": concurrency,
|
|
48
49
|
"timeout": timeout,
|
|
50
|
+
"only": only,
|
|
49
51
|
},
|
|
50
52
|
)
|
|
51
53
|
if reply.status_code != 202:
|
|
@@ -8,6 +8,7 @@ from labnotes.create_experiment import create_experiment
|
|
|
8
8
|
from labnotes.daemon.remote_start import remote_start
|
|
9
9
|
from labnotes.utils.format_bytes import format_bytes
|
|
10
10
|
from labnotes.load_config import load_config
|
|
11
|
+
from labnotes.parse_subset import parse_subset
|
|
11
12
|
from labnotes.print_rows import print_rows
|
|
12
13
|
from labnotes.read_config import CONFIG_FILE
|
|
13
14
|
from labnotes.runner.run_headless import run_headless
|
|
@@ -20,7 +21,9 @@ BYTES = ("memory", "size")
|
|
|
20
21
|
|
|
21
22
|
@click.command(
|
|
22
23
|
help="List experiments, show one, list its runs, or run it."
|
|
23
|
-
" `new [NAME]` creates one."
|
|
24
|
+
" `new [NAME]` creates one. With run, --PARAM=VALUE runs only the"
|
|
25
|
+
" matrix cells where that param has that value.",
|
|
26
|
+
context_settings={"ignore_unknown_options": True, "allow_extra_args": True},
|
|
24
27
|
)
|
|
25
28
|
@click.argument("name", required=False)
|
|
26
29
|
@click.argument("action", required=False, metavar="[runs|run]")
|
|
@@ -74,7 +77,13 @@ def experiments(
|
|
|
74
77
|
click.echo(f"Created {path / 'experiment.toml'}")
|
|
75
78
|
return
|
|
76
79
|
case str(), "run":
|
|
77
|
-
|
|
80
|
+
try:
|
|
81
|
+
only = parse_subset(ctx.args)
|
|
82
|
+
except ValueError as error:
|
|
83
|
+
raise click.UsageError(str(error)) from error
|
|
84
|
+
start = remote_start(
|
|
85
|
+
config, name, experiment_config, concurrency, timeout, only
|
|
86
|
+
)
|
|
78
87
|
try:
|
|
79
88
|
if sys.stdout.isatty() and sys.stderr.isatty():
|
|
80
89
|
results = run_tui(start, name)
|
|
@@ -92,6 +101,8 @@ def experiments(
|
|
|
92
101
|
passed = len(results) - failed - retried
|
|
93
102
|
click.echo(f"{passed} passed, {failed} failed.{again}")
|
|
94
103
|
return
|
|
104
|
+
if ctx.args:
|
|
105
|
+
raise click.UsageError(f"Unexpected {ctx.args[0]}. --PARAM=VALUE needs run.")
|
|
95
106
|
if action not in (None, "runs"):
|
|
96
107
|
raise click.UsageError(f"Unknown action {action}. Use runs or run.")
|
|
97
108
|
if output_format is None and sys.stdout.isatty() and sys.stderr.isatty():
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
def parse_subset(args: list[str]) -> dict[str, str]:
|
|
2
|
+
only: dict[str, str] = {}
|
|
3
|
+
for arg in args:
|
|
4
|
+
param, equals, value = arg.removeprefix("--").partition("=")
|
|
5
|
+
if not arg.startswith("--") or not equals or not param:
|
|
6
|
+
raise ValueError(f"Unexpected {arg}. Pick params with --PARAM=VALUE.")
|
|
7
|
+
if param in only:
|
|
8
|
+
raise ValueError(f"--{param} given twice. Pass one value per param.")
|
|
9
|
+
only[param] = value
|
|
10
|
+
return only
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from labnotes.format_value import format_value
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def check_subset(params: dict[str, list[object]], only: dict[str, str]) -> None:
|
|
5
|
+
for param, value in only.items():
|
|
6
|
+
if param not in params:
|
|
7
|
+
declared = ", ".join(params) or "none"
|
|
8
|
+
raise ValueError(f"No param {param}. Params: {declared}.")
|
|
9
|
+
values = [format_value(option) for option in params[param]]
|
|
10
|
+
if value not in values:
|
|
11
|
+
raise ValueError(
|
|
12
|
+
f"No value {value} for {param}. Values: {', '.join(values)}."
|
|
13
|
+
)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
|
|
3
3
|
from labnotes.models import ExperimentConfig, LabnotesConfig
|
|
4
|
+
from labnotes.runner.check_subset import check_subset
|
|
4
5
|
from labnotes.runner.read_experiment_config import read_experiment_config
|
|
5
6
|
from labnotes.tables.file_text import file_text
|
|
6
7
|
|
|
@@ -10,6 +11,7 @@ async def prepare_experiment(
|
|
|
10
11
|
name: str,
|
|
11
12
|
experiment_config: Path | None,
|
|
12
13
|
concurrency: int | None,
|
|
14
|
+
only: dict[str, str] | None = None,
|
|
13
15
|
) -> tuple[ExperimentConfig, int]:
|
|
14
16
|
if config.experiment not in (None, name):
|
|
15
17
|
raise ValueError(
|
|
@@ -29,4 +31,6 @@ async def prepare_experiment(
|
|
|
29
31
|
config.retries,
|
|
30
32
|
config.defaults,
|
|
31
33
|
)
|
|
34
|
+
if only:
|
|
35
|
+
check_subset(experiment.params, only)
|
|
32
36
|
return experiment, experiment.concurrency if concurrency is None else concurrency
|
|
@@ -13,6 +13,7 @@ from labnotes.models import (
|
|
|
13
13
|
)
|
|
14
14
|
from labnotes.retries import RETRY_EXIT_CODE, RETRY_SECONDS
|
|
15
15
|
from labnotes.runner.execute_run import execute_run
|
|
16
|
+
from labnotes.runner.in_subset import in_subset
|
|
16
17
|
from labnotes.runner.invocation_meta import invocation_meta
|
|
17
18
|
from labnotes.runner.new_param_run_id import new_param_run_id
|
|
18
19
|
from labnotes.runner.new_stamped_run_id import new_stamped_run_id
|
|
@@ -36,6 +37,7 @@ async def run_experiment(
|
|
|
36
37
|
listen: Listen,
|
|
37
38
|
timeout: float | None = None,
|
|
38
39
|
retry_seconds: float = RETRY_SECONDS,
|
|
40
|
+
only: dict[str, str] | None = None,
|
|
39
41
|
) -> list[dict[str, object]]:
|
|
40
42
|
meta = None
|
|
41
43
|
if experiment.meta is not None:
|
|
@@ -52,7 +54,10 @@ async def run_experiment(
|
|
|
52
54
|
def taken(run: str) -> bool:
|
|
53
55
|
return run in planned or run in existing
|
|
54
56
|
|
|
55
|
-
|
|
57
|
+
grid = [
|
|
58
|
+
cell for cell in param_grid(experiment.params) if in_subset(cell, only or {})
|
|
59
|
+
]
|
|
60
|
+
cells = plan_runs(grid, experiment.repeats, finished)
|
|
56
61
|
group = None
|
|
57
62
|
match experiment.mode:
|
|
58
63
|
case "adhoc" if len(cells) > 1:
|
|
@@ -25,13 +25,13 @@ reason = "quiet counts up by one from zero, so it reaches IDLE_EXIT_SECONDS befo
|
|
|
25
25
|
[[python.exempt]]
|
|
26
26
|
path = "src/labnotes/daemon/daemon_app.py"
|
|
27
27
|
rules = ["mutation"]
|
|
28
|
-
lines = [
|
|
28
|
+
lines = [134]
|
|
29
29
|
reason = "start answers 202, 400, 409 or 500, so every status but 202 is above it: != equals >"
|
|
30
30
|
|
|
31
31
|
[[python.exempt]]
|
|
32
32
|
path = "src/labnotes/daemon/remote_start.py"
|
|
33
33
|
rules = ["mutation"]
|
|
34
|
-
lines = [
|
|
34
|
+
lines = [51]
|
|
35
35
|
reason = "the daemon answers a run with 202, 400, 409 or 500, so every status but 202 is above it: != equals >"
|
|
36
36
|
|
|
37
37
|
[[python.exempt]]
|
|
@@ -67,7 +67,7 @@ reason = "WorkerState members are singletons, so is equals =="
|
|
|
67
67
|
[[python.exempt]]
|
|
68
68
|
path = "src/labnotes/runner/run_experiment.py"
|
|
69
69
|
rules = ["mutation"]
|
|
70
|
-
lines = [
|
|
70
|
+
lines = [193, 274]
|
|
71
71
|
reason = "a retry is only scheduled below the budget and each one adds one, so tried never passes retries: >= equals ==; both sides are small ints, which CPython caches, so is equals =="
|
|
72
72
|
|
|
73
73
|
[[python.exempt]]
|
|
@@ -79,5 +79,5 @@ reason = "exit_code is non-negative here; when bit 7 is set, - 128 equals ^ 128,
|
|
|
79
79
|
[[python.exempt]]
|
|
80
80
|
path = "src/labnotes/experiments.py"
|
|
81
81
|
rules = ["mutation"]
|
|
82
|
-
lines = [
|
|
82
|
+
lines = [120]
|
|
83
83
|
reason = "click hands back the \"json\" choice literal itself, so is not equals !="
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|