labnotes 0.0.114__tar.gz → 0.0.116__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.114 → labnotes-0.0.116}/PKG-INFO +2 -1
- {labnotes-0.0.114 → labnotes-0.0.116}/pyproject.toml +1 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon/describe_status.py +2 -0
- labnotes-0.0.116/src/labnotes/daemon/last_stderr.py +15 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon/watch_daemon.py +6 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/experiment_runs.py +12 -0
- labnotes-0.0.116/src/labnotes/tables/runs_columns.py +11 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/uv.lock +12 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/.gitignore +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/CHANGELOG.md +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/MIGRATIONS.md +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/README.md +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/__init__.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/__main__.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/asset_url.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/check_counts.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/cli.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/compose_experiment.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/context.md +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/context_guide.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/count_groups.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/count_runs.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/create_app.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/create_experiment.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/create_note.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon/__init__.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon/control_run.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon/daemon_app.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon/daemon_client.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon/daemon_running.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon/daemon_server.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon/ensure_daemon.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon/exit_when_idle.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon/finalize_lost_runs.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon/remote_start.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon/run_daemon.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon/run_logs.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon/serve_daemon.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon/socket_path.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon/stop_runs.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon/watch_status.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/daemon_command.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/data_html.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/default_config_text.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/default_counts.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/drain_watch.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/experiment_notes.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/experiments.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/file_changes.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/format_duration.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/format_started.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/format_value.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/group_runs.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/init.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/invocation_started.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/is_non_negative_int.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/is_non_negative_number.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/is_positive_int.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/list_experiments.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/list_runs.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/load_config.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/load_experiment.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/load_run.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/log.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/log_path.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/memory_interval.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/models.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/modes.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/nests_runs.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/note_path.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/notebook_kernel.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/output_html.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/parse_run_view.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/print_rows.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/python_blocks.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/read_config.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/read_path.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/render_markdown.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/retries.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/run_command.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/run_control.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/run_output.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/run_status.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/__init__.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/describe_event.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/execute_run.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/exit_signal.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/hold_folder.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/invocation_meta.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/new_param_run_id.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/new_run_id.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/new_stamped_run_id.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/param_args.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/param_grid.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/param_run_name.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/plan_runs.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/prepare_experiment.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/read_experiment_config.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/record_memory.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/run_experiment.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/run_folder.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/run_headless.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/runs_parent.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/shell_command.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/signal_tree.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/stop_then_kill.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/wait_for_tree.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runner/write_run_json.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/runs_view_command.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/save_conflict_copy.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/save_note.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/saved_outputs.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/serve_app.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/server.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/shared_params.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/sort_href.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/sql_quote.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/static/elapsed.js +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/static/experiment.js +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/static/labnotes.css +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/static/local-time.js +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/static/new-note.js +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/static/note-edit.js +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/static/note-editor.js +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/static/row-link.js +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/static/run-cell.js +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/static/run-output.js +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/static/view-toggle.js +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/summarize_config.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/__init__.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/experiment_rows.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/experiment_run_ids.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/experiment_toml.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/experiments_ddl.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/file_prefix.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/file_text.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/iso_time.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/list_experiment_runs.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/note_text.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/open_tables.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/path_glob.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/path_pattern.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/read_blocks.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/read_experiment.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/read_file.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/read_log.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/read_memory.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/read_run.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/read_run_file.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tables/summarize_experiments.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/templates/base.html +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/templates/editor_imports.html +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/templates/experiment.html +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/templates/index.html +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/templates/note.html +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/templates/run.html +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/__init__.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/browse_app.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/browse_tui.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/check_view_response.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/config.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/dim.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/experiment_screen.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/experiments_screen.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/fill_table.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/format_cell.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/format_elapsed.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/group_cells.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/invocation_columns.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/invocation_rows.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/leave_prompt.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/log_block.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/log_blocks.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/native_rows.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/reload_on_change.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/run_app.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/run_cells.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/run_output.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/run_screen.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/run_tui.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/runs_table.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/runs_view.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/stopped_title.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/view_column.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/tui/view_process.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/utils/__init__.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/utils/format_bytes.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/utils/process_alive.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/utils/run_usage.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/utils/tree_rss.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/utils/tree_usage.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/view/__init__.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/view/answer.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/view/build.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/view/respond.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/view/serve.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/wait_for_note.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/src/labnotes/watch_rows.py +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/testing-conventions.toml +0 -0
- {labnotes-0.0.114 → labnotes-0.0.116}/tests/integration/conftest.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: labnotes
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.116
|
|
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>
|
|
@@ -15,6 +15,7 @@ Requires-Dist: jinja2>=3.1.6
|
|
|
15
15
|
Requires-Dist: jupyter-client>=8.10.0
|
|
16
16
|
Requires-Dist: markdown-it-py>=4.2.0
|
|
17
17
|
Requires-Dist: markupsafe>=3.0.4
|
|
18
|
+
Requires-Dist: posix-tools>=0.0.4
|
|
18
19
|
Requires-Dist: psutil>=7.2.2
|
|
19
20
|
Requires-Dist: rich>=14
|
|
20
21
|
Requires-Dist: starlette>=1.8.0
|
|
@@ -10,6 +10,8 @@ def describe_status(event: dict[str, object]) -> str:
|
|
|
10
10
|
memory = format_bytes(event["memory"]) or "?" # type: ignore[arg-type]
|
|
11
11
|
size = format_bytes(event["size"]) or "?" # type: ignore[arg-type]
|
|
12
12
|
said = f"{event['run']} uses {memory} of memory, {size} on disk."
|
|
13
|
+
case {"event": "ended", "last_stderr": str(line)}:
|
|
14
|
+
said = f"{describe_event(event)}: {line}"
|
|
13
15
|
case {"event": "done", "error": None}:
|
|
14
16
|
said = "Done."
|
|
15
17
|
case {"event": "done"}:
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from posix_tools import tail
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
async def last_stderr(folder: Path) -> str | None:
|
|
7
|
+
try:
|
|
8
|
+
lines = await tail(folder / "stderr.log", n=50)
|
|
9
|
+
except FileNotFoundError:
|
|
10
|
+
return None
|
|
11
|
+
for line in reversed(lines):
|
|
12
|
+
shown = line.rstrip(b"\r\n").rsplit(b"\r")[-1]
|
|
13
|
+
if text := shown.decode(errors="replace").strip():
|
|
14
|
+
return text
|
|
15
|
+
return None
|
|
@@ -5,6 +5,7 @@ from pathlib import Path
|
|
|
5
5
|
import httpx2
|
|
6
6
|
|
|
7
7
|
from labnotes.daemon.daemon_client import daemon_client
|
|
8
|
+
from labnotes.daemon.last_stderr import last_stderr
|
|
8
9
|
from labnotes.daemon.run_logs import RunLogs
|
|
9
10
|
from labnotes.utils.run_usage import run_usage
|
|
10
11
|
|
|
@@ -61,6 +62,11 @@ async def watch_daemon(root: Path, follow: bool, emit: Callable[[Event], None])
|
|
|
61
62
|
logs.add(name, run, Path(str(event["folder"])))
|
|
62
63
|
case {"event": "ended", "experiment": str(name), "run": str(run)}:
|
|
63
64
|
tail()
|
|
65
|
+
folder = logs.folders.get((name, run))
|
|
66
|
+
if event.get("exit_code") != 0 and folder is not None:
|
|
67
|
+
line = await last_stderr(folder)
|
|
68
|
+
if line is not None:
|
|
69
|
+
event = {**event, "last_stderr": line}
|
|
64
70
|
logs.drop(name, run)
|
|
65
71
|
emit(event)
|
|
66
72
|
except httpx2.TransportError:
|
|
@@ -1,14 +1,26 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
|
|
1
3
|
from labnotes.sql_quote import quote_identifier, quote_string
|
|
4
|
+
from labnotes.tables.runs_columns import runs_columns
|
|
2
5
|
|
|
3
6
|
STARTED = "strftime('%Y-%m-%d %H:%M:%S', created)"
|
|
4
7
|
DURATION = "CAST(round((julianday(ended) - julianday(created)) * 86400) AS INTEGER)"
|
|
5
8
|
|
|
6
9
|
|
|
7
10
|
def experiment_runs(experiment: str, params: list[str]) -> str:
|
|
11
|
+
taken = {*runs_columns(), "started", "duration"}
|
|
12
|
+
clashes = [key for key in params if key in taken]
|
|
13
|
+
if clashes:
|
|
14
|
+
warnings.warn(
|
|
15
|
+
f"Params {', '.join(clashes)} clash with runs columns;"
|
|
16
|
+
" the runs column wins. Read them from params instead.",
|
|
17
|
+
stacklevel=2,
|
|
18
|
+
)
|
|
8
19
|
columns = "".join(
|
|
9
20
|
f", params ->> {quote_string(f'$.{quote_identifier(key)}')}"
|
|
10
21
|
f" AS {quote_identifier(key)}"
|
|
11
22
|
for key in params
|
|
23
|
+
if key not in taken
|
|
12
24
|
)
|
|
13
25
|
return (
|
|
14
26
|
f"(SELECT *{columns}, {STARTED} AS started, {DURATION} AS duration FROM runs"
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import sqlite3
|
|
2
|
+
from functools import cache
|
|
3
|
+
|
|
4
|
+
from labnotes.tables.open_tables import RUNS
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@cache
|
|
8
|
+
def runs_columns() -> tuple[str, ...]:
|
|
9
|
+
with sqlite3.connect(":memory:") as db:
|
|
10
|
+
db.execute(RUNS)
|
|
11
|
+
return tuple(row[1] for row in db.execute("PRAGMA table_info(runs)"))
|
|
@@ -18,6 +18,7 @@ curtaincall = false
|
|
|
18
18
|
dirsql = false
|
|
19
19
|
labnotes = false
|
|
20
20
|
lamp-the-djinn = false
|
|
21
|
+
posix-tools = false
|
|
21
22
|
pyskillet = false
|
|
22
23
|
repo-name-checker = false
|
|
23
24
|
|
|
@@ -562,6 +563,7 @@ dependencies = [
|
|
|
562
563
|
{ name = "jupyter-client" },
|
|
563
564
|
{ name = "markdown-it-py" },
|
|
564
565
|
{ name = "markupsafe" },
|
|
566
|
+
{ name = "posix-tools" },
|
|
565
567
|
{ name = "psutil" },
|
|
566
568
|
{ name = "rich" },
|
|
567
569
|
{ name = "starlette" },
|
|
@@ -590,6 +592,7 @@ requires-dist = [
|
|
|
590
592
|
{ name = "jupyter-client", specifier = ">=8.10.0" },
|
|
591
593
|
{ name = "markdown-it-py", specifier = ">=4.2.0" },
|
|
592
594
|
{ name = "markupsafe", specifier = ">=3.0.4" },
|
|
595
|
+
{ name = "posix-tools", specifier = ">=0.0.4" },
|
|
593
596
|
{ name = "psutil", specifier = ">=7.2.2" },
|
|
594
597
|
{ name = "rich", specifier = ">=14" },
|
|
595
598
|
{ name = "starlette", specifier = ">=1.8.0" },
|
|
@@ -1028,6 +1031,15 @@ wheels = [
|
|
|
1028
1031
|
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
|
1029
1032
|
]
|
|
1030
1033
|
|
|
1034
|
+
[[package]]
|
|
1035
|
+
name = "posix-tools"
|
|
1036
|
+
version = "0.0.4"
|
|
1037
|
+
source = { registry = "https://pypi.org/simple" }
|
|
1038
|
+
sdist = { url = "https://files.pythonhosted.org/packages/fd/dd/94ade35bdcac09894b189e3d5b26051ff9836736fc1a6e4b924915948689/posix_tools-0.0.4.tar.gz", hash = "sha256:9f0fc2ff886a21c0aae7e93c77e07d84d079d0d7332889c9bde260ed39f5b9c2", size = 29985, upload-time = "2026-10-25T20:09:10.72Z" }
|
|
1039
|
+
wheels = [
|
|
1040
|
+
{ url = "https://files.pythonhosted.org/packages/58/42/6db531e3bc3ea59909bbacc5f0e814f6b1ce7e6feaf0d8cc124da9e8b222/posix_tools-0.0.4-py3-none-any.whl", hash = "sha256:159519be82a630dbb60ea68b8cd61da9d1af3f134652c39d628b117fb2667d2d", size = 9014, upload-time = "2026-10-25T20:09:09.508Z" },
|
|
1041
|
+
]
|
|
1042
|
+
|
|
1031
1043
|
[[package]]
|
|
1032
1044
|
name = "prompt-toolkit"
|
|
1033
1045
|
version = "3.0.53"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|