labnotes 0.2.0__tar.gz → 0.2.2__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.0 → labnotes-0.2.2}/PKG-INFO +1 -1
- labnotes-0.2.2/src/labnotes/runner/check_args.py +19 -0
- labnotes-0.2.2/src/labnotes/runner/command_flags.py +35 -0
- labnotes-0.2.2/src/labnotes/runner/group_args.py +33 -0
- labnotes-0.2.2/src/labnotes/runner/override_flags.py +21 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/project_snapshot.py +11 -9
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/shell_command.py +3 -1
- labnotes-0.2.0/src/labnotes/runner/check_args.py +0 -15
- {labnotes-0.2.0 → labnotes-0.2.2}/.gitignore +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/CHANGELOG.md +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/MIGRATIONS.md +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/README.md +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/pyproject.toml +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/__init__.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/__main__.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/asset_url.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/check_counts.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/cli.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/compose_experiment.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/context.md +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/context_guide.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/count_groups.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/count_runs.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/create_app.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/create_experiment.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/create_note.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/data_html.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/default_config_text.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/default_counts.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/drain_watch.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/experiment_notes.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/experiment_runs.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/experiments.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/file_changes.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/format_duration.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/format_started.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/format_value.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/get_state.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/grid_cell.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/group_runs.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/init.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/invocation_started.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/is_non_negative_int.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/is_non_negative_number.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/is_positive_int.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/list_experiments.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/list_runs.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/load_config.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/load_experiment.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/load_run.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/log.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/log_path.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/memory_interval.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/models.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/modes.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/nests_runs.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/note_path.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/notebook_kernel.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/output_html.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/parse_run_view.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/parse_subset.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/pivot_runs.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/print_rows.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/python_blocks.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/read_config.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/read_path.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/render_markdown.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/retries.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/run_output.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/__init__.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/cgroup_memory.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/check_hook_placeholders.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/check_subset.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/container_cgroup.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/container_memory.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/describe_event.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/docker_output.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/execute_run.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/exit_signal.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/fill_dirs.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/fill_experiment_env.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/finalize_lost_runs.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/flag_name.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/in_subset.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/invocation_hook.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/invocation_meta.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/new_param_run_id.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/new_run_id.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/new_stamped_run_id.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/param_args.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/param_grid.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/param_run_name.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/placeholders.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/plan_runs.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/prepare_experiment.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/read_experiment_config.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/record_memory.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/run_experiment.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/run_folder.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/run_git.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/run_headless.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/runs_parent.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/signal_tree.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/start_experiment.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/stop_then_kill.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/wait_for_tree.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runner/write_run_json.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/runs_view_command.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/save_conflict_copy.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/save_note.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/saved_outputs.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/serve_app.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/server.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/set_state.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/shared_params.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/sort_href.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/sql_quote.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/state_path.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/static/elapsed.js +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/static/experiment.js +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/static/labnotes.css +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/static/local-time.js +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/static/new-note.js +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/static/note-edit.js +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/static/note-editor.js +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/static/row-link.js +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/static/run-cell.js +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/static/run-output.js +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/static/view-toggle.js +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/summarize_config.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/__init__.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/experiment_rows.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/experiment_run_ids.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/experiment_toml.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/experiments_ddl.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/file_prefix.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/file_text.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/iso_time.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/list_experiment_runs.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/note_text.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/open_tables.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/path_glob.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/path_pattern.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/read_blocks.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/read_experiment.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/read_file.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/read_log.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/read_memory.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/read_run.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/read_run_file.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/runs_columns.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tables/summarize_experiments.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/templates/base.html +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/templates/editor_imports.html +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/templates/experiment.html +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/templates/index.html +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/templates/note.html +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/templates/run.html +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/__init__.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/browse_app.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/browse_tui.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/check_view_response.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/config.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/dim.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/experiment_screen.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/experiments_screen.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/fill_table.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/format_cell.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/format_elapsed.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/group_cells.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/invocation_columns.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/invocation_rows.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/leave_prompt.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/log_block.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/log_blocks.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/native_rows.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/reload_on_change.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/run_app.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/run_cells.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/run_output.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/run_screen.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/run_tui.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/runs_table.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/runs_view.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/stopped_title.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/view_column.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/tui/view_process.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/utils/__init__.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/utils/format_bytes.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/utils/process_alive.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/utils/run_usage.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/utils/tree_rss.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/utils/tree_usage.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/view/__init__.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/view/answer.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/view/build.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/view/respond.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/view/serve.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/wait_for_note.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/src/labnotes/watch_rows.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/testing-conventions.toml +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/tests/conftest.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/tests/e2e/conftest.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/tests/integration/conftest.py +0 -0
- {labnotes-0.2.0 → labnotes-0.2.2}/uv.lock +0 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from collections import Counter
|
|
2
|
+
|
|
3
|
+
from labnotes.runner.command_flags import command_flags
|
|
4
|
+
from labnotes.runner.group_args import group_args
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def check_args(params: dict[str, list[object]], command: str, args: list[str]) -> None:
|
|
8
|
+
taken = Counter(flag.name for flag in command_flags(command))
|
|
9
|
+
given: set[str] = set()
|
|
10
|
+
for name in (arg.name for arg in group_args(args) if arg.name is not None):
|
|
11
|
+
if name in params:
|
|
12
|
+
raise ValueError(f"--{name} is a param. Pick it with --{name}=VALUE.")
|
|
13
|
+
if taken[name] > 1:
|
|
14
|
+
raise ValueError(
|
|
15
|
+
f"--{name} is in the command more than once, so -- can't override it."
|
|
16
|
+
)
|
|
17
|
+
if taken[name] and name in given:
|
|
18
|
+
raise ValueError(f"--{name} is in -- ARGS more than once.")
|
|
19
|
+
given.add(name)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from itertools import zip_longest
|
|
3
|
+
from typing import NamedTuple
|
|
4
|
+
|
|
5
|
+
from labnotes.runner.flag_name import flag_name
|
|
6
|
+
|
|
7
|
+
OPERATOR = ";&|<>()"
|
|
8
|
+
WORD = re.compile(
|
|
9
|
+
rf"""[{OPERATOR}]+|(?:[^\s{OPERATOR}'"\\]|\\.|'[^']*'|"(?:[^"\\]|\\.)*")+""",
|
|
10
|
+
re.DOTALL,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class CommandFlag(NamedTuple):
|
|
15
|
+
name: str
|
|
16
|
+
start: int
|
|
17
|
+
end: int
|
|
18
|
+
joined: bool
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def command_flags(command: str) -> list[CommandFlag]:
|
|
22
|
+
words = list(WORD.finditer(command))
|
|
23
|
+
flags: list[CommandFlag] = []
|
|
24
|
+
for word, after in zip_longest(words, words[1:]):
|
|
25
|
+
name = flag_name(word[0])
|
|
26
|
+
if name is None:
|
|
27
|
+
continue
|
|
28
|
+
joined = "=" in word[0]
|
|
29
|
+
end = word.end()
|
|
30
|
+
if not joined and after is not None:
|
|
31
|
+
value = after[0]
|
|
32
|
+
if value[0] not in OPERATOR and not value.startswith("-"):
|
|
33
|
+
end = after.end()
|
|
34
|
+
flags.append(CommandFlag(name, word.start(), end, joined))
|
|
35
|
+
return flags
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from typing import NamedTuple
|
|
2
|
+
|
|
3
|
+
from labnotes.runner.flag_name import flag_name
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Arg(NamedTuple):
|
|
7
|
+
name: str | None
|
|
8
|
+
value: str | None
|
|
9
|
+
tokens: list[str]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def group_args(args: list[str]) -> list[Arg]:
|
|
13
|
+
grouped: list[Arg] = []
|
|
14
|
+
values = {
|
|
15
|
+
index + 1
|
|
16
|
+
for index, token in enumerate(args[:-1])
|
|
17
|
+
if flag_name(token) is not None
|
|
18
|
+
and "=" not in token
|
|
19
|
+
and not args[index + 1].startswith("-")
|
|
20
|
+
}
|
|
21
|
+
for index, token in enumerate(args):
|
|
22
|
+
name = flag_name(token)
|
|
23
|
+
if index in values:
|
|
24
|
+
continue
|
|
25
|
+
if name is None:
|
|
26
|
+
grouped.append(Arg(None, None, [token]))
|
|
27
|
+
elif "=" in token:
|
|
28
|
+
grouped.append(Arg(name, token.partition("=")[2], [token]))
|
|
29
|
+
elif index + 1 in values:
|
|
30
|
+
grouped.append(Arg(name, args[index + 1], [token, args[index + 1]]))
|
|
31
|
+
else:
|
|
32
|
+
grouped.append(Arg(name, None, [token]))
|
|
33
|
+
return grouped
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import shlex
|
|
2
|
+
|
|
3
|
+
from labnotes.runner.command_flags import command_flags
|
|
4
|
+
from labnotes.runner.group_args import group_args
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def override_flags(command: str, args: list[str]) -> tuple[str, list[str]]:
|
|
8
|
+
flags = {flag.name: flag for flag in command_flags(command)}
|
|
9
|
+
replaced: list[tuple[int, int, str]] = []
|
|
10
|
+
rest: list[str] = []
|
|
11
|
+
for arg in group_args(args):
|
|
12
|
+
flag = flags.get(arg.name) if arg.name is not None else None
|
|
13
|
+
if flag is None:
|
|
14
|
+
rest += arg.tokens
|
|
15
|
+
elif arg.value is not None:
|
|
16
|
+
separator = "=" if flag.joined else " "
|
|
17
|
+
text = f"--{arg.name}{separator}{shlex.quote(arg.value)}"
|
|
18
|
+
replaced.append((flag.start, flag.end, text))
|
|
19
|
+
for start, end, text in sorted(replaced, reverse=True):
|
|
20
|
+
command = command[:start] + text + command[end:]
|
|
21
|
+
return command, rest
|
|
@@ -35,19 +35,21 @@ def project_snapshot(root: Path) -> Iterator[ProjectSnapshot]:
|
|
|
35
35
|
|
|
36
36
|
try:
|
|
37
37
|
sha = git(root, "rev-parse", "HEAD").decode("ascii").strip()
|
|
38
|
-
|
|
38
|
+
repo_root = Path(git(root, "rev-parse", "--show-toplevel").decode().strip())
|
|
39
|
+
project_prefix = root.resolve().relative_to(repo_root.resolve())
|
|
40
|
+
diff = git(repo_root, "diff", "HEAD")
|
|
39
41
|
except (OSError, subprocess.SubprocessError):
|
|
40
42
|
logging.warning("Project has no readable Git HEAD; running from the live tree")
|
|
41
43
|
yield ProjectSnapshot(root)
|
|
42
44
|
return
|
|
43
45
|
files = filter(
|
|
44
|
-
None, git(
|
|
46
|
+
None, git(repo_root, "ls-files", "-co", "--exclude-standard", "-z").split(b"\0")
|
|
45
47
|
)
|
|
46
48
|
ignored = filter(
|
|
47
49
|
None,
|
|
48
|
-
git(
|
|
49
|
-
|
|
50
|
-
),
|
|
50
|
+
git(
|
|
51
|
+
repo_root, "ls-files", "-oi", "--exclude-standard", "--directory", "-z"
|
|
52
|
+
).split(b"\0"),
|
|
51
53
|
)
|
|
52
54
|
with TemporaryDirectory(prefix="labnotes-") as directory:
|
|
53
55
|
snapshot = Path(directory)
|
|
@@ -73,14 +75,14 @@ def project_snapshot(root: Path) -> Iterator[ProjectSnapshot]:
|
|
|
73
75
|
"--quiet",
|
|
74
76
|
"--shared",
|
|
75
77
|
"--no-checkout",
|
|
76
|
-
str(
|
|
78
|
+
str(repo_root),
|
|
77
79
|
str(snapshot),
|
|
78
80
|
],
|
|
79
81
|
check=True,
|
|
80
82
|
)
|
|
81
83
|
for raw in files:
|
|
82
84
|
relative = Path(raw.decode())
|
|
83
|
-
source =
|
|
85
|
+
source = repo_root / relative
|
|
84
86
|
if not source.exists() and not source.is_symlink():
|
|
85
87
|
continue
|
|
86
88
|
target = snapshot / relative
|
|
@@ -100,7 +102,7 @@ def project_snapshot(root: Path) -> Iterator[ProjectSnapshot]:
|
|
|
100
102
|
continue
|
|
101
103
|
if any((snapshot / parent).is_symlink() for parent in relative.parents):
|
|
102
104
|
continue
|
|
103
|
-
source =
|
|
105
|
+
source = repo_root / relative
|
|
104
106
|
if source.is_dir() and (source / "pyvenv.cfg").exists():
|
|
105
107
|
skipped.add(relative)
|
|
106
108
|
continue
|
|
@@ -115,4 +117,4 @@ def project_snapshot(root: Path) -> Iterator[ProjectSnapshot]:
|
|
|
115
117
|
finally:
|
|
116
118
|
for number, handler in previous.items():
|
|
117
119
|
signal.signal(number, handler)
|
|
118
|
-
yield ProjectSnapshot(snapshot, sha, diff)
|
|
120
|
+
yield ProjectSnapshot(snapshot / project_prefix, sha, diff)
|
|
@@ -2,6 +2,7 @@ import shlex
|
|
|
2
2
|
from collections.abc import Sequence
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
|
+
from labnotes.runner.override_flags import override_flags
|
|
5
6
|
from labnotes.runner.param_args import param_args
|
|
6
7
|
|
|
7
8
|
|
|
@@ -9,4 +10,5 @@ def shell_command(
|
|
|
9
10
|
command: str, folder: Path, params: dict[str, object], args: Sequence[str] = ()
|
|
10
11
|
) -> str:
|
|
11
12
|
filled = command.replace("{run_dir}", shlex.quote(str(folder)))
|
|
12
|
-
|
|
13
|
+
overridden, rest = override_flags(filled, list(args))
|
|
14
|
+
return f"{overridden} {shlex.join([*param_args(params), *rest])}".rstrip()
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import shlex
|
|
2
|
-
|
|
3
|
-
from labnotes.runner.flag_name import flag_name
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def check_args(params: dict[str, list[object]], command: str, args: list[str]) -> None:
|
|
7
|
-
taken = {flag_name(token) for token in shlex.split(command)}
|
|
8
|
-
for arg in args:
|
|
9
|
-
name = flag_name(arg)
|
|
10
|
-
if name is None:
|
|
11
|
-
continue
|
|
12
|
-
if name in params:
|
|
13
|
-
raise ValueError(f"--{name} is a param. Pick it with --{name}=VALUE.")
|
|
14
|
-
if name in taken:
|
|
15
|
-
raise ValueError(f"--{name} is already in the command.")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|