labnotes 0.2.18__tar.gz → 0.2.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.2.18 → labnotes-0.2.19}/PKG-INFO +1 -1
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/daemon/server.py +2 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/experiments.py +29 -1
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/models.py +2 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/retries.py +1 -1
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/describe_event.py +4 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/prepare_experiment.py +6 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/run_experiment.py +18 -8
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/start_experiment.py +12 -1
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/list_resumable_runs.py +6 -1
- {labnotes-0.2.18 → labnotes-0.2.19}/.gitignore +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/CHANGELOG.md +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/MIGRATIONS.md +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/README.md +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/conftest.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/pyproject.toml +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/__init__.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/__main__.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/asset_url.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/check_counts.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/cli.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/command_line_group.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/compose_experiment.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/config_migration.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/context.md +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/context_guide.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/copy_experiment.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/count_groups.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/count_runs.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/create_app.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/create_experiment.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/create_note.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/daemon/__init__.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/daemon/client.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/daemon/command.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/daemon/ensure.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/daemon/marker.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/daemon/socket_path.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/daemon_command.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/data_html.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/default_config_text.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/default_counts.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/drain_watch.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/experiment_definition.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/experiment_notes.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/experiment_runs.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/file_changes.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/format_duration.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/format_started.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/format_value.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/get_state.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/grid_cell.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/group_runs.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/init.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/invocation_started.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/is_non_negative_int.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/is_non_negative_number.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/is_positive_int.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/latest_log.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/list_experiments.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/list_runs.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/load_config.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/load_experiment.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/load_run.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/log.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/log_path.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/memory_interval.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/nests_runs.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/note_path.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/notebook_kernel.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/output_html.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/param_names.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/parse_param_value.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/parse_params.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/parse_run_view.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/parse_subset.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/pivot_runs.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/print_rows.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/python_blocks.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/read_config.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/read_path.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/render_markdown.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/run_columns.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/run_output.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/__init__.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/cgroup_memory.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/check_args.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/check_hook_placeholders.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/check_subset.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/claim_run.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/command_flags.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/container_cgroup.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/container_memory.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/continue_run.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/docker_output.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/execute_run.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/exit_signal.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/fill_dirs.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/fill_experiment_env.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/finalize_lost_runs.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/first_invocation.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/flag_name.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/group_args.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/hold_experiment.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/in_subset.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/invocation_hook.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/invocation_meta.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/new_run_id.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/new_stamped_run_id.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/override_flags.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/param_args.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/param_grid.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/placeholders.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/plan_runs.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/project_snapshot.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/read_experiment_config.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/record_memory.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/run_folder.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/run_git.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/run_headless.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/run_locked.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/run_state.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/runs_parent.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/shell_command.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/signal_tree.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/stop_then_kill.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/untracked_diff.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/wait_for_tree.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runner/write_run_json.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/runs_view_command.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/save_conflict_copy.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/save_note.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/saved_outputs.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/serve_app.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/server.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/set_state.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/shared_params.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/sort_href.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/sql_quote.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/state_path.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/static/elapsed.js +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/static/experiment.js +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/static/labnotes.css +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/static/local-time.js +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/static/new-note.js +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/static/note-edit.js +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/static/note-editor.js +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/static/row-link.js +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/static/run-cell.js +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/static/run-output.js +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/static/view-toggle.js +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/summarize_config.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/__init__.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/experiment_rows.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/experiment_run_ids.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/experiment_toml.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/experiments_ddl.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/file_prefix.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/file_text.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/iso_time.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/list_experiment_runs.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/note_text.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/open_tables.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/path_glob.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/path_pattern.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/read_blocks.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/read_experiment.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/read_file.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/read_log.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/read_memory.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/read_run.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/read_run_file.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/runs_columns.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tables/summarize_experiments.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/templates/base.html +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/templates/editor_imports.html +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/templates/experiment.html +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/templates/index.html +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/templates/note.html +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/templates/run.html +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/__init__.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/browse_app.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/browse_tui.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/check_view_response.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/config.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/dim.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/experiment_screen.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/experiments_screen.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/fill_table.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/format_cell.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/format_elapsed.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/guard_view.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/leave_prompt.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/load_view.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/log_block.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/log_blocks.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/native_rows.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/reload_on_change.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/run_app.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/run_cells.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/run_output.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/run_panel.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/run_tui.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/runs_browser.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/runs_table.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/runs_view.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/stopped_title.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/table_columns.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/table_rows.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/view_column.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/view_pane.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/view_process.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/tui/view_switcher.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/utils/__init__.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/utils/format_bytes.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/utils/process_alive.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/utils/run_usage.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/utils/tree_rss.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/utils/tree_usage.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/view/__init__.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/view/answer.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/view/build.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/view/changed.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/view/experiment.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/view/respond.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/view/serve.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/view_specs.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/wait_for_note.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/src/labnotes/watch_rows.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/testing-conventions.toml +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/tests/conftest.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/tests/e2e/conftest.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/tests/integration/conftest.py +0 -0
- {labnotes-0.2.18 → labnotes-0.2.19}/uv.lock +0 -0
|
@@ -61,6 +61,8 @@ class ExperimentDaemon:
|
|
|
61
61
|
cast(str | None, options.get("teardown")),
|
|
62
62
|
cast(str | None, options.get("command_line")),
|
|
63
63
|
cast(str | None, options.get("run_id")),
|
|
64
|
+
cast(int | None, options.get("retries")),
|
|
65
|
+
bool(options.get("replace_capped")),
|
|
64
66
|
)
|
|
65
67
|
path = str(selected.run_state.path)
|
|
66
68
|
invocation = Invocation()
|
|
@@ -60,7 +60,23 @@ class PassthroughCommand(click.Command):
|
|
|
60
60
|
help="With run: how many runs at once. Overrides experiment.toml and"
|
|
61
61
|
" .labnotes.toml; 1 if none sets it.",
|
|
62
62
|
)
|
|
63
|
-
@click.option(
|
|
63
|
+
@click.option(
|
|
64
|
+
"--run-id",
|
|
65
|
+
help="With run: restart only this failed run by id, even if out of retries.",
|
|
66
|
+
)
|
|
67
|
+
@click.option(
|
|
68
|
+
"--retries",
|
|
69
|
+
type=click.IntRange(min=0),
|
|
70
|
+
help="With run: how many times a failed run is tried again, on exit 75 or,"
|
|
71
|
+
" with continues, by a later run. Overrides experiment.toml and"
|
|
72
|
+
" .labnotes.toml; 3 if none sets it.",
|
|
73
|
+
)
|
|
74
|
+
@click.option(
|
|
75
|
+
"--replace-capped",
|
|
76
|
+
is_flag=True,
|
|
77
|
+
help="With run: start a fresh run for a cell whose run is out of retries."
|
|
78
|
+
" Unset, that cell stays short.",
|
|
79
|
+
)
|
|
64
80
|
@click.option(
|
|
65
81
|
"--headless",
|
|
66
82
|
is_flag=True,
|
|
@@ -124,6 +140,8 @@ def experiments(
|
|
|
124
140
|
output_format: str | None,
|
|
125
141
|
concurrency: int | None,
|
|
126
142
|
run_id: str | None,
|
|
143
|
+
retries: int | None,
|
|
144
|
+
replace_capped: bool,
|
|
127
145
|
headless: bool,
|
|
128
146
|
experiment_config: Path | None,
|
|
129
147
|
timeout: int | None,
|
|
@@ -191,6 +209,8 @@ def experiments(
|
|
|
191
209
|
"teardown": teardown,
|
|
192
210
|
"command_line": ctx.meta.get(COMMAND_LINE),
|
|
193
211
|
"run_id": run_id,
|
|
212
|
+
"retries": retries,
|
|
213
|
+
"replace_capped": replace_capped,
|
|
194
214
|
},
|
|
195
215
|
},
|
|
196
216
|
)
|
|
@@ -220,6 +240,8 @@ def experiments(
|
|
|
220
240
|
teardown,
|
|
221
241
|
ctx.meta.get(COMMAND_LINE),
|
|
222
242
|
run_id,
|
|
243
|
+
retries,
|
|
244
|
+
replace_capped,
|
|
223
245
|
)
|
|
224
246
|
)
|
|
225
247
|
except ValueError as error:
|
|
@@ -239,6 +261,8 @@ def experiments(
|
|
|
239
261
|
output_format is not None
|
|
240
262
|
or concurrency is not None
|
|
241
263
|
or run_id is not None
|
|
264
|
+
or retries is not None
|
|
265
|
+
or replace_capped
|
|
242
266
|
or experiment_config is not None
|
|
243
267
|
or timeout is not None
|
|
244
268
|
or setup is not None
|
|
@@ -261,6 +285,10 @@ def experiments(
|
|
|
261
285
|
raise click.UsageError("-- ARGS needs run.")
|
|
262
286
|
if run_id is not None:
|
|
263
287
|
raise click.UsageError("--run-id needs run.")
|
|
288
|
+
if retries is not None:
|
|
289
|
+
raise click.UsageError("--retries needs run.")
|
|
290
|
+
if replace_capped:
|
|
291
|
+
raise click.UsageError("--replace-capped needs run.")
|
|
264
292
|
if ctx.args:
|
|
265
293
|
raise click.UsageError(f"Unexpected {ctx.args[0]}. --PARAM=VALUE needs run.")
|
|
266
294
|
if action not in (None, "runs"):
|
|
@@ -33,6 +33,10 @@ def describe_event(event: dict[str, object]) -> str:
|
|
|
33
33
|
case "gave up":
|
|
34
34
|
tried = f"after {event['retries']} retries"
|
|
35
35
|
return f"{event['run']} gave up (exit {RETRY_EXIT_CODE}) {tried}."
|
|
36
|
+
case "capped":
|
|
37
|
+
cells = len(event["runs"]) # type: ignore[arg-type]
|
|
38
|
+
noun = "cell" if cells == 1 else "cells"
|
|
39
|
+
return f"{cells} {noun} gave up after {event['retries']} retries."
|
|
36
40
|
case "retry cancelled":
|
|
37
41
|
return f"{event['run']} won't retry."
|
|
38
42
|
case "idle":
|
|
@@ -17,6 +17,8 @@ async def prepare_experiment(
|
|
|
17
17
|
args: list[str] | None = None,
|
|
18
18
|
setup: str | None = None,
|
|
19
19
|
teardown: str | None = None,
|
|
20
|
+
retries: int | None = None,
|
|
21
|
+
replace_capped: bool = False,
|
|
20
22
|
) -> tuple[ExperimentConfig, int]:
|
|
21
23
|
if config.experiment not in (None, name):
|
|
22
24
|
raise ValueError(
|
|
@@ -39,6 +41,10 @@ async def prepare_experiment(
|
|
|
39
41
|
experiment = dataclasses.replace(experiment, setup=setup)
|
|
40
42
|
if teardown is not None:
|
|
41
43
|
experiment = dataclasses.replace(experiment, teardown=teardown)
|
|
44
|
+
if retries is not None:
|
|
45
|
+
experiment = dataclasses.replace(experiment, retries=retries)
|
|
46
|
+
if replace_capped:
|
|
47
|
+
experiment = dataclasses.replace(experiment, replace_capped=True)
|
|
42
48
|
if only:
|
|
43
49
|
check_subset(experiment.params, only)
|
|
44
50
|
if args:
|
|
@@ -84,6 +84,17 @@ async def run_experiment(
|
|
|
84
84
|
for r in counted
|
|
85
85
|
if r["counted"] or str(r.get("id")) in held_ids
|
|
86
86
|
]
|
|
87
|
+
resumable: list[Entry] = []
|
|
88
|
+
capped: list[Entry] = []
|
|
89
|
+
tries: dict[str, int] = {}
|
|
90
|
+
if experiment.continues:
|
|
91
|
+
for row in await list_resumable_runs(tables, name, experiment.counts):
|
|
92
|
+
entry = (str(row["id"]), json.loads(str(row["params"])))
|
|
93
|
+
tries[entry[0]] = int(str(row["invocations"]))
|
|
94
|
+
over = tries[entry[0]] > experiment.retries
|
|
95
|
+
(capped if over else resumable).append(entry)
|
|
96
|
+
if not experiment.replace_capped:
|
|
97
|
+
finished += [params for _, params in capped]
|
|
87
98
|
planned: set[str] = set()
|
|
88
99
|
|
|
89
100
|
def taken(run: str) -> bool:
|
|
@@ -112,12 +123,6 @@ async def run_experiment(
|
|
|
112
123
|
def release(run: str) -> None:
|
|
113
124
|
os.close(locks.pop(run))
|
|
114
125
|
|
|
115
|
-
resumable: list[Entry] = []
|
|
116
|
-
if experiment.continues:
|
|
117
|
-
resumable = [
|
|
118
|
-
(str(row["id"]), json.loads(str(row["params"])))
|
|
119
|
-
for row in await list_resumable_runs(tables, name, experiment.counts)
|
|
120
|
-
]
|
|
121
126
|
plan: list[Entry] = []
|
|
122
127
|
target_folder: Path | None = None
|
|
123
128
|
if run_id is not None:
|
|
@@ -155,6 +160,8 @@ async def run_experiment(
|
|
|
155
160
|
run = new_stamped_run_id(taken) if resumed is None else resumed[0]
|
|
156
161
|
planned.add(run)
|
|
157
162
|
plan.append((run, params))
|
|
163
|
+
# A resumed run's earlier invocations spend the same retries as exit 75 does.
|
|
164
|
+
earlier = {run: tries[run] for run, _ in plan if run in tries and run != run_id}
|
|
158
165
|
hooks = {
|
|
159
166
|
"setup": experiment.setup,
|
|
160
167
|
"teardown": experiment.teardown,
|
|
@@ -180,6 +187,9 @@ async def run_experiment(
|
|
|
180
187
|
)
|
|
181
188
|
for row in held:
|
|
182
189
|
emit({"event": "held", "run": str(row["id"])})
|
|
190
|
+
gave_up = [run for run, params in capped if in_subset(params, only or {})]
|
|
191
|
+
if gave_up and run_id is None and not experiment.replace_capped:
|
|
192
|
+
emit({"event": "capped", "runs": gave_up, "retries": experiment.retries})
|
|
183
193
|
running: dict[str, set[asyncio.subprocess.Process]] = {}
|
|
184
194
|
trees: dict[str, set[psutil.Process]] = {}
|
|
185
195
|
stopped: set[str] = set()
|
|
@@ -240,11 +250,11 @@ async def run_experiment(
|
|
|
240
250
|
fill()
|
|
241
251
|
|
|
242
252
|
def retry_later(run: str) -> None:
|
|
243
|
-
tried = attempts.get(run, 0)
|
|
253
|
+
tried = attempts.get(run, earlier.get(run, 0))
|
|
244
254
|
if tried >= experiment.retries:
|
|
245
255
|
emit({"event": "gave up", "run": run, "retries": tried})
|
|
246
256
|
return
|
|
247
|
-
seconds = retry_seconds * 2**tried
|
|
257
|
+
seconds = retry_seconds * 2 ** (tried - earlier.get(run, 0))
|
|
248
258
|
|
|
249
259
|
def due() -> None:
|
|
250
260
|
del waiting[run]
|
|
@@ -32,12 +32,23 @@ def start_experiment(
|
|
|
32
32
|
teardown: str | None,
|
|
33
33
|
command_line: str | None = None,
|
|
34
34
|
run_id: str | None = None,
|
|
35
|
+
retries: int | None = None,
|
|
36
|
+
replace_capped: bool = False,
|
|
35
37
|
) -> ExperimentStart:
|
|
36
38
|
state = RunState.create(config, name)
|
|
37
39
|
|
|
38
40
|
async def start(report: Report, listen: Listen) -> list[dict[str, object]]:
|
|
39
41
|
experiment, limit = await prepare_experiment(
|
|
40
|
-
config,
|
|
42
|
+
config,
|
|
43
|
+
name,
|
|
44
|
+
experiment_config,
|
|
45
|
+
concurrency,
|
|
46
|
+
only,
|
|
47
|
+
args,
|
|
48
|
+
setup,
|
|
49
|
+
teardown,
|
|
50
|
+
retries,
|
|
51
|
+
replace_capped,
|
|
41
52
|
)
|
|
42
53
|
await finalize_lost_runs(config)
|
|
43
54
|
with project_snapshot(config.root) as snapshot:
|
|
@@ -8,8 +8,13 @@ async def list_resumable_runs(
|
|
|
8
8
|
tables: DirSQL, name: str, counts: str
|
|
9
9
|
) -> list[dict[str, object]]:
|
|
10
10
|
# Ended badly: a nonzero or missing exit code, not merely uncounted.
|
|
11
|
+
# Invocations stopped by hand don't spend retries.
|
|
11
12
|
return await tables.query(
|
|
12
|
-
|
|
13
|
+
"SELECT id, params, CASE WHEN json_type(run, '$.invocations') = 'array'"
|
|
14
|
+
" THEN (SELECT count(*) FROM json_each(run, '$.invocations')"
|
|
15
|
+
" WHERE json_extract(value, '$.ended_by') IS NOT 'stop')"
|
|
16
|
+
" ELSE json_extract(run, '$.ended_by') IS NOT 'stop' END AS invocations"
|
|
17
|
+
f" FROM runs WHERE experiment = {quote_string(name)}"
|
|
13
18
|
f" AND NOT coalesce(({counts}), false) AND NOT {UNFINISHED}"
|
|
14
19
|
" AND (exit_code IS NULL OR exit_code <> 0)"
|
|
15
20
|
" AND NOT coalesce(run ->> 'excluded', false) ORDER BY created, id"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|