labnotes 0.0.115__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.
Files changed (200) hide show
  1. {labnotes-0.0.115 → labnotes-0.0.116}/PKG-INFO +2 -1
  2. {labnotes-0.0.115 → labnotes-0.0.116}/pyproject.toml +1 -0
  3. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon/describe_status.py +2 -0
  4. labnotes-0.0.116/src/labnotes/daemon/last_stderr.py +15 -0
  5. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon/watch_daemon.py +6 -0
  6. {labnotes-0.0.115 → labnotes-0.0.116}/uv.lock +12 -0
  7. {labnotes-0.0.115 → labnotes-0.0.116}/.gitignore +0 -0
  8. {labnotes-0.0.115 → labnotes-0.0.116}/CHANGELOG.md +0 -0
  9. {labnotes-0.0.115 → labnotes-0.0.116}/MIGRATIONS.md +0 -0
  10. {labnotes-0.0.115 → labnotes-0.0.116}/README.md +0 -0
  11. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/__init__.py +0 -0
  12. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/__main__.py +0 -0
  13. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/asset_url.py +0 -0
  14. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/check_counts.py +0 -0
  15. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/cli.py +0 -0
  16. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/compose_experiment.py +0 -0
  17. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/context.md +0 -0
  18. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/context_guide.py +0 -0
  19. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/count_groups.py +0 -0
  20. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/count_runs.py +0 -0
  21. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/create_app.py +0 -0
  22. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/create_experiment.py +0 -0
  23. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/create_note.py +0 -0
  24. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon/__init__.py +0 -0
  25. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon/control_run.py +0 -0
  26. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon/daemon_app.py +0 -0
  27. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon/daemon_client.py +0 -0
  28. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon/daemon_running.py +0 -0
  29. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon/daemon_server.py +0 -0
  30. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon/ensure_daemon.py +0 -0
  31. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon/exit_when_idle.py +0 -0
  32. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon/finalize_lost_runs.py +0 -0
  33. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon/remote_start.py +0 -0
  34. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon/run_daemon.py +0 -0
  35. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon/run_logs.py +0 -0
  36. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon/serve_daemon.py +0 -0
  37. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon/socket_path.py +0 -0
  38. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon/stop_runs.py +0 -0
  39. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon/watch_status.py +0 -0
  40. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/daemon_command.py +0 -0
  41. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/data_html.py +0 -0
  42. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/default_config_text.py +0 -0
  43. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/default_counts.py +0 -0
  44. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/drain_watch.py +0 -0
  45. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/experiment_notes.py +0 -0
  46. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/experiment_runs.py +0 -0
  47. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/experiments.py +0 -0
  48. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/file_changes.py +0 -0
  49. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/format_duration.py +0 -0
  50. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/format_started.py +0 -0
  51. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/format_value.py +0 -0
  52. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/group_runs.py +0 -0
  53. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/init.py +0 -0
  54. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/invocation_started.py +0 -0
  55. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/is_non_negative_int.py +0 -0
  56. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/is_non_negative_number.py +0 -0
  57. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/is_positive_int.py +0 -0
  58. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/list_experiments.py +0 -0
  59. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/list_runs.py +0 -0
  60. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/load_config.py +0 -0
  61. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/load_experiment.py +0 -0
  62. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/load_run.py +0 -0
  63. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/log.py +0 -0
  64. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/log_path.py +0 -0
  65. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/memory_interval.py +0 -0
  66. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/models.py +0 -0
  67. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/modes.py +0 -0
  68. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/nests_runs.py +0 -0
  69. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/note_path.py +0 -0
  70. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/notebook_kernel.py +0 -0
  71. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/output_html.py +0 -0
  72. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/parse_run_view.py +0 -0
  73. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/print_rows.py +0 -0
  74. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/python_blocks.py +0 -0
  75. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/read_config.py +0 -0
  76. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/read_path.py +0 -0
  77. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/render_markdown.py +0 -0
  78. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/retries.py +0 -0
  79. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/run_command.py +0 -0
  80. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/run_control.py +0 -0
  81. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/run_output.py +0 -0
  82. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/run_status.py +0 -0
  83. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/__init__.py +0 -0
  84. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/describe_event.py +0 -0
  85. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/execute_run.py +0 -0
  86. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/exit_signal.py +0 -0
  87. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/hold_folder.py +0 -0
  88. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/invocation_meta.py +0 -0
  89. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/new_param_run_id.py +0 -0
  90. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/new_run_id.py +0 -0
  91. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/new_stamped_run_id.py +0 -0
  92. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/param_args.py +0 -0
  93. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/param_grid.py +0 -0
  94. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/param_run_name.py +0 -0
  95. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/plan_runs.py +0 -0
  96. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/prepare_experiment.py +0 -0
  97. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/read_experiment_config.py +0 -0
  98. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/record_memory.py +0 -0
  99. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/run_experiment.py +0 -0
  100. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/run_folder.py +0 -0
  101. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/run_headless.py +0 -0
  102. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/runs_parent.py +0 -0
  103. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/shell_command.py +0 -0
  104. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/signal_tree.py +0 -0
  105. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/stop_then_kill.py +0 -0
  106. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/wait_for_tree.py +0 -0
  107. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runner/write_run_json.py +0 -0
  108. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/runs_view_command.py +0 -0
  109. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/save_conflict_copy.py +0 -0
  110. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/save_note.py +0 -0
  111. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/saved_outputs.py +0 -0
  112. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/serve_app.py +0 -0
  113. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/server.py +0 -0
  114. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/shared_params.py +0 -0
  115. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/sort_href.py +0 -0
  116. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/sql_quote.py +0 -0
  117. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/static/elapsed.js +0 -0
  118. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/static/experiment.js +0 -0
  119. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/static/labnotes.css +0 -0
  120. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/static/local-time.js +0 -0
  121. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/static/new-note.js +0 -0
  122. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/static/note-edit.js +0 -0
  123. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/static/note-editor.js +0 -0
  124. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/static/row-link.js +0 -0
  125. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/static/run-cell.js +0 -0
  126. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/static/run-output.js +0 -0
  127. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/static/view-toggle.js +0 -0
  128. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/summarize_config.py +0 -0
  129. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/__init__.py +0 -0
  130. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/experiment_rows.py +0 -0
  131. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/experiment_run_ids.py +0 -0
  132. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/experiment_toml.py +0 -0
  133. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/experiments_ddl.py +0 -0
  134. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/file_prefix.py +0 -0
  135. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/file_text.py +0 -0
  136. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/iso_time.py +0 -0
  137. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/list_experiment_runs.py +0 -0
  138. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/note_text.py +0 -0
  139. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/open_tables.py +0 -0
  140. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/path_glob.py +0 -0
  141. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/path_pattern.py +0 -0
  142. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/read_blocks.py +0 -0
  143. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/read_experiment.py +0 -0
  144. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/read_file.py +0 -0
  145. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/read_log.py +0 -0
  146. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/read_memory.py +0 -0
  147. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/read_run.py +0 -0
  148. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/read_run_file.py +0 -0
  149. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/runs_columns.py +0 -0
  150. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tables/summarize_experiments.py +0 -0
  151. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/templates/base.html +0 -0
  152. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/templates/editor_imports.html +0 -0
  153. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/templates/experiment.html +0 -0
  154. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/templates/index.html +0 -0
  155. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/templates/note.html +0 -0
  156. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/templates/run.html +0 -0
  157. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/__init__.py +0 -0
  158. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/browse_app.py +0 -0
  159. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/browse_tui.py +0 -0
  160. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/check_view_response.py +0 -0
  161. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/config.py +0 -0
  162. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/dim.py +0 -0
  163. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/experiment_screen.py +0 -0
  164. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/experiments_screen.py +0 -0
  165. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/fill_table.py +0 -0
  166. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/format_cell.py +0 -0
  167. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/format_elapsed.py +0 -0
  168. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/group_cells.py +0 -0
  169. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/invocation_columns.py +0 -0
  170. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/invocation_rows.py +0 -0
  171. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/leave_prompt.py +0 -0
  172. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/log_block.py +0 -0
  173. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/log_blocks.py +0 -0
  174. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/native_rows.py +0 -0
  175. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/reload_on_change.py +0 -0
  176. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/run_app.py +0 -0
  177. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/run_cells.py +0 -0
  178. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/run_output.py +0 -0
  179. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/run_screen.py +0 -0
  180. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/run_tui.py +0 -0
  181. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/runs_table.py +0 -0
  182. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/runs_view.py +0 -0
  183. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/stopped_title.py +0 -0
  184. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/view_column.py +0 -0
  185. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/tui/view_process.py +0 -0
  186. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/utils/__init__.py +0 -0
  187. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/utils/format_bytes.py +0 -0
  188. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/utils/process_alive.py +0 -0
  189. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/utils/run_usage.py +0 -0
  190. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/utils/tree_rss.py +0 -0
  191. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/utils/tree_usage.py +0 -0
  192. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/view/__init__.py +0 -0
  193. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/view/answer.py +0 -0
  194. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/view/build.py +0 -0
  195. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/view/respond.py +0 -0
  196. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/view/serve.py +0 -0
  197. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/wait_for_note.py +0 -0
  198. {labnotes-0.0.115 → labnotes-0.0.116}/src/labnotes/watch_rows.py +0 -0
  199. {labnotes-0.0.115 → labnotes-0.0.116}/testing-conventions.toml +0 -0
  200. {labnotes-0.0.115 → 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.115
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
@@ -20,6 +20,7 @@ dependencies = [
20
20
  "jupyter-client>=8.10.0",
21
21
  "markdown-it-py>=4.2.0",
22
22
  "markupsafe>=3.0.4",
23
+ "posix-tools>=0.0.4",
23
24
  "psutil>=7.2.2",
24
25
  "rich>=14",
25
26
  "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:
@@ -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