testsuit 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.
- {testsuit-0.2.0/src/testsuit.egg-info → testsuit-0.2.2}/PKG-INFO +1 -1
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/datapack/model.py +1 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/README.md +10 -4
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/editor.py +86 -11
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/editor_api.py +1 -1
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/transports/local.py +6 -0
- testsuit-0.2.2/src/testsuit/sequencer/ui/assets/index-BKl1M_UV.css +1 -0
- testsuit-0.2.0/src/testsuit/sequencer/ui/assets/index-BuS4u73y.js → testsuit-0.2.2/src/testsuit/sequencer/ui/assets/index-CbEFdzIL.js +156 -155
- testsuit-0.2.0/src/testsuit/sequencer/ui/assets/python-CXwGBQa0.js → testsuit-0.2.2/src/testsuit/sequencer/ui/assets/python-BZmsOrut.js +1 -1
- testsuit-0.2.0/src/testsuit/sequencer/ui/assets/yaml-DlFYn7RY.js → testsuit-0.2.2/src/testsuit/sequencer/ui/assets/yaml-DrdUns_S.js +1 -1
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/ui/index.html +2 -2
- {testsuit-0.2.0 → testsuit-0.2.2/src/testsuit.egg-info}/PKG-INFO +1 -1
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit.egg-info/SOURCES.txt +4 -4
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/editor_t.py +62 -1
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/sequencer_t.py +22 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/editor/EditorHome.tsx +28 -16
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/editor/Session.tsx +15 -9
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/styles.css +20 -1
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/util.tsx +9 -0
- testsuit-0.2.0/src/testsuit/sequencer/ui/assets/index-BByuW_dm.css +0 -1
- {testsuit-0.2.0 → testsuit-0.2.2}/.editorconfig +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/.github/workflows/publish.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/.github/workflows/tests.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/.gitignore +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/CONTRIBUTING.md +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/LICENSE +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/README.md +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/docs/diagrams/overview.puml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/docs/diagrams/overview.svg +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/docs/diagrams/render.sh +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/docs/diagrams/seq_cancel.puml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/docs/diagrams/seq_cancel.svg +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/docs/diagrams/seq_editor.puml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/docs/diagrams/seq_editor.svg +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/docs/diagrams/seq_run.puml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/docs/diagrams/seq_run.svg +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/docs/diagrams/seq_submit.puml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/docs/diagrams/seq_submit.svg +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/docs/diagrams/toytrain_lab.puml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/docs/diagrams/toytrain_lab.svg +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/config_extract_data_any.json +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/.gitignore +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/README.md +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/baseline_expected.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/release_store/README.md +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/release_store/toytrain-sim/v1.1.0/SIM.txt +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/release_store/toytrain-sim/v1.1.0/dataset.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/release_store/toytrain-sw/v0.3.0/acquisition/APP.txt +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/release_store/toytrain-sw/v0.3.0/dataset.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/release_store/toytrain-sw/v0.3.0/pilot/APP.txt +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/release_store/toytrain-sw/v0.3.0/pilot/FIRMWARE.txt +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/release_store/toytrain-sw/v0.3.0/telemetry/APP.txt +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/setup/globals.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/setup/platforms/emulated.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/setup/platforms/sim_bench.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/setup/scripts/check_data.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/setup/templates/acquisition.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/setup/templates/exploit.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/setup/templates/piezo_sim.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/setup/templates/pilot.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/setup/templates/propulsion_sim.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/setup/templates/telemetry.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/setup/toytrain_setup.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/testdef/front_contact/criteria/front_contact/front_contact.mexploit.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/testdef/front_contact/scenario.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/testdef/front_contact/testdef.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/testdef/max_speed/criteria/max_speed/max_speed.mexploit.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/testdef/max_speed/scenario.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/datapack/testdef/max_speed/testdef.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/lab/toytrain_emulated.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/lab/toytrain_lab.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/lab/types/toytrain.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/lab/types_emulated/toytrain.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/pyproject.toml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/sample/data/front_contact/propulsion.propj +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/sample/data/front_contact/telemetry.csv +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/sample/data/max_speed/propulsion.propj +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/sample/data/max_speed/telemetry.csv +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/sample/exploit_front_contact.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/sample/exploit_max_speed.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/sample/make_runs.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/src/toytrain/__init__.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/src/toytrain/assets/toytrain_logo.svg +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/src/toytrain/checks.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/src/toytrain/cli.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/src/toytrain/criteria.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/src/toytrain/filemgrs.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/src/toytrain/importer.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/src/toytrain/plugin.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/tests/conftest.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/tests/etc/exploit_nok.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/tests/etc/overspeed/overspeed.sim.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/tests/test_cli.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/tests/test_criteria.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/tests/test_datapack.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/tests/test_exploit_runner.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/tests/test_formats.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/tsq.dev.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/examples/toytrain/tsq.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/pyproject.toml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/setup.cfg +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/__init__.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/cli/__init__.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/cli/apply_clock_correction.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/cli/data2db.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/cli/data2h5.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/cli/datapack.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/cli/evalfile.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/cli/exploit_runner.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/cli/extract_data_any.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/cli/extract_data_flags.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/cli/mxp.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/cli/notebooks.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/cli/tsq.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/DataFileMgrs/AFileMgr.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/DataFileMgrs/ClickhouseFileMgr.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/DataFileMgrs/CsvFileMgr.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/DataFileMgrs/DxdFileMgr.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/DataFileMgrs/FolderParamMgr.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/DataFileMgrs/H5FileMgr.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/DataFileMgrs/InfluxDbFileMgr.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/DataFileMgrs/MdfFileMgr.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/DataFileMgrs/TdmsFileMgr.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/DataFileMgrs/UdbfFileMgr.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/DataFileMgrs/__init__.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/DataFileMgrs/formats.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/DataframeToHdf5.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/__init__.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/data2db.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/datapack/ADataImporter.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/datapack/GitImporter.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/datapack/__init__.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/datapack/baseline.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/datapack/datapack_tools.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/datapack/generators.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/datapack/importers.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/datapack/processors.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/datapack/templating.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/datatoolbox.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/h5diff.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/plotBackends/__init__.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/plotBackends/common.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/plotBackends/matplotlibBackend.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/plotBackends/plotlyBackend.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/datatools/plotHelpers.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/exploit/mexploit/__init__.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/exploit/mexploit/conftest.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/exploit/mexploit/conftest_scn_template.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/exploit/mexploit/criteria.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/exploit/mexploit/helpers.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/exploit/mexploit/mexploit.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/exploit/mexploit/registry.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/exploit/runner/__init__.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/exploit/runner/exploit_runner.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/exploit/runner/report.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/exploit/runner/report_html.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/exploit/runner/report_libs/README.md +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/exploit/runner/report_libs/showdown.min.js +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/exploit/runner/report_libs/toastui-editor-all.min.js +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/exploit/runner/report_libs/toastui-editor.min.css +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/exploit/runner/runProcess.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/exploit/runner/utils.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/jupytertools/FileDialog.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/jupytertools/JupyterGui.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/jupytertools/MexploitJupyterGui.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/jupytertools/PlotJupyterGui.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/jupytertools/__init__.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/jupytertools/h5ConvertJupyterGui.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/jupytertools/install.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/jupytertools/notebooks/__init__.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/jupytertools/notebooks/data_plot.ipynb +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/jupytertools/notebooks/h5_convert.ipynb +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/jupytertools/notebooks/mexploit.ipynb +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/misc/MonitorProgress.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/misc/__init__.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/misc/files.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/misc/logger.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/plugins.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/__init__.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/api.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/benchmark.md +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/component_types.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/config.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/daemon.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/editor_schemas.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/engine.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/gitlab/README.md +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/gitlab/cleanup.sh +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/gitlab/config.sh +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/gitlab/prepare.sh +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/gitlab/run.sh +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/intake.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/inventory.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/lab.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/model.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/monitor.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/registry.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/results.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/scheduler.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/sequencer.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/store.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/transports/__init__.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/transports/ssh.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/ui/assets/codicon-DCmgc-ay.ttf +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/ui/assets/editor.worker-B4pQIWZD.js +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/ui/assets/ini-BvajGCUy.js +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/ui/assets/markdown-B811l8j2.js +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/ui/assets/shell-CsDZo4DB.js +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/ui/assets/yaml.worker-0FgWxutO.js +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/util.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit/sequencer/yamledit.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit.egg-info/dependency_links.txt +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit.egg-info/entry_points.txt +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit.egg-info/requires.txt +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/src/testsuit.egg-info/top_level.txt +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/clickhousefilemgr_t.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/data2db_t.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/datapack_t.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/datatoolbox_t.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/data/csv/CorridorParam.csv +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/data/csv/National_Instruments.csv +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/data/csv/channels_recording.csv +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/data/csv/clocks.csv +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/data/csv/demo_exploit.clean_01.csv +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/data/csv/demo_exploit.clean_02.csv +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/data/csv/flags.csv +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/data/csv/influxdb.csv +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/data/csv/test_date_at_the_end.csv +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/datapack/setup/globals.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/datapack/setup/includes/header.txt +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/datapack/setup/utest_ref_files/conf_dir/limits.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/datapack/setup/utest_ref_files/ref1.txt +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/datapack/setup/utest_ref_files/ref2.txt +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/datapack/setup/utest_setup.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/datapack/testdef/datapack_utest.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/datapack/testdef/local_ref_files/my_ref_file.txt +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/datapack/testdef/overrides.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/datapack/testdef/values.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/exploit_config_NOK.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/exploit_config_NOK_comments.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/exploit_config_OK.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/exploit_config_OK_comments.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/exploit_shiftDateConst_OK.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/exploit_shiftDateParam_OK.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/scenario/compute_clock_drift/clock_drift.mexploit.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/scenario/session_NOK/testrun_01/testsuite01.mexploit.yaml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/scenario/session_NOK/testrun_02/testsuite_02.mexploit.yaml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/scenario/session_OK/testrun_01/testsuite01.mexploit.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/scenario/session_OK/testrun_01/testsuite02.mexploit.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/scenario/session_OK/testrun_01/testsuite03.mexploit.yaml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/scenario/session_OK/testrun_01/testsuite04.mexploit.yaml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/scenario/session_OK/testrun_02/testsuite01.mexploit.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/scenario/session_OK/testrun_02/testsuite02.mexploit.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/scenario/session_OK/testrun_02/testsuite03.mexploit.yaml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/scenario/shiftDateConst_OK/param1_partially_shifted.mexploit.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/scenario/shiftDateConst_OK/param2_not_shifted.mexploit.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/scenario/shiftDateParam_OK/param1_partially_shifted.mexploit.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/scenario/shiftDateParam_OK/param2_not_shifted.mexploit.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/exploit_runner/values.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/mexploit/custom_exploit/custom_criteria.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/mexploit/custom_exploit/custom_helpers.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/mexploit/scenarii/mxp_NOK_check_param_at_rst/1_check_param_at_rest.mexploit.yaml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/mexploit/scenarii/mxp_NOK_corridor/0_corridor.mexploit.yaml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/mexploit/scenarii/mxp_NOK_registered_crit/1_registered.mexploit.yaml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/mexploit/scenarii/mxp_NOK_sequence/0_sequence.mexploit.yaml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/mexploit/scenarii/mxp_NOK_sequence_multi/0_sequence.mexploit.yaml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/mexploit/scenarii/mxp_OK_custom_crit/1_custom.mexploit.yaml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/mexploit/scenarii/mxp_OK_main_functions/0_time_origin.mexploit.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/mexploit/scenarii/mxp_OK_main_functions/1_computed_param.mexploit.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/mexploit/scenarii/mxp_OK_main_functions/1_computed_param_multiline.mexploit.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/mexploit/scenarii/mxp_OK_main_functions/1_corridor.mexploit.yaml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/mexploit/scenarii/mxp_OK_main_functions/1_sequence.mexploit.yaml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/mexploit/scenarii/mxp_OK_main_functions/2_plot.mexploit.yaml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/mexploit/scenarii/mxp_OK_main_functions/3_helper_dropdups.mexploit.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/mexploit/scenarii/mxp_OK_main_functions/3_helper_mask_values_on_event.mexploit.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/mexploit/scenarii/mxp_OK_registered_crit/1_registered.mexploit.yaml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/etc/misc/flags_desc.yml +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/exploit_runner_crash_t.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/exploit_runner_t.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/extensions_t.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/h5filemgr_t.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/loaddata_t.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/mexploit_t.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/misc_t.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/notebooks_t.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/plot_backends_t.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/ref/loaddata_test/National_Instruments.h5 +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/ref/loaddata_test/channels_recording.h5 +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/ref/loaddata_test/flags_flags.h5 +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/ref/loaddata_test/influxdb.h5 +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/ref/loaddata_test/sample_csv.h5 +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/ref/loaddata_test/sample_csv_date_at_the_end.h5 +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/report_html_t.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/tdms_t.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/tests/templating_t.py +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/e2e/smoke.mjs +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/index.html +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/package-lock.json +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/package.json +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/api.ts +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/editor/Generate.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/editor/InventoryForm.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/editor/PipelineEditor.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/editor/Publish.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/editor/SetupForm.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/editor/TemplateEditor.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/editor/TestdefForm.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/editor/TypesForm.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/editor/commands.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/editor/state.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/editor/wizards.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/fields.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/files.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/graph.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/main.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/monaco.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/pages/Config.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/pages/Lab.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/pages/Queue.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/pages/Run.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/pages/Runs.tsx +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/vendor.d.ts +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/src/yaml.worker.ts +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/tsconfig.json +0 -0
- {testsuit-0.2.0 → testsuit-0.2.2}/ui/vite.config.ts +0 -0
|
@@ -125,6 +125,7 @@ class ComponentConfiguration(_Model):
|
|
|
125
125
|
|
|
126
126
|
class ComponentType(_Model):
|
|
127
127
|
configurations: dict[str, ComponentConfiguration]
|
|
128
|
+
description: str = "" # what the type is (shown in the Editor)
|
|
128
129
|
# for the test sequencer
|
|
129
130
|
extends: str = ""
|
|
130
131
|
commands: dict[str, Any] = Field(default_factory=dict)
|
|
@@ -249,7 +249,7 @@ The sequencer reuses the testsuit `datapack` tool (YAML dictionaries, Jinja2 tem
|
|
|
249
249
|
| Term | Meaning |
|
|
250
250
|
|---|---|
|
|
251
251
|
| **Editor mode** | the part of the web UI that edits the lab and tests repositories (`server.editor`, section 13.2). |
|
|
252
|
-
| **editing session** | a scratch git clone of one repository, on one branch, where the Editor writes: a **lab session** edits the inventory and types, a **workspace session** (one of `server.workspaces`) edits setups, test definitions, sub-pipelines, dictionaries and templates. |
|
|
252
|
+
| **editing session** | a scratch git clone of one repository, on one branch, where the Editor writes (or, **in place**, the folder itself): a **lab session** edits the inventory and types, a **workspace session** (one of `server.workspaces`) edits setups, test definitions, sub-pipelines, dictionaries and templates. |
|
|
253
253
|
| **context** | what the Editor's menus and help are built from: the types with their commands, roles, stage types, setups, test definitions and installed plugins, read again after each save. A lab session uses its own files; a workspace session uses the running lab. |
|
|
254
254
|
| **palette** | in the pipeline graph, what a step can do on each logical component: its commands, with where each comes from, plus the generic and plugin step types. |
|
|
255
255
|
| **flattened view** | the whole pipeline with sub-pipelines expanded and every command resolved for a setup configuration, as the run will see it. |
|
|
@@ -925,7 +925,7 @@ tsq config # settings in use, a
|
|
|
925
925
|
- `GET /events` (Server-Sent Events: run and component state changes, log lines);
|
|
926
926
|
- `GET /runs/{id}/pipeline` (phases and steps after sub-pipeline expansion, with their `needs`: the run graph of the UI);
|
|
927
927
|
- Editor mode only (section 13.2):
|
|
928
|
-
- `GET /edit` (repositories, sessions, last pushes), `POST /edit/sessions` (scratch clone of a repository), `GET|DELETE /edit/sessions/{id}`;
|
|
928
|
+
- `GET /edit` (repositories, sessions, last pushes), `POST /edit/sessions` (scratch clone of a repository, or `local: true` to edit it in place), `GET|DELETE /edit/sessions/{id}`;
|
|
929
929
|
- `GET /edit/sessions/{id}/files`, `GET|PUT|DELETE /edit/sessions/{id}/files/{path}` (a `PUT` of `data` merges it into the file, keeping its comments), `POST .../rename`;
|
|
930
930
|
- helpers: `GET .../context` (lab types, roles, stage types, workspace contents), `GET .../schemas` (JSON Schemas with help and the lab's choices), `POST .../validate`, `.../flatten`, `.../palette`, `.../keys`, `.../preview`, `POST /edit/reachability`;
|
|
931
931
|
- `POST .../datapack` (generate), `GET .../datapack/{name}[/files/{path}]`, `POST .../datapack/{name}/submit`;
|
|
@@ -947,7 +947,13 @@ The kernel never depends on the UI below: it is a web front end on the REST API,
|
|
|
947
947
|
|
|
948
948
|
An optional mode of the same UI, enabled with `server.editor` (off by default, since it writes files). It edits the YAML files the CLI tools read, and adds nothing the files cannot express: whatever it does can also be done with a text editor and git.
|
|
949
949
|
|
|
950
|
-
**Where it works.**
|
|
950
|
+
**Where it works.** By default an editing session works in a scratch clone of the repository being edited (the lab repository, or one of `server.workspaces`), on the branch it was opened on, so that a half-done change never reaches the running lab.
|
|
951
|
+
|
|
952
|
+
**In place.** A session can instead edit the folder itself (`in place (no clone)` on the Editor home, `"local": true` on `POST /edit/sessions`):
|
|
953
|
+
- The files are saved where the sequencer reads them. A lab change still applies only on **Reload**; a test definition is used the next time a datapack is generated.
|
|
954
|
+
- The folder need not be a git work tree. When it is, the session works on the checked-out branch, and review and push commit and push only the edited folder, in the user's name: other changes of that working copy are left alone. From a detached HEAD (a lab on a tag) nothing can be pushed.
|
|
955
|
+
- Rebase replays the working copy's own commits on the upstream branch; it never drops them.
|
|
956
|
+
- One in-place session per repository at a time; opening it again returns the same session. Closing it keeps the files.
|
|
951
957
|
|
|
952
958
|
**Lab inventory.**
|
|
953
959
|
- Forms for stages, ad hoc components and their variables, with a YAML view next to them.
|
|
@@ -1038,7 +1044,7 @@ src/testsuit/sequencer/
|
|
|
1038
1044
|
results.py # results datapack, large files, fetch.txt
|
|
1039
1045
|
transports/ # local, ssh (AsyncSSH, SFTP), process groups and pid files
|
|
1040
1046
|
api.py # FastAPI app; serves the web UI under /ui
|
|
1041
|
-
editor.py # Editor mode: sessions on scratch clones, file kinds, checks, helpers, generate, push, rebase
|
|
1047
|
+
editor.py # Editor mode: sessions on scratch clones or in place, file kinds, checks, helpers, generate, push, rebase
|
|
1042
1048
|
editor_api.py # its REST routes (server.editor)
|
|
1043
1049
|
editor_schemas.py # JSON Schemas of the files, with help, filled with the lab's choices
|
|
1044
1050
|
yamledit.py # YAML written back keeping comments, key order and layout
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
"""Editor mode (README section 13.2): editing sessions on scratch clones, checks, helpers, push.
|
|
2
2
|
|
|
3
3
|
An editing session is a clone of the repository holding the lab folder, or one of
|
|
4
|
-
``server.workspaces``, in ``<storage.root>/editor/<session>/repo
|
|
5
|
-
|
|
4
|
+
``server.workspaces``, in ``<storage.root>/editor/<session>/repo``: the sequencer's own copy is not
|
|
5
|
+
written, and a change reaches the lab when it is pushed, then reloaded on demand.
|
|
6
|
+
|
|
7
|
+
An *in-place* session (``local``) edits the folder itself instead, without a clone: the files are
|
|
8
|
+
saved where the sequencer reads them, with whatever else that working copy holds. The folder need
|
|
9
|
+
not be a git work tree; when it is, review and push commit and push from it. A lab change still
|
|
10
|
+
applies only on ``tsq lab reload``. One in-place session per repository at a time.
|
|
6
11
|
|
|
7
12
|
Everything the Editor does can be done with a text editor and git: it reads and writes the same
|
|
8
13
|
YAML files, and keeps them as written (``yamledit``).
|
|
@@ -82,10 +87,13 @@ class EditSession:
|
|
|
82
87
|
upstream: str | None
|
|
83
88
|
created_at: str = field(default_factory=now)
|
|
84
89
|
pushed: list[dict] = field(default_factory=list)
|
|
90
|
+
local: bool = False # in place: edits the folder itself, no clone
|
|
91
|
+
local_root: str = "" # in place: the git work tree root, or the folder when it is not in one
|
|
92
|
+
git: bool = True # in place: whether local_root is a git work tree
|
|
85
93
|
|
|
86
94
|
@property
|
|
87
95
|
def root(self) -> Path:
|
|
88
|
-
return Path(self.dir) / "repo"
|
|
96
|
+
return Path(self.local_root) if self.local else Path(self.dir) / "repo"
|
|
89
97
|
|
|
90
98
|
@property
|
|
91
99
|
def folder(self) -> Path:
|
|
@@ -177,7 +185,9 @@ class Editor:
|
|
|
177
185
|
return repo
|
|
178
186
|
raise SequencerError(f"no repository '{repo_id}' (lab, or workspace0.. from server.workspaces)")
|
|
179
187
|
|
|
180
|
-
def open(self, repo_id: str, branch: str | None = None) -> EditSession:
|
|
188
|
+
def open(self, repo_id: str, branch: str | None = None, local: bool = False) -> EditSession:
|
|
189
|
+
if local:
|
|
190
|
+
return self._open_in_place(repo_id, branch)
|
|
181
191
|
repo = self._repo(repo_id)
|
|
182
192
|
source = Path(repo["folder"])
|
|
183
193
|
src_root = _repo_root(source)
|
|
@@ -212,6 +222,49 @@ class Editor:
|
|
|
212
222
|
self._save(session)
|
|
213
223
|
return session
|
|
214
224
|
|
|
225
|
+
def _open_in_place(self, repo_id: str, branch: str | None) -> EditSession:
|
|
226
|
+
"""A session on the folder itself. The one already open on that repository is returned as is."""
|
|
227
|
+
for existing in self.sessions.values():
|
|
228
|
+
if existing.local and existing.repo == repo_id:
|
|
229
|
+
if branch and branch != existing.branch:
|
|
230
|
+
raise SequencerError(f"an in-place session works on the checked-out branch "
|
|
231
|
+
f"('{existing.branch or 'detached'}'), not '{branch}'")
|
|
232
|
+
return existing
|
|
233
|
+
repo = self._repo(repo_id)
|
|
234
|
+
source = Path(repo["folder"]).resolve()
|
|
235
|
+
if not source.is_dir():
|
|
236
|
+
raise SequencerError(f"no folder '{source}'")
|
|
237
|
+
try:
|
|
238
|
+
root, git = _repo_root(source).resolve(), True
|
|
239
|
+
except SequencerError:
|
|
240
|
+
root, git = source, False
|
|
241
|
+
current = _git(root, "symbolic-ref", "--quiet", "--short", "HEAD", check=False).strip() if git else ""
|
|
242
|
+
if branch and branch != current:
|
|
243
|
+
raise SequencerError(f"an in-place session works on the checked-out branch ('{current or 'detached'}'), "
|
|
244
|
+
f"not '{branch}': check it out first, or open a session on a clone")
|
|
245
|
+
session_id = uuid.uuid4().hex[:8]
|
|
246
|
+
folder = self.base / session_id
|
|
247
|
+
folder.mkdir(parents=True)
|
|
248
|
+
upstream = (_git(root, "remote", "get-url", "origin", check=False).strip() or None) if git else None
|
|
249
|
+
if git: # datapacks generated here leave their work folder
|
|
250
|
+
exclude = Path(_git(root, "rev-parse", "--git-path", "info/exclude").strip())
|
|
251
|
+
exclude = exclude if exclude.is_absolute() else root / exclude
|
|
252
|
+
if ".current_datapack/" not in (exclude.read_text() if exclude.is_file() else ""):
|
|
253
|
+
exclude.parent.mkdir(parents=True, exist_ok=True)
|
|
254
|
+
with open(exclude, "a") as f:
|
|
255
|
+
f.write("\n.current_datapack/\n")
|
|
256
|
+
session = EditSession(id=session_id, repo=repo_id, kind=repo["kind"], source=str(source), dir=str(folder),
|
|
257
|
+
sub=source.relative_to(root).as_posix() if source != root else "", branch=current,
|
|
258
|
+
base=_git(root, "rev-parse", "HEAD", check=False).strip() if git else "",
|
|
259
|
+
upstream=upstream, local=True, local_root=str(root), git=git)
|
|
260
|
+
self.sessions[session_id] = session
|
|
261
|
+
self._save(session)
|
|
262
|
+
return session
|
|
263
|
+
|
|
264
|
+
def _need_git(self, session: EditSession) -> None:
|
|
265
|
+
if not session.git:
|
|
266
|
+
raise SequencerError(f"'{session.source}' is not a git work tree: there is nothing to review or push")
|
|
267
|
+
|
|
215
268
|
def _save(self, session: EditSession) -> None:
|
|
216
269
|
(Path(session.dir) / "session.json").write_text(json.dumps(asdict(session), indent=1))
|
|
217
270
|
|
|
@@ -221,12 +274,15 @@ class Editor:
|
|
|
221
274
|
return self.sessions[session_id]
|
|
222
275
|
|
|
223
276
|
def close(self, session_id: str) -> None:
|
|
277
|
+
"""Drop the session: its clone, generated datapacks and notes. An in-place session's folder is kept."""
|
|
224
278
|
session = self.sessions.pop(session_id, None)
|
|
225
279
|
if session is not None:
|
|
226
280
|
shutil.rmtree(session.dir, ignore_errors=True)
|
|
227
281
|
|
|
228
282
|
def describe(self, session: EditSession) -> dict:
|
|
229
|
-
|
|
283
|
+
if not session.git:
|
|
284
|
+
return {**session.describe(), "changed": None, "head": None}
|
|
285
|
+
status = _git(session.root, "status", "--porcelain", "--untracked-files=all", "--", session.sub or ".", check=False)
|
|
230
286
|
return {**session.describe(), "changed": len([line for line in status.splitlines() if line.strip()]),
|
|
231
287
|
"head": _git(session.root, "rev-parse", "HEAD", check=False).strip()}
|
|
232
288
|
|
|
@@ -967,9 +1023,12 @@ class Editor:
|
|
|
967
1023
|
# ── git: diff, push, rebase ──────────────────────────────────────────
|
|
968
1024
|
|
|
969
1025
|
def diff(self, session: EditSession) -> dict:
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
1026
|
+
self._need_git(session)
|
|
1027
|
+
# only the edited folder: an in-place session's working copy may hold other changes, left alone
|
|
1028
|
+
where = ["--", session.sub or "."]
|
|
1029
|
+
_git(session.root, "add", "-A", *where)
|
|
1030
|
+
names = _git(session.root, "diff", "--cached", "--name-status", session.base, *where)
|
|
1031
|
+
patch = _git(session.root, "diff", "--cached", session.base, *where)
|
|
973
1032
|
files = [{"status": line.split("\t")[0], "path": line.split("\t")[-1]} for line in names.splitlines() if line]
|
|
974
1033
|
ahead = _git(session.root, "rev-list", "--count", f"{session.base}..HEAD").strip()
|
|
975
1034
|
return {"files": files, "patch": patch, "branch": session.branch, "base": session.base,
|
|
@@ -993,6 +1052,9 @@ class Editor:
|
|
|
993
1052
|
"""Commit the session's changes as the user, tag, and push to the session's branch. On a refused
|
|
994
1053
|
push nothing is applied: the commit and the tag are undone, the changes stay in the session."""
|
|
995
1054
|
credentials = credentials or {}
|
|
1055
|
+
self._need_git(session)
|
|
1056
|
+
if not session.branch:
|
|
1057
|
+
raise SequencerError("the working copy is on no branch (detached HEAD): check out a branch to push from it")
|
|
996
1058
|
if not message.strip():
|
|
997
1059
|
raise SequencerError("a commit message is needed")
|
|
998
1060
|
if not author_name.strip() or not author_email.strip():
|
|
@@ -1005,7 +1067,7 @@ class Editor:
|
|
|
1005
1067
|
if not diff["files"]:
|
|
1006
1068
|
raise SequencerError("nothing to push: no change since the session started")
|
|
1007
1069
|
ident = ["-c", f"user.name={author_name}", "-c", f"user.email={author_email}"]
|
|
1008
|
-
_git(session.root, *ident, "commit", "--quiet", "-m", message)
|
|
1070
|
+
_git(session.root, *ident, "commit", "--quiet", "-m", message, "--", session.sub or ".")
|
|
1009
1071
|
commit = _git(session.root, "rev-parse", "HEAD").strip()
|
|
1010
1072
|
if tag:
|
|
1011
1073
|
_git(session.root, *ident, "tag", "-a", tag, "-m", message)
|
|
@@ -1034,15 +1096,28 @@ class Editor:
|
|
|
1034
1096
|
def rebase(self, session: EditSession, credentials: dict | None = None) -> dict:
|
|
1035
1097
|
"""Fetch the upstream branch and put the session's changes on top of it."""
|
|
1036
1098
|
credentials = credentials or {}
|
|
1099
|
+
self._need_git(session)
|
|
1037
1100
|
result = subprocess.run(["git", "-c", "credential.helper=", "fetch", "--quiet", "--tags", "origin"],
|
|
1038
1101
|
cwd=session.root, capture_output=True, text=True, timeout=300,
|
|
1039
1102
|
env={**os.environ, "GIT_TERMINAL_PROMPT": "0", **self._push_env(credentials)})
|
|
1040
1103
|
if result.returncode:
|
|
1041
1104
|
return {"ok": False, "error": self._scrub(result.stderr.strip(), credentials)}
|
|
1042
1105
|
_git(session.root, "add", "-A")
|
|
1106
|
+
before = len(_git(session.root, "stash", "list").splitlines())
|
|
1043
1107
|
stashed = _git(session.root, "stash", "push", "--quiet", "--include-untracked", "-m", "editor", check=False)
|
|
1044
|
-
has_stash =
|
|
1045
|
-
|
|
1108
|
+
has_stash = len(_git(session.root, "stash", "list").splitlines()) > before
|
|
1109
|
+
if session.local:
|
|
1110
|
+
# the user's working copy: its own commits are replayed on the upstream branch, never dropped
|
|
1111
|
+
moved = subprocess.run(["git", "rebase", "--quiet", f"origin/{session.branch}"], cwd=session.root,
|
|
1112
|
+
capture_output=True, text=True)
|
|
1113
|
+
if moved.returncode:
|
|
1114
|
+
_git(session.root, "rebase", "--abort", check=False)
|
|
1115
|
+
if has_stash:
|
|
1116
|
+
_git(session.root, "stash", "pop", "--quiet", check=False)
|
|
1117
|
+
return {"ok": False, "error": "the local commits do not apply on the latest revision: "
|
|
1118
|
+
+ (moved.stderr or moved.stdout).strip(), "conflicts": []}
|
|
1119
|
+
else:
|
|
1120
|
+
_git(session.root, "reset", "--quiet", "--hard", f"origin/{session.branch}")
|
|
1046
1121
|
session.base = _git(session.root, "rev-parse", "HEAD").strip()
|
|
1047
1122
|
self._save(session)
|
|
1048
1123
|
conflicts = []
|
|
@@ -39,7 +39,7 @@ def add_editor_routes(app: FastAPI, seq) -> Editor:
|
|
|
39
39
|
|
|
40
40
|
@app.post("/edit/sessions", status_code=201)
|
|
41
41
|
async def open_session(body: dict):
|
|
42
|
-
s = await run(editor.open, str(body.get("repo") or "lab"), body.get("branch"))
|
|
42
|
+
s = await run(editor.open, str(body.get("repo") or "lab"), body.get("branch"), bool(body.get("local")))
|
|
43
43
|
return editor.describe(s)
|
|
44
44
|
|
|
45
45
|
@app.get("/edit/sessions/{sid}")
|
|
@@ -45,6 +45,12 @@ class LocalTransport(Transport):
|
|
|
45
45
|
code = None
|
|
46
46
|
process.done.set_result(Result(code, process.text(), error=f"killed by {signal}" if signal else None,
|
|
47
47
|
signal=signal))
|
|
48
|
+
except asyncio.CancelledError:
|
|
49
|
+
# The loop is shutting down (tsqd stopping, asyncio.run ending): close the process's
|
|
50
|
+
# transport now. Left to the garbage collector, it would be closed after the loop,
|
|
51
|
+
# which fails with 'Event loop is closed'.
|
|
52
|
+
proc._transport.close()
|
|
53
|
+
raise
|
|
48
54
|
except Exception as e: # pragma: no cover - defensive
|
|
49
55
|
if not process.done.done():
|
|
50
56
|
process.done.set_result(Result(None, process.text(), error=f"transport: {e}"))
|