qplotter 1.6.0__tar.gz → 1.6.1__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.
- {qplotter-1.6.0 → qplotter-1.6.1}/CHANGELOG.md +27 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/CONTRIBUTING.md +1 -1
- {qplotter-1.6.0 → qplotter-1.6.1}/MANIFEST.in +1 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/PKG-INFO +12 -7
- {qplotter-1.6.0 → qplotter-1.6.1}/README.md +10 -5
- {qplotter-1.6.0 → qplotter-1.6.1}/docs/architecture.md +10 -2
- {qplotter-1.6.0 → qplotter-1.6.1}/docs/distribution.md +50 -19
- {qplotter-1.6.0 → qplotter-1.6.1}/docs/trusted-live-reader.md +18 -2
- {qplotter-1.6.0 → qplotter-1.6.1}/docs/user-guide.md +8 -3
- {qplotter-1.6.0 → qplotter-1.6.1}/pyproject.toml +2 -2
- qplotter-1.6.1/scripts/revalidate_published_release.py +81 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/scripts/validate_compiler_free_install.py +11 -1
- {qplotter-1.6.0 → qplotter-1.6.1}/scripts/validate_distribution.py +1 -1
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/__main__.py +2 -1
- qplotter-1.6.1/src/qplot/_build_info.json +1 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_live.py +1 -1
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_plot.py +21 -6
- qplotter-1.6.1/src/qplot/windows/_auto_plot.py +201 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_database_actions.py +7 -6
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_actions.py +15 -13
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_run_controls.py +4 -6
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_trusted_derived_qt.py +4 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/main.py +3 -1
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplotter.egg-info/SOURCES.txt +4 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_live.py +4 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_plot.py +36 -0
- qplotter-1.6.1/tests/datahandling/test_trusted_wal_contention.py +214 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_ci_artifacts.py +12 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_compiler_free_install.py +16 -1
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_config.py +1 -1
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_distribution_validator.py +4 -3
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_packaging_split.py +1 -1
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_release.py +68 -3
- qplotter-1.6.1/tests/windows/test_auto_plot.py +203 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_main_window.py +6 -4
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_trusted_plot_launch.py +237 -1
- qplotter-1.6.0/src/qplot/_build_info.json +0 -1
- {qplotter-1.6.0 → qplotter-1.6.1}/Agents.md +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/LICENSE +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/docs/assets/qplot-color-scale-dialog.png +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/docs/assets/qplot-heatmap.png +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/docs/assets/qplot-line-plot.png +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/docs/assets/qplot-main-window.png +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/docs/configuration.md +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/docs/demo-data.md +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/docs/troubleshooting.md +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/scripts/README.md +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/scripts/benchmark_heatmap_aggregation.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/scripts/benchmark_plot_launch.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/scripts/capture_demo_screenshots.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/scripts/liveplot.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/scripts/manual_run.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/scripts/profile_trusted_reads.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/scripts/release.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/scripts/time_stress.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/scripts/write_build_info.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/setup.cfg +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/__init__.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/_auxiliary_paths.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/_metadata.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/_repair.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/_shutdown_supervisor.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/_version.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/_windows_shutdown_job.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/__init__.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/config.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/config_schema.json +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/fonts.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/scripts.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/themes/__init__.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/themes/_base.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/themes/blank.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/themes/dark.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/themes/light.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/LoadFromDB.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/__init__.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/_trusted_live_helper.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/_trusted_live_protocol.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/database.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/dimensions.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/file_identity.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/parameter_data.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/plot_progress.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/qcodes_cache.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/qcodes_compat.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/readSQL.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/readonly.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/source_activity.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_array_preview.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_derived_cache.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_derived_rendering.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_heatmap.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_live_queries.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_live_service.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_live_supervisor.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_presentation.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_snapshot.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_work_coordinator.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_work_scheduler.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/diagnostics.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_01_10mb.csv +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_02_25mb.csv +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_03_50mb.csv +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_04_100mb.csv +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_05_250mb.csv +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_06_500mb.csv +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_07_1gb.csv +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_08_5gb.csv +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_09_10gb.csv +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_10_30gb.csv +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/testdata.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/tools/__init__.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/tools/finite_means.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/tools/general.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/tools/heatmap_geometry.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/tools/operation_registry.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/tools/plot_tools.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/tools/sample_statistics.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/tools/worker.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/__init__.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_colorbar.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_commands.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_config_persistence.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_dataset_handle.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_display_precision.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_dragdrop.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_export_paths.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_help.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_mixed_appearance.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_mixed_plots.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_native_averaging.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_native_transforms.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot1d_snap.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot1d_traces.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot2d_colorbar.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot2d_colorbar_dialog.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot2d_layers.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot2d_sweeps.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plotWin.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_annotation.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_appearance.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_axis_scaling.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_data_viewbox.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_drop_axes.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_export.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_feedback.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_marquee.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_refresh.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_source_promotion.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_state.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_status.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_tiling.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_transform_labels.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_preferences.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_refresh_interval.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_shortcuts.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_subplots/__init__.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_subplots/subplot1d.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_subplots/subplot2d.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_svg_export.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_widgets/__init__.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_widgets/_run_formatting.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_widgets/details_tables.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_widgets/dropbox.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_widgets/operations.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_widgets/preview.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_widgets/run_list_items.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_widgets/toolbar.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_widgets/treeWidgets.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_window_controls.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/plot1d.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/plot2d.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/_artifact_audit.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/_ci_scheduling.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/_window_lifecycle.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/conftest.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/_wal_lineage_scenarios.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_array_record_metadata.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_database_worker_instance_binding.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_dimensions.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_inferred_planned_counts.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_integer_record_cache.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_live_acquired_point_counts.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_plot_progress.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_qcodes_cache.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_read_sql.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_read_sql_database_identity.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_readonly.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_snapshot_planned_setpoints.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_stage5c_real_qcodes.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_array_preview.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_array_record_metadata.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_database_information.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_derived_cache.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_derived_cache_ownership.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_derived_live_integration.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_derived_queries.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_derived_rendering.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_heatmap.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_live_partial_frames.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_live_protocol.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_live_queries.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_live_result_limits.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_live_service.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_live_stage4_integration.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_live_supervisor.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_live_worker_integration.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_presentation.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_read_scope.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_snapshot.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_source_identifiers.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_work_coordinator.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_work_scheduler.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_wal_lineage_subprocess.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_auxiliary_database_protection.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bounded_heatmap_means.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bounded_integer_precision.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_array_bin_ranges.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_auxiliary_safety.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_average_view_updates.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_bounded_mixed_means.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_config.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_constant_auto_recovery.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_database_refresh.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_derivative_cancellation.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_duplicate_mean_cancellation.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_fill_cancellation.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_float_average_performance.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_generator_fifo.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_generator_safety.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_heatmap_display_ranges.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_integer_mean_cancellation.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_line_display_ranges.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_longdouble_samples.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_marquee_statistics_performance.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_measurement_generator.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_measurement_lines.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_measurement_previews.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_mixed_average_performance.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_native_averaging.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_object_scan_cancellation.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_shaped_coordinate_ranges.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_snapshot_fifo.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_tiny_heatmap_bins.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_ui_cuts.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_ui_display_precision.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_ui_refresh.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_ci_scheduling.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_demo_database_safety.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_derivative_numeric_ranges.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_diagnostics.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_heatmap_cancellation_residuals.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_heatmap_float_means.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_heatmap_geometry.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_independent_heatmap_extremes.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_liveplot_database_safety.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_native_fft_mixed_coordinates.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_nonuniform_cancellation.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_package_import.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_sample_statistics_accuracy.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_shutdown_supervisor.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_testdata.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_time_stress_database_safety.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_tools.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_version_info.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_windows_ci.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_windows_shutdown_job.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_array_heatmaps.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_array_measurements.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_boolean_heatmap_missing.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_complex_heatmaps.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_complex_lines.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_coordinate_precision.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_heatmap_limits.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_nonfinite_sql_heatmaps.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_shaped_coordinate_validity.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_sidecar_identities.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/widgets/test_operations.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/widgets/test_plot_preview_reuse.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/widgets/test_preview_database_instance.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/widgets/test_preview_dragdrop.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/widgets/test_preview_extreme_range.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/widgets/test_preview_placeholders.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/widgets/test_run_details.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/widgets/test_run_list.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/widgets/test_themes.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/_trusted_derived_wal_ui.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_appearance_swap_cuts.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_axis_auto_padding_overflow.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_axis_global_auto_validation.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_axis_limit_overflow.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_axis_limit_precision.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_bounded_shutdown.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_centering_extremes.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_color_scale_locale.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_commands.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_complex_line_data.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_config_transactions.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_csv_shared_coordinates.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_cursor_precision_preference.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_cut_cursor_integration.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_database_information.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_database_worker_errors.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_derivative_scale.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_differentiation_integration.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_export_paths.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_filtered_axis_autoscale.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_font_preferences.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_free_cursor_axis_assignment.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_heatmap_appearance.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_heatmap_color_range.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_heatmap_layer_integration.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_heatmap_limit_missing_samples.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_help_menu.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_independent_cancellation_mean.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_independent_native_extremes.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_limit_integer_integration.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_live_array_dtypes.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_marquee_statistics_accuracy.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_merged_trace_metadata.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_mixed_plot_drops.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_average_cancellation.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_averaging.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_boolean_derivatives.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_fft_coordinates.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_fft_dynamic_range.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_fft_float_precision.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_fft_integer_precision.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_float_transforms.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_integer_transforms.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_transform_labels.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_transform_snapping.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_nonuniform_gradient_overflow.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_numeric_sample_preservation.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_numerical_stability.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_offset_precision_regressions.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_pending_preview_drop.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_planned_integer_array_extent.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot1d.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot1d_snap_precision.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot2d.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot2d_layers.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_actions.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_annotation.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_csv_precision.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_dialog_lifecycle.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_integration.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_overlay_integration.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_progress_ui.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_sidecar_binding.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_tiling.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_window.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_preferences.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_preferences_lifecycle.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_preferences_value_preservation.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_preview_drop_axes.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_refresh_interval_precision.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_refresh_lifecycle.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_run_csv_export_race.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_run_csv_mixed_integer_precision.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_run_duration_wal.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_settings_decoder_limits.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_svg_export_integration.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_testdata_gui.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_tiny_tick_labels.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_trusted_derived_live_counts.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_trusted_derived_qt.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_trusted_derived_wal_grid_ui.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_trusted_derived_wal_snapshot_ui.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_trusted_derived_wal_tiers_ui.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_trusted_derived_wal_ui.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_trusted_live_ui.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_unloaded_database_export.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_variable_array_records.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_visual_smoke.py +0 -0
- {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_window_controls.py +0 -0
|
@@ -2,6 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
All notable user-facing changes are recorded here.
|
|
4
4
|
|
|
5
|
+
## 1.6.1
|
|
6
|
+
|
|
7
|
+
This patch release improves live acquisition viewing and release validation.
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Restore Auto-plot in trusted live mode. Newly detected runs open automatically,
|
|
12
|
+
and enabling Auto-plot opens the newest incomplete run. Requests survive
|
|
13
|
+
selection changes and refreshes, retry while run metadata becomes available,
|
|
14
|
+
and cancel when Auto-plot is disabled, the database changes, or qPlot closes.
|
|
15
|
+
- Reduce unnecessary WAL coordination overhead that could cause deferred QCoDeS
|
|
16
|
+
writes to fail with `SQLITE_BUSY` during live viewing. Existing database
|
|
17
|
+
protections remain enforced.
|
|
18
|
+
- Display the main window title as `qPlot - <version>` without a duplicated
|
|
19
|
+
application-name suffix.
|
|
20
|
+
- Correct editable-install validation for source checkouts without generated
|
|
21
|
+
build metadata.
|
|
22
|
+
|
|
23
|
+
### Maintenance
|
|
24
|
+
|
|
25
|
+
- Release the native-reader fix as `qplotter-native==1.0.1`, installed
|
|
26
|
+
automatically by the application's updated dependency pin.
|
|
27
|
+
- Add a workflow to revalidate published releases against their original
|
|
28
|
+
artifacts, retaining each release's original native dependency pin.
|
|
29
|
+
- Update live-reader, Auto-plot, and release-validation documentation and add
|
|
30
|
+
README badges.
|
|
31
|
+
|
|
5
32
|
## 1.6.0
|
|
6
33
|
|
|
7
34
|
### Highlights ###
|
|
@@ -52,7 +52,7 @@ Linux is exercised in headless CI; Windows and macOS are supported desktop
|
|
|
52
52
|
platforms. See the [platform matrix](docs/distribution.md#supported-platforms).
|
|
53
53
|
|
|
54
54
|
The root distribution `qplotter` is pure Python. Install the compatible
|
|
55
|
-
`qplotter-native==1.0.
|
|
55
|
+
`qplotter-native==1.0.1` platform wheel with the application in editable
|
|
56
56
|
mode. After the native release is on PyPI, no separate download is needed:
|
|
57
57
|
|
|
58
58
|
```console
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: qplotter
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.1
|
|
4
4
|
Summary: PyQt-based viewer for completed and running QCoDeS database experiments
|
|
5
5
|
Author-email: Ben Wordsworth <b.wordsworth@lancaster.ac.uk>, Edward Laird <e.a.laird@lancaster.ac.uk>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -24,7 +24,7 @@ Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
|
24
24
|
Requires-Python: >=3.11
|
|
25
25
|
Description-Content-Type: text/markdown
|
|
26
26
|
License-File: LICENSE
|
|
27
|
-
Requires-Dist: qplotter-native==1.0.
|
|
27
|
+
Requires-Dist: qplotter-native==1.0.1
|
|
28
28
|
Requires-Dist: apsw==3.53.4.0
|
|
29
29
|
Requires-Dist: jsonschema>=4.23.0
|
|
30
30
|
Requires-Dist: numpy>=2.3.1
|
|
@@ -46,6 +46,11 @@ Dynamic: license-file
|
|
|
46
46
|
# QCoDeS-Plotter
|
|
47
47
|
|
|
48
48
|
[](https://github.com/lairdgrouplancaster/QCoDeS-Plotter/releases/latest)
|
|
49
|
+
[](https://github.com/lairdgrouplancaster/QCoDeS-Plotter/actions/workflows/ci.yml)
|
|
50
|
+
[](LICENSE)
|
|
51
|
+
[](#requirements)
|
|
52
|
+
[](https://pypi.org/project/qplotter/)
|
|
53
|
+
|
|
49
54
|
[](https://github.com/lairdgrouplancaster/QCoDeS-Plotter/releases)
|
|
50
55
|
|
|
51
56
|
QCoDeS-Plotter, or qPlot, is a PyQt-based data viewer for QCoDeS databases. It
|
|
@@ -129,7 +134,7 @@ Source checkouts also show the commit and
|
|
|
129
134
|
whether there are local changes. CI-built packages retain their build commit
|
|
130
135
|
and, for pull-request builds, the PR number. Packages installed without build
|
|
131
136
|
provenance still show the release number.
|
|
132
|
-
The separately built `qplotter-native==1.0.
|
|
137
|
+
The separately built `qplotter-native==1.0.1` supplies the protected
|
|
133
138
|
SQLite reader through `qplot_native`. The application's exact dependency pin
|
|
134
139
|
installs the compatible native wheel automatically. Both packages pin the same
|
|
135
140
|
APSW/SQLite runtime, preserving trusted live reading and database protections.
|
|
@@ -147,7 +152,7 @@ source builds, and release validation.
|
|
|
147
152
|
## Install
|
|
148
153
|
|
|
149
154
|
Install qPlot inside a supported Python virtual environment. This checkout
|
|
150
|
-
prepares the stable application release `1.6.
|
|
155
|
+
prepares the stable application release `1.6.1`, with native `1.0.1`.
|
|
151
156
|
The installation examples below work after publication; until then, use
|
|
152
157
|
validated local artifacts as described in [Distribution](docs/distribution.md).
|
|
153
158
|
|
|
@@ -178,9 +183,9 @@ For ordinary installation after a stable PyPI release is available:
|
|
|
178
183
|
python -m pip install --only-binary=:all: qplotter
|
|
179
184
|
```
|
|
180
185
|
|
|
181
|
-
To select version 1.6.
|
|
186
|
+
To select version 1.6.1 explicitly after publication:
|
|
182
187
|
```console
|
|
183
|
-
python -m pip install --only-binary=:all: qplotter==1.6.
|
|
188
|
+
python -m pip install --only-binary=:all: qplotter==1.6.1
|
|
184
189
|
```
|
|
185
190
|
|
|
186
191
|
Both commands install the full runtime dependency set as wheels, with no C
|
|
@@ -202,7 +207,7 @@ installing the new packages:
|
|
|
202
207
|
|
|
203
208
|
```console
|
|
204
209
|
python -m pip uninstall -y qplot qcodes-plotter qcodes-plotter-native qplotter qplotter-native
|
|
205
|
-
python -m pip install --only-binary=:all: qplotter==1.6.
|
|
210
|
+
python -m pip install --only-binary=:all: qplotter==1.6.1
|
|
206
211
|
python -m pip check
|
|
207
212
|
```
|
|
208
213
|
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# QCoDeS-Plotter
|
|
2
2
|
|
|
3
3
|
[](https://github.com/lairdgrouplancaster/QCoDeS-Plotter/releases/latest)
|
|
4
|
+
[](https://github.com/lairdgrouplancaster/QCoDeS-Plotter/actions/workflows/ci.yml)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](#requirements)
|
|
7
|
+
[](https://pypi.org/project/qplotter/)
|
|
8
|
+
|
|
4
9
|
[](https://github.com/lairdgrouplancaster/QCoDeS-Plotter/releases)
|
|
5
10
|
|
|
6
11
|
QCoDeS-Plotter, or qPlot, is a PyQt-based data viewer for QCoDeS databases. It
|
|
@@ -84,7 +89,7 @@ Source checkouts also show the commit and
|
|
|
84
89
|
whether there are local changes. CI-built packages retain their build commit
|
|
85
90
|
and, for pull-request builds, the PR number. Packages installed without build
|
|
86
91
|
provenance still show the release number.
|
|
87
|
-
The separately built `qplotter-native==1.0.
|
|
92
|
+
The separately built `qplotter-native==1.0.1` supplies the protected
|
|
88
93
|
SQLite reader through `qplot_native`. The application's exact dependency pin
|
|
89
94
|
installs the compatible native wheel automatically. Both packages pin the same
|
|
90
95
|
APSW/SQLite runtime, preserving trusted live reading and database protections.
|
|
@@ -102,7 +107,7 @@ source builds, and release validation.
|
|
|
102
107
|
## Install
|
|
103
108
|
|
|
104
109
|
Install qPlot inside a supported Python virtual environment. This checkout
|
|
105
|
-
prepares the stable application release `1.6.
|
|
110
|
+
prepares the stable application release `1.6.1`, with native `1.0.1`.
|
|
106
111
|
The installation examples below work after publication; until then, use
|
|
107
112
|
validated local artifacts as described in [Distribution](docs/distribution.md).
|
|
108
113
|
|
|
@@ -133,9 +138,9 @@ For ordinary installation after a stable PyPI release is available:
|
|
|
133
138
|
python -m pip install --only-binary=:all: qplotter
|
|
134
139
|
```
|
|
135
140
|
|
|
136
|
-
To select version 1.6.
|
|
141
|
+
To select version 1.6.1 explicitly after publication:
|
|
137
142
|
```console
|
|
138
|
-
python -m pip install --only-binary=:all: qplotter==1.6.
|
|
143
|
+
python -m pip install --only-binary=:all: qplotter==1.6.1
|
|
139
144
|
```
|
|
140
145
|
|
|
141
146
|
Both commands install the full runtime dependency set as wheels, with no C
|
|
@@ -157,7 +162,7 @@ installing the new packages:
|
|
|
157
162
|
|
|
158
163
|
```console
|
|
159
164
|
python -m pip uninstall -y qplot qcodes-plotter qcodes-plotter-native qplotter qplotter-native
|
|
160
|
-
python -m pip install --only-binary=:all: qplotter==1.6.
|
|
165
|
+
python -m pip install --only-binary=:all: qplotter==1.6.1
|
|
161
166
|
python -m pip check
|
|
162
167
|
```
|
|
163
168
|
|
|
@@ -245,8 +245,16 @@ unavailable detail state: ordinary selection starts no selected-detail worker
|
|
|
245
245
|
and prepares no additional selected-detail snapshot. A trusted detail failure
|
|
246
246
|
also does not trigger an automatic fallback copy. This is a property of the
|
|
247
247
|
selection action, not the whole fallback session: fallback metadata and retained
|
|
248
|
-
preview paths can still create private snapshots.
|
|
249
|
-
actions materialise a DataSet.
|
|
248
|
+
preview paths can still create private snapshots. Fallback plot actions
|
|
249
|
+
(including Auto-plot) and CSV actions can materialise a DataSet.
|
|
250
|
+
|
|
251
|
+
Trusted Auto-plot owns a deduplicated queue independently of selected-detail
|
|
252
|
+
and refresh requests. It submits one bounded plot-metadata request at a time,
|
|
253
|
+
then uses the same asynchronous plot pipeline as manual plotting. Unavailable
|
|
254
|
+
descriptions are operation-local failures that leave the reader session usable.
|
|
255
|
+
Retries use bounded backoff; later run-metadata changes wake exhausted requests.
|
|
256
|
+
Disabling Auto-plot, committing a database switch, closing the database, and
|
|
257
|
+
shutdown cancel the queue. Source identity checks still guard publication.
|
|
250
258
|
|
|
251
259
|
Stage 5A's `trusted_work_scheduler.py` owns the exact derived priority key
|
|
252
260
|
`(run tier, work kind, stable run index)` without materialising one task per
|
|
@@ -29,15 +29,15 @@ virtual environment with:
|
|
|
29
29
|
python -m pip install --only-binary=:all: qplotter
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
The current development target is the stable application release `1.6.
|
|
33
|
-
with exact native dependency `1.0.
|
|
32
|
+
The current development target is the stable application release `1.6.1`,
|
|
33
|
+
with exact native dependency `1.0.1`. Existing candidate tags do not establish
|
|
34
34
|
that publication succeeded. Preparing a PR does not publish either package.
|
|
35
35
|
|
|
36
|
-
The prepared stable application release is `1.6.
|
|
37
|
-
dependency `1.0.
|
|
36
|
+
The prepared stable application release is `1.6.1`, with exact native
|
|
37
|
+
dependency `1.0.1`. Once published, install that release explicitly:
|
|
38
38
|
|
|
39
39
|
```console
|
|
40
|
-
python -m pip install --only-binary=:all: qplotter==1.6.
|
|
40
|
+
python -m pip install --only-binary=:all: qplotter==1.6.1
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
The earlier `native-and-app/v1.6.0b2` candidate did not pass its complete hosted
|
|
@@ -59,7 +59,7 @@ wheel paths from this revision's validated artifacts together. For example,
|
|
|
59
59
|
on Windows x64 (replace the application version when appropriate):
|
|
60
60
|
|
|
61
61
|
```console
|
|
62
|
-
python -m pip install --only-binary=:all: dist/qplotter_native-1.0.
|
|
62
|
+
python -m pip install --only-binary=:all: dist/qplotter_native-1.0.1-cp311-abi3-win_amd64.whl dist/qplotter-1.6.1-py3-none-any.whl
|
|
63
63
|
```
|
|
64
64
|
|
|
65
65
|
Use your platform's native filename on macOS/Linux. Never mix artifacts from
|
|
@@ -91,7 +91,7 @@ application names before installing the replacement:
|
|
|
91
91
|
|
|
92
92
|
```console
|
|
93
93
|
python -m pip uninstall -y qplot qcodes-plotter qcodes-plotter-native qplotter qplotter-native
|
|
94
|
-
python -m pip install --only-binary=:all: qplotter==1.6.
|
|
94
|
+
python -m pip install --only-binary=:all: qplotter==1.6.1
|
|
95
95
|
python -m pip check
|
|
96
96
|
python -c "from importlib.metadata import packages_distributions; p = packages_distributions(); assert set(p['qplot']) == {'qplotter'}; assert set(p['qplot_native']) == {'qplotter-native'}"
|
|
97
97
|
```
|
|
@@ -221,7 +221,7 @@ wheels must build the extension from source.
|
|
|
221
221
|
|
|
222
222
|
The native wheel contains the `cp311-abi3` extension
|
|
223
223
|
`qplot_native._trusted_vfs_native` and is platform-specific. The application
|
|
224
|
-
wheel is `py3-none-any`. The application requires exactly native version 1.0.
|
|
224
|
+
wheel is `py3-none-any`. The application requires exactly native version 1.0.1;
|
|
225
225
|
both distributions pin APSW 3.53.4.0. Keep these dependencies, the validator's
|
|
226
226
|
pins, and the Python/native SQLite 3.53.4 and source-ID checks coordinated.
|
|
227
227
|
The reader also rejects an incompatible native distribution version, SQLite
|
|
@@ -399,8 +399,8 @@ application version from `pyproject.toml`:
|
|
|
399
399
|
|
|
400
400
|
| Tag | Native handling | PyPI uploads |
|
|
401
401
|
| --- | --- | --- |
|
|
402
|
-
| `native-and-app/v1.6.
|
|
403
|
-
| `v1.6.
|
|
402
|
+
| `native-and-app/v1.6.1` | Build/validate native `1.0.1` at this revision, if unpublished | Native wheels first, then application wheel/sdist |
|
|
403
|
+
| `v1.6.1` | Fetch/validate the application's exact published native pin | Application wheel/sdist only |
|
|
404
404
|
|
|
405
405
|
The workflow calls the entire CI workflow at the tagged revision. Failure of
|
|
406
406
|
any build, static check, source-distribution suite, database-protection suite,
|
|
@@ -432,9 +432,9 @@ After application publication and byte verification, `public-installations`
|
|
|
432
432
|
runs on all four platforms and every advertised CPython version (3.11–3.14).
|
|
433
433
|
Each entry creates two fresh environments outside the original checkout.
|
|
434
434
|
The ordinary path runs `python -m pip install --only-binary=:all:
|
|
435
|
-
qplotter==1.6.
|
|
435
|
+
qplotter==1.6.1` against the public PyPI index with all runtime dependencies.
|
|
436
436
|
The editable path fetches the exact tested commit into a fresh checkout and
|
|
437
|
-
installs `.[dev]` with `qplotter-native==1.0.
|
|
437
|
+
installs `.[dev]` with `qplotter-native==1.0.1` resolved from public PyPI.
|
|
438
438
|
Neither path installs a local release wheel; the validated artifacts are only
|
|
439
439
|
comparison receipts for the pip report and installed-file hashes. All runtime
|
|
440
440
|
and development dependencies must resolve to public wheels. Both paths disable
|
|
@@ -444,7 +444,10 @@ protections. Editable acceptance additionally observes a Python edit without
|
|
|
444
444
|
reinstalling and checks that the native binary's bytes, identity and timestamp
|
|
445
445
|
remain unchanged. Windows uses the standard-user wrapper for both paths.
|
|
446
446
|
Publication is irreversible; failures in these post-publication checks must
|
|
447
|
-
be reported
|
|
447
|
+
be reported. Changes to published package contents require a new release.
|
|
448
|
+
A defect confined to the validation tools can instead be corrected and the
|
|
449
|
+
existing release rechecked as described below; the failed original run remains
|
|
450
|
+
part of the release record.
|
|
448
451
|
|
|
449
452
|
### One-time account configuration
|
|
450
453
|
|
|
@@ -490,12 +493,11 @@ and [pending-publisher instructions](https://docs.pypi.org/trusted-publishers/cr
|
|
|
490
493
|
|
|
491
494
|
### Paired release commands
|
|
492
495
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
use the application-only tag `v1.6.0` instead. Never republish native 1.0.0.
|
|
496
|
+
Version 1.6.1 includes native-reader changes, so release native 1.0.1 with
|
|
497
|
+
the paired tag below. Keep the already published native 1.0.0 unchanged.
|
|
496
498
|
|
|
497
499
|
Complete the account setup and merge the reviewed packaging/release changes
|
|
498
|
-
to `main`. With application `1.6.
|
|
500
|
+
to `main`. With application `1.6.1` and native `1.0.1`, use the configured
|
|
499
501
|
Git remote/credentials:
|
|
500
502
|
|
|
501
503
|
```console
|
|
@@ -503,8 +505,8 @@ git fetch origin
|
|
|
503
505
|
git switch main
|
|
504
506
|
git pull --ff-only origin main
|
|
505
507
|
python scripts/validate_distribution.py --check-clean
|
|
506
|
-
git tag -a native-and-app/v1.6.
|
|
507
|
-
git push origin refs/tags/native-and-app/v1.6.
|
|
508
|
+
git tag -a native-and-app/v1.6.1 -m "qPlot 1.6.1 with native reader 1.0.1"
|
|
509
|
+
git push origin refs/tags/native-and-app/v1.6.1
|
|
508
510
|
```
|
|
509
511
|
|
|
510
512
|
Use the activated project venv for Python; on macOS set
|
|
@@ -545,6 +547,35 @@ the application remains blocked. Once the complete native release is verified,
|
|
|
545
547
|
an application-only tag for the still-unpublished application version can also
|
|
546
548
|
recover a failed paired release after a new validation run.
|
|
547
549
|
|
|
550
|
+
### Recheck an existing published release
|
|
551
|
+
|
|
552
|
+
If post-publication acceptance fails because of a validation-tool defect,
|
|
553
|
+
fix and review the tools, then merge them to `main`. Do not move the release
|
|
554
|
+
tag or rerun a successful publication job. In GitHub Actions, select
|
|
555
|
+
**Revalidate published qPlot release**, then **Run workflow**, using branch
|
|
556
|
+
`main`. Supply the original release tag and publication workflow run ID.
|
|
557
|
+
For the 1.6.0 resource-inventory correction these are `v1.6.0` and
|
|
558
|
+
`38429734516`.
|
|
559
|
+
|
|
560
|
+
This manual workflow uses the corrected tools from `main`, but checks out
|
|
561
|
+
the original release source separately. It checks the native package version
|
|
562
|
+
pinned by that original source while retaining the tools' supported APSW/SQLite
|
|
563
|
+
ABI checks. It downloads the `qplot-release` artifact from the original
|
|
564
|
+
publication run, verifies its tag, commit, run ID,
|
|
565
|
+
and hashes, and checks the published PyPI bytes against those receipts. The
|
|
566
|
+
artifact must still be available; a missing/expired receipt is a failed gate,
|
|
567
|
+
not permission to substitute a new build. The receipts are comparison inputs;
|
|
568
|
+
ordinary and editable dependencies are still installed from public PyPI.
|
|
569
|
+
All four platforms and CPython 3.11-3.14 run both installation paths, including
|
|
570
|
+
GUI startup and the trusted live reader/database-protection smokes. Windows
|
|
571
|
+
runs unprivileged. The workflow has only read permissions and no publishing
|
|
572
|
+
jobs or deployment approvals.
|
|
573
|
+
|
|
574
|
+
Wait for all 16 matrix jobs to pass before reporting corrected acceptance.
|
|
575
|
+
Link both the original publication run and the new validation run in the
|
|
576
|
+
release notes. If any failure requires an application or native package change,
|
|
577
|
+
use a new package version and the normal release workflow.
|
|
578
|
+
|
|
548
579
|
### Local and hosted results
|
|
549
580
|
|
|
550
581
|
Local tests and actionlint validate release configuration and failure gates.
|
|
@@ -265,8 +265,19 @@ proof handles, actual SQLite handles, source pathnames, rollback-journal absence
|
|
|
265
265
|
and active SHM bindings. Only after that succeeds may page reads reuse pathname
|
|
266
266
|
proofs until operation cleanup. Every page read still validates the retained and
|
|
267
267
|
actual handle identities and their physically read-only permissions, before and
|
|
268
|
-
after delegation.
|
|
269
|
-
full
|
|
268
|
+
after delegation. SHM mapping and newly opened or promoted WAL handles retain
|
|
269
|
+
their full checks. SHM locks and memory barriers use the binding already proved
|
|
270
|
+
by mapping and operation-boundary validation, without filesystem calls inside
|
|
271
|
+
SQLite's WAL critical sections. Unlocks are forwarded even after a latched
|
|
272
|
+
validation error, allowing SQLite to release its coordination locks on cleanup.
|
|
273
|
+
|
|
274
|
+
SQLite reads the two WAL-index header copies around `xShmBarrier`. Filesystem
|
|
275
|
+
checks in that callback widen the race with a commit and can force even a
|
|
276
|
+
read-only connection to acquire `WAL_WRITE_LOCK` to retry the header. Checks
|
|
277
|
+
after acquisition or before release then prolong that lock, causing a QCoDeS
|
|
278
|
+
deferred read-to-write upgrade to fail with `SQLITE_BUSY`. The native callbacks
|
|
279
|
+
retain the platform memory fence and real SHM locking, including legitimate
|
|
280
|
+
WAL-index recovery; they neither suppress locks nor bypass them.
|
|
270
281
|
|
|
271
282
|
Cleanup disables pathname reuse and performs full native validation before any
|
|
272
283
|
materialised result is published, including error, deadline and cancellation
|
|
@@ -279,6 +290,11 @@ transaction. Reads outside the explicit finite scope retain per-read path checks
|
|
|
279
290
|
Native audit counters include `read_path_reused`, `read_validation_ns` and
|
|
280
291
|
`read_io_ns`. The timings separate page-read validation from the delegated OS VFS
|
|
281
292
|
read, not total SQL or IPC time, and never govern safety checks or deadlines.
|
|
293
|
+
`shm_write_lock_attempts`, `shm_write_lock_acquired`, `shm_write_lock_ns` and
|
|
294
|
+
`shm_write_lock_max_ns` expose transient WAL write-lock contention. The durations
|
|
295
|
+
run from successful acquisition return through successful release return; these
|
|
296
|
+
diagnostics do not control locking. A read-only connection can legitimately
|
|
297
|
+
acquire this lock to coordinate the writable WAL index.
|
|
282
298
|
`scripts/profile_trusted_reads.py DATABASE RUN_ID` profiles finite 65,536-row
|
|
283
299
|
intervals through the pinned reader and checks protected-file sizes/timestamps.
|
|
284
300
|
It does not clear OS caches or modify the selected database. Use the actual plot
|
|
@@ -329,9 +329,14 @@ Common actions:
|
|
|
329
329
|
on macOS and `Ctrl+Q` on Windows and Linux.
|
|
330
330
|
* The refresh interval controls how often qPlot checks for new runs. Set it to
|
|
331
331
|
`0.0 s` to disable automatic checks.
|
|
332
|
-
* `Auto-plot`
|
|
333
|
-
|
|
334
|
-
|
|
332
|
+
* `Auto-plot` opens every newly detected run, including runs already complete,
|
|
333
|
+
in both trusted live and snapshot fallback sessions. Enabling it also opens
|
|
334
|
+
the newest incomplete run already listed. Trusted live requests use the
|
|
335
|
+
asynchronous reader and survive selection changes and subsequent refreshes.
|
|
336
|
+
An empty plot waits for its first data. Missing descriptions are retried with
|
|
337
|
+
backoff (eight attempts); after that, a run metadata change wakes the request,
|
|
338
|
+
or you can open it manually. Disabling Auto-plot, changing databases, or
|
|
339
|
+
quitting cancels pending automatic requests.
|
|
335
340
|
|
|
336
341
|
Where a legacy preview is available, its double-click and context-menu actions
|
|
337
342
|
can still request a plot or export. Trusted live sessions do not generate those
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "qplotter"
|
|
7
|
-
version = "1.6.
|
|
7
|
+
version = "1.6.1"
|
|
8
8
|
description = "PyQt-based viewer for completed and running QCoDeS database experiments"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{name="Ben Wordsworth", email="b.wordsworth@lancaster.ac.uk"},{name="Edward Laird", email="e.a.laird@lancaster.ac.uk"}]
|
|
@@ -27,7 +27,7 @@ classifiers = [
|
|
|
27
27
|
"Topic :: Scientific/Engineering :: Visualization",
|
|
28
28
|
]
|
|
29
29
|
dependencies = [
|
|
30
|
-
"qplotter-native==1.0.
|
|
30
|
+
"qplotter-native==1.0.1",
|
|
31
31
|
"apsw==3.53.4.0",
|
|
32
32
|
"jsonschema>=4.23.0",
|
|
33
33
|
"numpy>=2.3.1",
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Recheck an existing public release with corrected validation tools; never upload."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import re
|
|
7
|
+
import subprocess
|
|
8
|
+
import tempfile
|
|
9
|
+
import tomllib
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
if __package__:
|
|
13
|
+
from . import release
|
|
14
|
+
from . import validate_compiler_free_install as acceptance
|
|
15
|
+
else:
|
|
16
|
+
import release
|
|
17
|
+
import validate_compiler_free_install as acceptance
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def validate_installation(repository: Path, bundle: Path, *, tag: str,
|
|
21
|
+
run_id: str, platform: str, mode: str) -> None:
|
|
22
|
+
"""Use the original release's native pin with the corrected validation tools.
|
|
23
|
+
|
|
24
|
+
Publishing still requires the current pin. Only this read-only recheck
|
|
25
|
+
scopes the pin to the tagged source; the current APSW/SQLite ABI checks,
|
|
26
|
+
receipt identities, public hashes and installed-reader smokes remain intact.
|
|
27
|
+
"""
|
|
28
|
+
native = tomllib.loads((repository / 'native/pyproject.toml').read_text())['project']
|
|
29
|
+
current_pin = release.validator.PINNED_NATIVE_VERSION
|
|
30
|
+
try:
|
|
31
|
+
release.validator.PINNED_NATIVE_VERSION = native['version']
|
|
32
|
+
_validate_installation(repository, bundle, tag=tag, run_id=run_id,
|
|
33
|
+
platform=platform, mode=mode)
|
|
34
|
+
finally:
|
|
35
|
+
release.validator.PINNED_NATIVE_VERSION = current_pin
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _validate_installation(repository: Path, bundle: Path, *, tag: str,
|
|
39
|
+
run_id: str, platform: str, mode: str) -> None:
|
|
40
|
+
"""Bind original receipts to the tagged source and public package bytes."""
|
|
41
|
+
repository = repository.resolve()
|
|
42
|
+
assert mode in ('wheel', 'editable'), mode
|
|
43
|
+
assert re.fullmatch(r'[1-9][0-9]*', run_id), 'invalid original release run ID'
|
|
44
|
+
ref = f'refs/tags/{tag}'
|
|
45
|
+
release.preflight(repository, ref)
|
|
46
|
+
metadata = release.projects(repository)
|
|
47
|
+
revision = subprocess.check_output(
|
|
48
|
+
['git', '-c', f'safe.directory={repository}', 'rev-parse', 'HEAD'],
|
|
49
|
+
cwd=repository, text=True,
|
|
50
|
+
).strip()
|
|
51
|
+
identity = dict(revision=revision, ref=ref, run_id=run_id)
|
|
52
|
+
for package in ('application', 'native'):
|
|
53
|
+
receipt = release.verify_bundle(bundle / package, **identity)
|
|
54
|
+
assert receipt['package'] == release.PACKAGES[package], 'wrong receipt package'
|
|
55
|
+
assert receipt['version'] == metadata[package]['version'], 'wrong receipt version'
|
|
56
|
+
release.verify_pypi(receipt)
|
|
57
|
+
with tempfile.TemporaryDirectory(prefix=f'qplot-public-recheck-{mode}-') as name:
|
|
58
|
+
temporary = Path(name)
|
|
59
|
+
selected = temporary / 'comparison'
|
|
60
|
+
release.select_platform(bundle, platform, selected, **identity)
|
|
61
|
+
artifacts = acceptance.validator.find_artifacts([selected], wheel_only=True)
|
|
62
|
+
acceptance.accept_installation(repository, artifacts, temporary,
|
|
63
|
+
editable=mode == 'editable', public_pypi=True)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def main() -> None:
|
|
67
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
68
|
+
parser.add_argument('--repository', type=Path, required=True,
|
|
69
|
+
help='Clean checkout of the original release tag, not the validation tools')
|
|
70
|
+
parser.add_argument('--bundle', type=Path, required=True)
|
|
71
|
+
parser.add_argument('--tag', required=True)
|
|
72
|
+
parser.add_argument('--run-id', required=True, help='Original publication workflow run ID')
|
|
73
|
+
parser.add_argument('--platform', required=True, choices=release.PLATFORMS)
|
|
74
|
+
parser.add_argument('--mode', required=True, choices=('wheel', 'editable'))
|
|
75
|
+
args = parser.parse_args()
|
|
76
|
+
validate_installation(args.repository, args.bundle, tag=args.tag,
|
|
77
|
+
run_id=args.run_id, platform=args.platform, mode=args.mode)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
if __name__ == '__main__':
|
|
81
|
+
main()
|
|
@@ -382,6 +382,15 @@ def fresh_checkout(repository: Path, destination: Path) -> Path:
|
|
|
382
382
|
return destination
|
|
383
383
|
|
|
384
384
|
|
|
385
|
+
def smoke_runtime_files(runtime: set[str], *, editable_source: Path | None) -> set[str]:
|
|
386
|
+
"""Keep required resources, allowing unstamped editable Git checkouts."""
|
|
387
|
+
if editable_source is not None and not (editable_source / 'src/qplot/_build_info.json').is_file():
|
|
388
|
+
# Release wheels and extracted sdists carry generated provenance.
|
|
389
|
+
# A fresh Git checkout instead reports provenance from Git at runtime.
|
|
390
|
+
return runtime - {'qplot/_build_info.json'}
|
|
391
|
+
return set(runtime)
|
|
392
|
+
|
|
393
|
+
|
|
385
394
|
def accept_installation(repository: Path, artifacts: dict[str, Path],
|
|
386
395
|
temporary: Path, *, editable: bool, public_pypi: bool = False) -> None:
|
|
387
396
|
assert not temporary.resolve().is_relative_to(repository.resolve())
|
|
@@ -444,7 +453,8 @@ else:
|
|
|
444
453
|
if editable:
|
|
445
454
|
prove_editable_edit(python, app, temporary, audit, env)
|
|
446
455
|
start_qplot(environment, temporary, env)
|
|
447
|
-
|
|
456
|
+
smoke_runtime = smoke_runtime_files(runtime, editable_source=app if editable else None)
|
|
457
|
+
validator.smoke_test_installation(repository, app_wheel, native, smoke_runtime,
|
|
448
458
|
temporary, environment, audit_code=audit, env=env)
|
|
449
459
|
validator.run([str(python), '-I', str(native_probe)], cwd=temporary, env=env)
|
|
450
460
|
assert_no_compiler_builds(log, baseline)
|
|
@@ -50,7 +50,7 @@ NATIVE_EXTENSION_MEMBERS = {
|
|
|
50
50
|
f"{NATIVE_EXTENSION_STEM}.pyd",
|
|
51
51
|
}
|
|
52
52
|
PINNED_APSW_VERSION = "3.53.4.0"
|
|
53
|
-
PINNED_NATIVE_VERSION = "1.0.
|
|
53
|
+
PINNED_NATIVE_VERSION = "1.0.1"
|
|
54
54
|
CONSOLE_SCRIPTS = {
|
|
55
55
|
"qplot": "qplot.__main__:run",
|
|
56
56
|
"qplot-cfg": "qplot.configuration.scripts:scripts",
|
|
@@ -62,7 +62,8 @@ def _configure_application_identity(app):
|
|
|
62
62
|
"""
|
|
63
63
|
app.setApplicationName("qPlot")
|
|
64
64
|
if hasattr(app, "setApplicationDisplayName"):
|
|
65
|
-
|
|
65
|
+
# Window titles already identify qPlot; suppress Qt's automatic suffix.
|
|
66
|
+
app.setApplicationDisplayName("")
|
|
66
67
|
|
|
67
68
|
|
|
68
69
|
def _finalize_confirmed_process_shutdown(
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version": "1.6.1", "commit": "2ae041507af8edbcd89ddfcb750b0e97917aa98d", "dirty": false, "released": true}
|
|
@@ -39,7 +39,7 @@ from qplot.datahandling.file_identity import (
|
|
|
39
39
|
)
|
|
40
40
|
|
|
41
41
|
TRUSTED_READER_APSW_VERSION = "3.53.4.0"
|
|
42
|
-
TRUSTED_READER_NATIVE_VERSION = "1.0.
|
|
42
|
+
TRUSTED_READER_NATIVE_VERSION = "1.0.1"
|
|
43
43
|
TRUSTED_READER_SQLITE_VERSION = "3.53.4"
|
|
44
44
|
TRUSTED_READER_SQLITE_SOURCE_ID = (
|
|
45
45
|
"2026-07-24 19:02:57 "
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Plot data captured through the application's trusted broker.
|
|
2
2
|
|
|
3
3
|
Only a run's result table is staged, never database pages or unrelated runs.
|
|
4
4
|
The private spool lets the existing precision-preserving QCoDeS decoder and
|
|
@@ -24,6 +24,14 @@ RECORD_PROGRESS_UNITS = 1_000_000
|
|
|
24
24
|
MAX_PARAMETERS = 256
|
|
25
25
|
|
|
26
26
|
|
|
27
|
+
class PlotMetadataUnavailableError(TrustedLiveQueryError):
|
|
28
|
+
"""Run creation/start has not yet published a usable plot description.
|
|
29
|
+
|
|
30
|
+
This is an operation-local data condition, not a fatal reader failure.
|
|
31
|
+
The broker session must remain usable for other runs and later attempts.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
|
|
27
35
|
def identifier(name):
|
|
28
36
|
return '"' + str(name).replace('"', '""') + '"'
|
|
29
37
|
|
|
@@ -46,10 +54,17 @@ class TrustedPlotDataset:
|
|
|
46
54
|
self.service = service
|
|
47
55
|
self.path_to_db = service.database_instance.logical_path
|
|
48
56
|
self.description_json = description
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
if not description:
|
|
58
|
+
raise PlotMetadataUnavailableError("The run description is not available yet.")
|
|
59
|
+
try:
|
|
60
|
+
self.description = from_json_to_current(description)
|
|
61
|
+
self._parameters = list(new_to_old(self.description.interdeps).paramspecs)
|
|
62
|
+
except (ValueError, TypeError, KeyError) as error:
|
|
63
|
+
raise PlotMetadataUnavailableError("The run description is not usable yet.") from error
|
|
64
|
+
if not self._parameters:
|
|
65
|
+
raise PlotMetadataUnavailableError("The run has no plot parameters yet.")
|
|
66
|
+
if len(self._parameters) > MAX_PARAMETERS:
|
|
67
|
+
raise TrustedLiveQueryError("Plot parameter count exceeds the supported bound.")
|
|
53
68
|
self._completed = bool(completed)
|
|
54
69
|
self.number_of_results = 0
|
|
55
70
|
# Only qPlot's cache accessors are used; no DataSet database methods.
|
|
@@ -80,7 +95,7 @@ def plot_dataset(executor, service, guid):
|
|
|
80
95
|
"WHERE r.guid=? LIMIT 2", (guid,),
|
|
81
96
|
).rows
|
|
82
97
|
if len(rows) != 1:
|
|
83
|
-
raise
|
|
98
|
+
raise TrustedLiveQueryError("The requested plot GUID does not identify one run.")
|
|
84
99
|
return TrustedPlotDataset(service, rows[0])
|
|
85
100
|
|
|
86
101
|
|