labnotes 0.2.17__tar.gz → 0.2.18__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.17 → labnotes-0.2.18}/PKG-INFO +1 -1
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/experiments.py +50 -15
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/leave_prompt.py +18 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/run_app.py +129 -8
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/run_tui.py +9 -2
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/runs_browser.py +14 -20
- {labnotes-0.2.17 → labnotes-0.2.18}/.gitignore +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/CHANGELOG.md +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/MIGRATIONS.md +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/README.md +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/conftest.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/pyproject.toml +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/__init__.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/__main__.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/asset_url.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/check_counts.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/cli.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/command_line_group.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/compose_experiment.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/config_migration.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/context.md +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/context_guide.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/copy_experiment.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/count_groups.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/count_runs.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/create_app.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/create_experiment.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/create_note.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/daemon/__init__.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/daemon/client.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/daemon/command.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/daemon/ensure.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/daemon/marker.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/daemon/server.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/daemon/socket_path.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/daemon_command.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/data_html.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/default_config_text.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/default_counts.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/drain_watch.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/experiment_definition.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/experiment_notes.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/experiment_runs.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/file_changes.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/format_duration.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/format_started.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/format_value.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/get_state.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/grid_cell.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/group_runs.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/init.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/invocation_started.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/is_non_negative_int.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/is_non_negative_number.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/is_positive_int.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/latest_log.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/list_experiments.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/list_runs.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/load_config.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/load_experiment.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/load_run.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/log.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/log_path.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/memory_interval.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/models.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/nests_runs.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/note_path.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/notebook_kernel.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/output_html.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/param_names.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/parse_param_value.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/parse_params.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/parse_run_view.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/parse_subset.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/pivot_runs.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/print_rows.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/python_blocks.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/read_config.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/read_path.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/render_markdown.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/retries.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/run_columns.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/run_output.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/__init__.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/cgroup_memory.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/check_args.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/check_hook_placeholders.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/check_subset.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/claim_run.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/command_flags.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/container_cgroup.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/container_memory.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/continue_run.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/describe_event.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/docker_output.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/execute_run.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/exit_signal.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/fill_dirs.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/fill_experiment_env.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/finalize_lost_runs.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/first_invocation.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/flag_name.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/group_args.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/hold_experiment.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/in_subset.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/invocation_hook.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/invocation_meta.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/new_run_id.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/new_stamped_run_id.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/override_flags.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/param_args.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/param_grid.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/placeholders.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/plan_runs.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/prepare_experiment.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/project_snapshot.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/read_experiment_config.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/record_memory.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/run_experiment.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/run_folder.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/run_git.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/run_headless.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/run_locked.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/run_state.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/runs_parent.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/shell_command.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/signal_tree.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/start_experiment.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/stop_then_kill.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/untracked_diff.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/wait_for_tree.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runner/write_run_json.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/runs_view_command.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/save_conflict_copy.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/save_note.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/saved_outputs.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/serve_app.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/server.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/set_state.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/shared_params.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/sort_href.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/sql_quote.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/state_path.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/static/elapsed.js +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/static/experiment.js +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/static/labnotes.css +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/static/local-time.js +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/static/new-note.js +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/static/note-edit.js +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/static/note-editor.js +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/static/row-link.js +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/static/run-cell.js +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/static/run-output.js +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/static/view-toggle.js +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/summarize_config.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/__init__.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/experiment_rows.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/experiment_run_ids.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/experiment_toml.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/experiments_ddl.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/file_prefix.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/file_text.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/iso_time.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/list_experiment_runs.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/list_resumable_runs.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/note_text.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/open_tables.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/path_glob.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/path_pattern.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/read_blocks.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/read_experiment.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/read_file.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/read_log.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/read_memory.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/read_run.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/read_run_file.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/runs_columns.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tables/summarize_experiments.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/templates/base.html +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/templates/editor_imports.html +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/templates/experiment.html +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/templates/index.html +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/templates/note.html +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/templates/run.html +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/__init__.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/browse_app.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/browse_tui.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/check_view_response.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/config.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/dim.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/experiment_screen.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/experiments_screen.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/fill_table.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/format_cell.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/format_elapsed.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/guard_view.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/load_view.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/log_block.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/log_blocks.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/native_rows.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/reload_on_change.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/run_cells.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/run_output.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/run_panel.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/runs_table.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/runs_view.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/stopped_title.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/table_columns.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/table_rows.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/view_column.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/view_pane.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/view_process.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/tui/view_switcher.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/utils/__init__.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/utils/format_bytes.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/utils/process_alive.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/utils/run_usage.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/utils/tree_rss.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/utils/tree_usage.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/view/__init__.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/view/answer.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/view/build.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/view/changed.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/view/experiment.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/view/respond.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/view/serve.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/view_specs.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/wait_for_note.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/src/labnotes/watch_rows.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/testing-conventions.toml +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/tests/conftest.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/tests/e2e/conftest.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/tests/integration/conftest.py +0 -0
- {labnotes-0.2.17 → labnotes-0.2.18}/uv.lock +0 -0
|
@@ -7,7 +7,9 @@ import click
|
|
|
7
7
|
from labnotes.command_line_group import COMMAND_LINE
|
|
8
8
|
from labnotes.create_experiment import create_experiment
|
|
9
9
|
from labnotes.daemon.command import command as daemon_command
|
|
10
|
+
from labnotes.daemon.ensure import ensure_daemon
|
|
10
11
|
from labnotes.runner.start_experiment import start_experiment
|
|
12
|
+
from labnotes.runner.run_state import RunState
|
|
11
13
|
from labnotes.utils.format_bytes import format_bytes
|
|
12
14
|
from labnotes.load_config import load_config
|
|
13
15
|
from labnotes.parse_params import parse_params
|
|
@@ -169,24 +171,57 @@ def experiments(
|
|
|
169
171
|
only = parse_subset(ctx.args)
|
|
170
172
|
except ValueError as error:
|
|
171
173
|
raise click.UsageError(str(error)) from error
|
|
172
|
-
start = start_experiment(
|
|
173
|
-
config,
|
|
174
|
-
name,
|
|
175
|
-
experiment_config,
|
|
176
|
-
concurrency,
|
|
177
|
-
timeout,
|
|
178
|
-
only,
|
|
179
|
-
passthrough or None,
|
|
180
|
-
setup,
|
|
181
|
-
teardown,
|
|
182
|
-
ctx.meta.get(COMMAND_LINE),
|
|
183
|
-
run_id,
|
|
184
|
-
)
|
|
185
174
|
try:
|
|
186
175
|
if not headless and sys.stdout.isatty() and sys.stderr.isatty():
|
|
187
|
-
|
|
176
|
+
asyncio.run(ensure_daemon(config, name))
|
|
177
|
+
reply = daemon_command(
|
|
178
|
+
config,
|
|
179
|
+
name,
|
|
180
|
+
{
|
|
181
|
+
"command": "restart" if run_id else "start",
|
|
182
|
+
"options": {
|
|
183
|
+
"experiment_config": str(experiment_config)
|
|
184
|
+
if experiment_config
|
|
185
|
+
else None,
|
|
186
|
+
"concurrency": concurrency,
|
|
187
|
+
"timeout": timeout,
|
|
188
|
+
"only": only,
|
|
189
|
+
"args": passthrough or None,
|
|
190
|
+
"setup": setup,
|
|
191
|
+
"teardown": teardown,
|
|
192
|
+
"command_line": ctx.meta.get(COMMAND_LINE),
|
|
193
|
+
"run_id": run_id,
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
)
|
|
197
|
+
if not reply.get("ok"):
|
|
198
|
+
raise ValueError(
|
|
199
|
+
str(reply.get("error", "Daemon rejected start"))
|
|
200
|
+
)
|
|
201
|
+
run_tui(
|
|
202
|
+
None,
|
|
203
|
+
name,
|
|
204
|
+
config,
|
|
205
|
+
experiment_config,
|
|
206
|
+
daemon_journal=RunState(Path(str(reply["journal"]))),
|
|
207
|
+
)
|
|
208
|
+
return
|
|
188
209
|
else:
|
|
189
|
-
results = run_headless(
|
|
210
|
+
results = run_headless(
|
|
211
|
+
start_experiment(
|
|
212
|
+
config,
|
|
213
|
+
name,
|
|
214
|
+
experiment_config,
|
|
215
|
+
concurrency,
|
|
216
|
+
timeout,
|
|
217
|
+
only,
|
|
218
|
+
passthrough or None,
|
|
219
|
+
setup,
|
|
220
|
+
teardown,
|
|
221
|
+
ctx.meta.get(COMMAND_LINE),
|
|
222
|
+
run_id,
|
|
223
|
+
)
|
|
224
|
+
)
|
|
190
225
|
except ValueError as error:
|
|
191
226
|
raise click.ClickException(str(error)) from error
|
|
192
227
|
superseded = {r["retry_of"] for r in results if "retry_of" in r}
|
|
@@ -25,3 +25,21 @@ class LeavePrompt(ModalScreen[str | None]):
|
|
|
25
25
|
"Stop them (enter or s) / cancel (esc).",
|
|
26
26
|
id="prompt",
|
|
27
27
|
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class DetachedLeavePrompt(LeavePrompt):
|
|
31
|
+
"""Choose explicitly whether a detached daemon should keep its cells."""
|
|
32
|
+
|
|
33
|
+
BINDINGS = [
|
|
34
|
+
Binding("s", "dismiss('stop')", "Stop runs"),
|
|
35
|
+
Binding("enter,l", "dismiss('leave')", "Leave running"),
|
|
36
|
+
Binding("escape", "dismiss", "Cancel"),
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
def compose(self) -> ComposeResult:
|
|
40
|
+
runs = "run" if self.count == 1 else "runs"
|
|
41
|
+
yield Static(
|
|
42
|
+
f"{self.count} {runs} still going. "
|
|
43
|
+
"Stop them (s) / leave running (enter or l) / cancel (esc).",
|
|
44
|
+
id="prompt",
|
|
45
|
+
)
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import json
|
|
1
3
|
import signal
|
|
4
|
+
import socket
|
|
2
5
|
import time
|
|
3
6
|
import tomllib
|
|
4
7
|
from collections.abc import Mapping, Sequence
|
|
@@ -16,18 +19,21 @@ from textual.widget import Widget
|
|
|
16
19
|
from textual.widgets import ContentSwitcher, DataTable, Footer, Header, Input, Static
|
|
17
20
|
|
|
18
21
|
from labnotes.compose_experiment import compose_experiment
|
|
22
|
+
from labnotes.daemon.command import command as daemon_command
|
|
23
|
+
from labnotes.daemon.client import daemon_socket
|
|
19
24
|
from labnotes.load_experiment import load_experiment
|
|
20
25
|
from labnotes.models import Controls, LabnotesConfig, Start
|
|
21
26
|
from labnotes.retries import RETRY_EXIT_CODE
|
|
22
27
|
from labnotes.runner.describe_event import describe_event
|
|
23
28
|
from labnotes.runner.param_args import param_args
|
|
24
29
|
from labnotes.runner.start_experiment import ExperimentStart
|
|
30
|
+
from labnotes.runner.run_state import RunState
|
|
25
31
|
from labnotes.runner.stop_then_kill import GRACE_SECONDS, stop_then_kill
|
|
26
32
|
from labnotes.tables.open_tables import open_tables
|
|
27
33
|
from labnotes.tui.config import RUN_COLUMNS
|
|
28
34
|
from labnotes.tui.dim import dim
|
|
29
35
|
from labnotes.tui.format_elapsed import format_elapsed
|
|
30
|
-
from labnotes.tui.leave_prompt import LeavePrompt
|
|
36
|
+
from labnotes.tui.leave_prompt import DetachedLeavePrompt, LeavePrompt
|
|
31
37
|
from labnotes.tui.log_blocks import LogBlocks
|
|
32
38
|
from labnotes.tui.native_rows import native_rows
|
|
33
39
|
from labnotes.tui.reload_on_change import reload_on_change
|
|
@@ -55,6 +61,7 @@ class RunLiveView(Widget):
|
|
|
55
61
|
"""
|
|
56
62
|
BINDINGS = [
|
|
57
63
|
Binding("x", "kill_run", "Stop run"),
|
|
64
|
+
Binding("r", "restart_run", "Restart"),
|
|
58
65
|
Binding("slash", "filter", "Filter", key_display="/"),
|
|
59
66
|
Binding("escape", "leave", "Back"),
|
|
60
67
|
Binding("plus,equals_sign", "concurrency(1)", "More at once", key_display="+"),
|
|
@@ -294,6 +301,10 @@ class RunLiveView(Widget):
|
|
|
294
301
|
def action_concurrency(self, change: int) -> None:
|
|
295
302
|
self.controls.set_concurrency(self.concurrency + change)
|
|
296
303
|
|
|
304
|
+
def action_restart_run(self) -> None:
|
|
305
|
+
if (run := self.cursor_run()) is not None and isinstance(self.app, RunApp):
|
|
306
|
+
self.app.restart_run(run)
|
|
307
|
+
|
|
297
308
|
def action_filter(self) -> None:
|
|
298
309
|
field = self.query_one(Input)
|
|
299
310
|
field.display = True
|
|
@@ -354,11 +365,12 @@ class RunApp(ViewSwitcher, App[None]):
|
|
|
354
365
|
|
|
355
366
|
def __init__(
|
|
356
367
|
self,
|
|
357
|
-
start: Start,
|
|
368
|
+
start: Start | None,
|
|
358
369
|
title: str,
|
|
359
370
|
columns: Sequence[str],
|
|
360
371
|
config: LabnotesConfig | None = None,
|
|
361
372
|
experiment_config: Path | None = None,
|
|
373
|
+
daemon_journal: RunState | None = None,
|
|
362
374
|
) -> None:
|
|
363
375
|
super().__init__()
|
|
364
376
|
self.start = start
|
|
@@ -377,8 +389,12 @@ class RunApp(ViewSwitcher, App[None]):
|
|
|
377
389
|
self.shown: Experiment | None = None
|
|
378
390
|
self.left: dict[str, Widget] = {}
|
|
379
391
|
self.controls = self.body.controls
|
|
380
|
-
self.
|
|
392
|
+
self.daemon_journal = daemon_journal
|
|
393
|
+
self.run_state = daemon_journal or (
|
|
394
|
+
start.run_state if isinstance(start, ExperimentStart) else None
|
|
395
|
+
)
|
|
381
396
|
self.watching_state = False
|
|
397
|
+
self.attached: socket.socket | None = None
|
|
382
398
|
|
|
383
399
|
def compose(self) -> ComposeResult:
|
|
384
400
|
yield Header()
|
|
@@ -412,7 +428,93 @@ class RunApp(ViewSwitcher, App[None]):
|
|
|
412
428
|
exit_on_error=False,
|
|
413
429
|
)
|
|
414
430
|
self.run_worker(self.watch_files(tables), exit_on_error=False)
|
|
415
|
-
self.
|
|
431
|
+
if self.daemon_journal is not None:
|
|
432
|
+
journal = self.daemon_journal
|
|
433
|
+
try:
|
|
434
|
+
self.attach_daemon()
|
|
435
|
+
except (OSError, ValueError) as error:
|
|
436
|
+
self.error = error
|
|
437
|
+
self.exit()
|
|
438
|
+
return
|
|
439
|
+
self.listen(
|
|
440
|
+
Controls(
|
|
441
|
+
lambda: self.queue_command({"command": "stop_all"}),
|
|
442
|
+
lambda count: self.queue_command(
|
|
443
|
+
{
|
|
444
|
+
"command": "set_concurrency",
|
|
445
|
+
"count": count,
|
|
446
|
+
"journal": str(journal.path),
|
|
447
|
+
}
|
|
448
|
+
),
|
|
449
|
+
lambda run: self.queue_command({"command": "stop_one", "run": run}),
|
|
450
|
+
lambda: None,
|
|
451
|
+
)
|
|
452
|
+
)
|
|
453
|
+
self.set_interval(0.25, self.refresh_state)
|
|
454
|
+
self.refresh_state()
|
|
455
|
+
else:
|
|
456
|
+
self.run_worker(self.drive())
|
|
457
|
+
|
|
458
|
+
def attach_daemon(self) -> None:
|
|
459
|
+
assert self.config is not None
|
|
460
|
+
path = daemon_socket(self.config, self.experiment_name)
|
|
461
|
+
if path is None:
|
|
462
|
+
raise ValueError(f"No daemon is running for {self.experiment_name}.")
|
|
463
|
+
client = socket.socket(socket.AF_UNIX)
|
|
464
|
+
try:
|
|
465
|
+
client.settimeout(10)
|
|
466
|
+
client.connect(str(path))
|
|
467
|
+
client.sendall(b'{"command":"attach"}\n')
|
|
468
|
+
with client.makefile("r") as replies:
|
|
469
|
+
reply = json.loads(replies.readline())
|
|
470
|
+
if not reply.get("ok"):
|
|
471
|
+
raise ValueError(str(reply.get("error", "Daemon rejected attach")))
|
|
472
|
+
except Exception:
|
|
473
|
+
client.close()
|
|
474
|
+
raise
|
|
475
|
+
self.attached = client
|
|
476
|
+
|
|
477
|
+
def on_unmount(self) -> None:
|
|
478
|
+
if self.attached is not None:
|
|
479
|
+
self.attached.close()
|
|
480
|
+
|
|
481
|
+
def queue_command(self, message: dict[str, object]) -> None:
|
|
482
|
+
self.run_worker(self.send_command(message), exit_on_error=False)
|
|
483
|
+
|
|
484
|
+
async def send_command(self, message: dict[str, object]) -> None:
|
|
485
|
+
assert self.config is not None
|
|
486
|
+
try:
|
|
487
|
+
reply = await asyncio.to_thread(
|
|
488
|
+
daemon_command, self.config, self.experiment_name, message
|
|
489
|
+
)
|
|
490
|
+
if not reply.get("ok"):
|
|
491
|
+
raise ValueError(str(reply.get("error", "Daemon rejected command")))
|
|
492
|
+
except ValueError as error:
|
|
493
|
+
if self.body_ready:
|
|
494
|
+
self.body.show(str(error))
|
|
495
|
+
|
|
496
|
+
def restart_run(self, run: str) -> None:
|
|
497
|
+
if self.daemon_journal is None:
|
|
498
|
+
return
|
|
499
|
+
if run not in self.body.failed:
|
|
500
|
+
self.body.show(f"{run} has not failed.")
|
|
501
|
+
return
|
|
502
|
+
self.run_worker(self.restart_daemon_run(run), exit_on_error=False)
|
|
503
|
+
|
|
504
|
+
async def restart_daemon_run(self, run: str) -> None:
|
|
505
|
+
assert self.config is not None
|
|
506
|
+
try:
|
|
507
|
+
reply = await asyncio.to_thread(
|
|
508
|
+
daemon_command,
|
|
509
|
+
self.config,
|
|
510
|
+
self.experiment_name,
|
|
511
|
+
{"command": "restart", "options": {"run_id": run}},
|
|
512
|
+
)
|
|
513
|
+
if not reply.get("ok"):
|
|
514
|
+
raise ValueError(str(reply.get("error", "Daemon rejected restart")))
|
|
515
|
+
self.body.show(f"Restarted {run}.")
|
|
516
|
+
except ValueError as error:
|
|
517
|
+
self.body.show(f"Could not restart {run}: {error}")
|
|
416
518
|
|
|
417
519
|
def configured_views(self) -> dict[str, str]:
|
|
418
520
|
if self.config is None:
|
|
@@ -453,6 +555,7 @@ class RunApp(ViewSwitcher, App[None]):
|
|
|
453
555
|
self.deliver(self.shown, frozenset({str(row["path"])}))
|
|
454
556
|
|
|
455
557
|
async def drive(self) -> None:
|
|
558
|
+
assert self.start is not None
|
|
456
559
|
try:
|
|
457
560
|
self.results = await self.start(self.show_event, self.listen)
|
|
458
561
|
except Exception as error:
|
|
@@ -463,8 +566,9 @@ class RunApp(ViewSwitcher, App[None]):
|
|
|
463
566
|
self.controls = controls
|
|
464
567
|
if self.body_ready:
|
|
465
568
|
self.body.controls = controls
|
|
466
|
-
|
|
467
|
-
|
|
569
|
+
if self.daemon_journal is None:
|
|
570
|
+
stop_then_kill(self.stop_runs, signal.SIGTERM)
|
|
571
|
+
stop_then_kill(self.stop_runs, signal.SIGHUP)
|
|
468
572
|
|
|
469
573
|
def show_event(self, event: dict[str, object]) -> None:
|
|
470
574
|
if self.run_state is None:
|
|
@@ -488,6 +592,14 @@ class RunApp(ViewSwitcher, App[None]):
|
|
|
488
592
|
self.controls.interrupt()
|
|
489
593
|
|
|
490
594
|
def action_interrupt(self) -> None:
|
|
595
|
+
if self.daemon_journal is not None:
|
|
596
|
+
if self.body_ready and self.body.started:
|
|
597
|
+
self.push_screen(
|
|
598
|
+
DetachedLeavePrompt(len(self.body.started)), self.answer
|
|
599
|
+
)
|
|
600
|
+
else:
|
|
601
|
+
self.exit()
|
|
602
|
+
return
|
|
491
603
|
if self.body_ready and self.body.started:
|
|
492
604
|
self.push_screen(LeavePrompt(len(self.body.started)), self.answer)
|
|
493
605
|
elif self.body_ready and self.body.idle:
|
|
@@ -500,8 +612,17 @@ class RunApp(ViewSwitcher, App[None]):
|
|
|
500
612
|
|
|
501
613
|
def answer(self, choice: str | None) -> None:
|
|
502
614
|
if choice == "stop":
|
|
503
|
-
self.
|
|
504
|
-
|
|
615
|
+
if self.daemon_journal is None:
|
|
616
|
+
self.controls.interrupt()
|
|
617
|
+
self.set_timer(GRACE_SECONDS, self.controls.interrupt)
|
|
618
|
+
else:
|
|
619
|
+
self.run_worker(self.stop_daemon_and_exit(), exit_on_error=False)
|
|
620
|
+
elif choice == "leave" and self.daemon_journal is not None:
|
|
621
|
+
self.exit()
|
|
622
|
+
|
|
623
|
+
async def stop_daemon_and_exit(self) -> None:
|
|
624
|
+
await self.send_command({"command": "stop_all"})
|
|
625
|
+
self.exit()
|
|
505
626
|
|
|
506
627
|
def action_leave(self) -> None:
|
|
507
628
|
if self.query_one(ContentSwitcher).current != "view-1":
|
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
|
|
3
3
|
from labnotes.models import LabnotesConfig, Start
|
|
4
|
+
from labnotes.runner.run_state import RunState
|
|
4
5
|
from labnotes.tui.config import RUN_COLUMNS
|
|
5
6
|
from labnotes.tui.run_app import RunApp
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
def run_tui(
|
|
9
|
-
start: Start,
|
|
10
|
+
start: Start | None,
|
|
10
11
|
title: str,
|
|
11
12
|
config: LabnotesConfig | None = None,
|
|
12
13
|
experiment_config: Path | None = None,
|
|
14
|
+
daemon_journal: RunState | None = None,
|
|
13
15
|
) -> list[dict[str, object]]:
|
|
14
16
|
app = RunApp(
|
|
15
|
-
start,
|
|
17
|
+
start,
|
|
18
|
+
title,
|
|
19
|
+
RUN_COLUMNS,
|
|
20
|
+
config=config,
|
|
21
|
+
experiment_config=experiment_config,
|
|
22
|
+
daemon_journal=daemon_journal,
|
|
16
23
|
)
|
|
17
24
|
app.run()
|
|
18
25
|
if app.error is not None:
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import os
|
|
3
|
-
import sys
|
|
4
3
|
from collections.abc import Mapping
|
|
5
4
|
from pathlib import Path
|
|
6
5
|
from typing import Any, cast
|
|
@@ -11,6 +10,8 @@ from textual.widget import Widget
|
|
|
11
10
|
from textual.widgets import DataTable, Static
|
|
12
11
|
|
|
13
12
|
from labnotes.runs_view_command import runs_view_command
|
|
13
|
+
from labnotes.daemon.command import command as daemon_command
|
|
14
|
+
from labnotes.daemon.ensure import ensure_daemon
|
|
14
15
|
from labnotes.models import LabnotesConfig
|
|
15
16
|
from labnotes.runner.claim_run import claim_run
|
|
16
17
|
from labnotes.tui.fill_table import fill_table
|
|
@@ -144,28 +145,21 @@ class RunsBrowser(Widget):
|
|
|
144
145
|
|
|
145
146
|
async def restart(self, run_id: str) -> None:
|
|
146
147
|
config = cast(LabnotesConfig, getattr(self.app, "config"))
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
"
|
|
156
|
-
|
|
157
|
-
run_id,
|
|
158
|
-
stdout=asyncio.subprocess.PIPE,
|
|
159
|
-
stderr=asyncio.subprocess.PIPE,
|
|
160
|
-
)
|
|
161
|
-
stdout, stderr = await process.communicate()
|
|
162
|
-
if process.returncode == 0:
|
|
148
|
+
try:
|
|
149
|
+
await ensure_daemon(config, self.experiment.name)
|
|
150
|
+
reply = await asyncio.to_thread(
|
|
151
|
+
daemon_command,
|
|
152
|
+
config,
|
|
153
|
+
self.experiment.name,
|
|
154
|
+
{"command": "restart", "options": {"run_id": run_id}},
|
|
155
|
+
)
|
|
156
|
+
if not reply.get("ok"):
|
|
157
|
+
raise ValueError(str(reply.get("error", "Daemon rejected restart")))
|
|
163
158
|
self.restart_status = (
|
|
164
159
|
f"Restarted {run_id}. Select the run to view its output."
|
|
165
160
|
)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
self.restart_status = f"Could not restart {run_id}: {detail}"
|
|
161
|
+
except ValueError as error:
|
|
162
|
+
self.restart_status = f"Could not restart {run_id}: {error}"
|
|
169
163
|
self.show_status()
|
|
170
164
|
|
|
171
165
|
async def action_open_row(self) -> None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|