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.
Files changed (376) hide show
  1. {qplotter-1.6.0 → qplotter-1.6.1}/CHANGELOG.md +27 -0
  2. {qplotter-1.6.0 → qplotter-1.6.1}/CONTRIBUTING.md +1 -1
  3. {qplotter-1.6.0 → qplotter-1.6.1}/MANIFEST.in +1 -0
  4. {qplotter-1.6.0 → qplotter-1.6.1}/PKG-INFO +12 -7
  5. {qplotter-1.6.0 → qplotter-1.6.1}/README.md +10 -5
  6. {qplotter-1.6.0 → qplotter-1.6.1}/docs/architecture.md +10 -2
  7. {qplotter-1.6.0 → qplotter-1.6.1}/docs/distribution.md +50 -19
  8. {qplotter-1.6.0 → qplotter-1.6.1}/docs/trusted-live-reader.md +18 -2
  9. {qplotter-1.6.0 → qplotter-1.6.1}/docs/user-guide.md +8 -3
  10. {qplotter-1.6.0 → qplotter-1.6.1}/pyproject.toml +2 -2
  11. qplotter-1.6.1/scripts/revalidate_published_release.py +81 -0
  12. {qplotter-1.6.0 → qplotter-1.6.1}/scripts/validate_compiler_free_install.py +11 -1
  13. {qplotter-1.6.0 → qplotter-1.6.1}/scripts/validate_distribution.py +1 -1
  14. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/__main__.py +2 -1
  15. qplotter-1.6.1/src/qplot/_build_info.json +1 -0
  16. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_live.py +1 -1
  17. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_plot.py +21 -6
  18. qplotter-1.6.1/src/qplot/windows/_auto_plot.py +201 -0
  19. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_database_actions.py +7 -6
  20. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_actions.py +15 -13
  21. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_run_controls.py +4 -6
  22. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_trusted_derived_qt.py +4 -0
  23. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/main.py +3 -1
  24. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplotter.egg-info/SOURCES.txt +4 -0
  25. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_live.py +4 -0
  26. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_plot.py +36 -0
  27. qplotter-1.6.1/tests/datahandling/test_trusted_wal_contention.py +214 -0
  28. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_ci_artifacts.py +12 -0
  29. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_compiler_free_install.py +16 -1
  30. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_config.py +1 -1
  31. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_distribution_validator.py +4 -3
  32. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_packaging_split.py +1 -1
  33. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_release.py +68 -3
  34. qplotter-1.6.1/tests/windows/test_auto_plot.py +203 -0
  35. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_main_window.py +6 -4
  36. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_trusted_plot_launch.py +237 -1
  37. qplotter-1.6.0/src/qplot/_build_info.json +0 -1
  38. {qplotter-1.6.0 → qplotter-1.6.1}/Agents.md +0 -0
  39. {qplotter-1.6.0 → qplotter-1.6.1}/LICENSE +0 -0
  40. {qplotter-1.6.0 → qplotter-1.6.1}/docs/assets/qplot-color-scale-dialog.png +0 -0
  41. {qplotter-1.6.0 → qplotter-1.6.1}/docs/assets/qplot-heatmap.png +0 -0
  42. {qplotter-1.6.0 → qplotter-1.6.1}/docs/assets/qplot-line-plot.png +0 -0
  43. {qplotter-1.6.0 → qplotter-1.6.1}/docs/assets/qplot-main-window.png +0 -0
  44. {qplotter-1.6.0 → qplotter-1.6.1}/docs/configuration.md +0 -0
  45. {qplotter-1.6.0 → qplotter-1.6.1}/docs/demo-data.md +0 -0
  46. {qplotter-1.6.0 → qplotter-1.6.1}/docs/troubleshooting.md +0 -0
  47. {qplotter-1.6.0 → qplotter-1.6.1}/scripts/README.md +0 -0
  48. {qplotter-1.6.0 → qplotter-1.6.1}/scripts/benchmark_heatmap_aggregation.py +0 -0
  49. {qplotter-1.6.0 → qplotter-1.6.1}/scripts/benchmark_plot_launch.py +0 -0
  50. {qplotter-1.6.0 → qplotter-1.6.1}/scripts/capture_demo_screenshots.py +0 -0
  51. {qplotter-1.6.0 → qplotter-1.6.1}/scripts/liveplot.py +0 -0
  52. {qplotter-1.6.0 → qplotter-1.6.1}/scripts/manual_run.py +0 -0
  53. {qplotter-1.6.0 → qplotter-1.6.1}/scripts/profile_trusted_reads.py +0 -0
  54. {qplotter-1.6.0 → qplotter-1.6.1}/scripts/release.py +0 -0
  55. {qplotter-1.6.0 → qplotter-1.6.1}/scripts/time_stress.py +0 -0
  56. {qplotter-1.6.0 → qplotter-1.6.1}/scripts/write_build_info.py +0 -0
  57. {qplotter-1.6.0 → qplotter-1.6.1}/setup.cfg +0 -0
  58. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/__init__.py +0 -0
  59. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/_auxiliary_paths.py +0 -0
  60. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/_metadata.py +0 -0
  61. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/_repair.py +0 -0
  62. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/_shutdown_supervisor.py +0 -0
  63. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/_version.py +0 -0
  64. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/_windows_shutdown_job.py +0 -0
  65. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/__init__.py +0 -0
  66. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/config.py +0 -0
  67. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/config_schema.json +0 -0
  68. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/fonts.py +0 -0
  69. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/scripts.py +0 -0
  70. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/themes/__init__.py +0 -0
  71. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/themes/_base.py +0 -0
  72. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/themes/blank.py +0 -0
  73. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/themes/dark.py +0 -0
  74. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/configuration/themes/light.py +0 -0
  75. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/LoadFromDB.py +0 -0
  76. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/__init__.py +0 -0
  77. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/_trusted_live_helper.py +0 -0
  78. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/_trusted_live_protocol.py +0 -0
  79. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/database.py +0 -0
  80. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/dimensions.py +0 -0
  81. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/file_identity.py +0 -0
  82. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/parameter_data.py +0 -0
  83. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/plot_progress.py +0 -0
  84. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/qcodes_cache.py +0 -0
  85. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/qcodes_compat.py +0 -0
  86. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/readSQL.py +0 -0
  87. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/readonly.py +0 -0
  88. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/source_activity.py +0 -0
  89. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_array_preview.py +0 -0
  90. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_derived_cache.py +0 -0
  91. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_derived_rendering.py +0 -0
  92. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_heatmap.py +0 -0
  93. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_live_queries.py +0 -0
  94. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_live_service.py +0 -0
  95. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_live_supervisor.py +0 -0
  96. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_presentation.py +0 -0
  97. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_snapshot.py +0 -0
  98. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_work_coordinator.py +0 -0
  99. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/datahandling/trusted_work_scheduler.py +0 -0
  100. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/diagnostics.py +0 -0
  101. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_01_10mb.csv +0 -0
  102. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_02_25mb.csv +0 -0
  103. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_03_50mb.csv +0 -0
  104. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_04_100mb.csv +0 -0
  105. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_05_250mb.csv +0 -0
  106. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_06_500mb.csv +0 -0
  107. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_07_1gb.csv +0 -0
  108. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_08_5gb.csv +0 -0
  109. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_09_10gb.csv +0 -0
  110. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/resources/testdata/qplot_test_db_10_30gb.csv +0 -0
  111. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/testdata.py +0 -0
  112. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/tools/__init__.py +0 -0
  113. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/tools/finite_means.py +0 -0
  114. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/tools/general.py +0 -0
  115. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/tools/heatmap_geometry.py +0 -0
  116. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/tools/operation_registry.py +0 -0
  117. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/tools/plot_tools.py +0 -0
  118. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/tools/sample_statistics.py +0 -0
  119. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/tools/worker.py +0 -0
  120. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/__init__.py +0 -0
  121. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_colorbar.py +0 -0
  122. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_commands.py +0 -0
  123. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_config_persistence.py +0 -0
  124. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_dataset_handle.py +0 -0
  125. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_display_precision.py +0 -0
  126. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_dragdrop.py +0 -0
  127. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_export_paths.py +0 -0
  128. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_help.py +0 -0
  129. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_mixed_appearance.py +0 -0
  130. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_mixed_plots.py +0 -0
  131. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_native_averaging.py +0 -0
  132. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_native_transforms.py +0 -0
  133. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot1d_snap.py +0 -0
  134. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot1d_traces.py +0 -0
  135. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot2d_colorbar.py +0 -0
  136. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot2d_colorbar_dialog.py +0 -0
  137. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot2d_layers.py +0 -0
  138. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot2d_sweeps.py +0 -0
  139. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plotWin.py +0 -0
  140. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_annotation.py +0 -0
  141. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_appearance.py +0 -0
  142. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_axis_scaling.py +0 -0
  143. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_data_viewbox.py +0 -0
  144. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_drop_axes.py +0 -0
  145. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_export.py +0 -0
  146. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_feedback.py +0 -0
  147. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_marquee.py +0 -0
  148. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_refresh.py +0 -0
  149. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_source_promotion.py +0 -0
  150. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_state.py +0 -0
  151. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_status.py +0 -0
  152. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_tiling.py +0 -0
  153. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_plot_transform_labels.py +0 -0
  154. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_preferences.py +0 -0
  155. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_refresh_interval.py +0 -0
  156. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_shortcuts.py +0 -0
  157. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_subplots/__init__.py +0 -0
  158. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_subplots/subplot1d.py +0 -0
  159. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_subplots/subplot2d.py +0 -0
  160. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_svg_export.py +0 -0
  161. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_widgets/__init__.py +0 -0
  162. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_widgets/_run_formatting.py +0 -0
  163. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_widgets/details_tables.py +0 -0
  164. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_widgets/dropbox.py +0 -0
  165. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_widgets/operations.py +0 -0
  166. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_widgets/preview.py +0 -0
  167. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_widgets/run_list_items.py +0 -0
  168. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_widgets/toolbar.py +0 -0
  169. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_widgets/treeWidgets.py +0 -0
  170. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/_window_controls.py +0 -0
  171. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/plot1d.py +0 -0
  172. {qplotter-1.6.0 → qplotter-1.6.1}/src/qplot/windows/plot2d.py +0 -0
  173. {qplotter-1.6.0 → qplotter-1.6.1}/tests/_artifact_audit.py +0 -0
  174. {qplotter-1.6.0 → qplotter-1.6.1}/tests/_ci_scheduling.py +0 -0
  175. {qplotter-1.6.0 → qplotter-1.6.1}/tests/_window_lifecycle.py +0 -0
  176. {qplotter-1.6.0 → qplotter-1.6.1}/tests/conftest.py +0 -0
  177. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/_wal_lineage_scenarios.py +0 -0
  178. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_array_record_metadata.py +0 -0
  179. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_database_worker_instance_binding.py +0 -0
  180. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_dimensions.py +0 -0
  181. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_inferred_planned_counts.py +0 -0
  182. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_integer_record_cache.py +0 -0
  183. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_live_acquired_point_counts.py +0 -0
  184. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_plot_progress.py +0 -0
  185. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_qcodes_cache.py +0 -0
  186. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_read_sql.py +0 -0
  187. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_read_sql_database_identity.py +0 -0
  188. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_readonly.py +0 -0
  189. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_snapshot_planned_setpoints.py +0 -0
  190. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_stage5c_real_qcodes.py +0 -0
  191. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_array_preview.py +0 -0
  192. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_array_record_metadata.py +0 -0
  193. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_database_information.py +0 -0
  194. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_derived_cache.py +0 -0
  195. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_derived_cache_ownership.py +0 -0
  196. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_derived_live_integration.py +0 -0
  197. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_derived_queries.py +0 -0
  198. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_derived_rendering.py +0 -0
  199. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_heatmap.py +0 -0
  200. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_live_partial_frames.py +0 -0
  201. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_live_protocol.py +0 -0
  202. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_live_queries.py +0 -0
  203. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_live_result_limits.py +0 -0
  204. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_live_service.py +0 -0
  205. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_live_stage4_integration.py +0 -0
  206. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_live_supervisor.py +0 -0
  207. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_live_worker_integration.py +0 -0
  208. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_presentation.py +0 -0
  209. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_read_scope.py +0 -0
  210. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_snapshot.py +0 -0
  211. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_source_identifiers.py +0 -0
  212. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_work_coordinator.py +0 -0
  213. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_trusted_work_scheduler.py +0 -0
  214. {qplotter-1.6.0 → qplotter-1.6.1}/tests/datahandling/test_wal_lineage_subprocess.py +0 -0
  215. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_auxiliary_database_protection.py +0 -0
  216. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bounded_heatmap_means.py +0 -0
  217. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bounded_integer_precision.py +0 -0
  218. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_array_bin_ranges.py +0 -0
  219. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_auxiliary_safety.py +0 -0
  220. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_average_view_updates.py +0 -0
  221. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_bounded_mixed_means.py +0 -0
  222. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_config.py +0 -0
  223. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_constant_auto_recovery.py +0 -0
  224. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_database_refresh.py +0 -0
  225. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_derivative_cancellation.py +0 -0
  226. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_duplicate_mean_cancellation.py +0 -0
  227. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_fill_cancellation.py +0 -0
  228. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_float_average_performance.py +0 -0
  229. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_generator_fifo.py +0 -0
  230. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_generator_safety.py +0 -0
  231. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_heatmap_display_ranges.py +0 -0
  232. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_integer_mean_cancellation.py +0 -0
  233. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_line_display_ranges.py +0 -0
  234. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_longdouble_samples.py +0 -0
  235. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_marquee_statistics_performance.py +0 -0
  236. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_measurement_generator.py +0 -0
  237. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_measurement_lines.py +0 -0
  238. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_measurement_previews.py +0 -0
  239. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_mixed_average_performance.py +0 -0
  240. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_native_averaging.py +0 -0
  241. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_object_scan_cancellation.py +0 -0
  242. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_shaped_coordinate_ranges.py +0 -0
  243. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_snapshot_fifo.py +0 -0
  244. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_tiny_heatmap_bins.py +0 -0
  245. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_ui_cuts.py +0 -0
  246. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_ui_display_precision.py +0 -0
  247. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_bug_hunt_ui_refresh.py +0 -0
  248. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_ci_scheduling.py +0 -0
  249. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_demo_database_safety.py +0 -0
  250. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_derivative_numeric_ranges.py +0 -0
  251. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_diagnostics.py +0 -0
  252. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_heatmap_cancellation_residuals.py +0 -0
  253. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_heatmap_float_means.py +0 -0
  254. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_heatmap_geometry.py +0 -0
  255. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_independent_heatmap_extremes.py +0 -0
  256. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_liveplot_database_safety.py +0 -0
  257. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_native_fft_mixed_coordinates.py +0 -0
  258. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_nonuniform_cancellation.py +0 -0
  259. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_package_import.py +0 -0
  260. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_sample_statistics_accuracy.py +0 -0
  261. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_shutdown_supervisor.py +0 -0
  262. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_testdata.py +0 -0
  263. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_time_stress_database_safety.py +0 -0
  264. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_tools.py +0 -0
  265. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_version_info.py +0 -0
  266. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_windows_ci.py +0 -0
  267. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_windows_shutdown_job.py +0 -0
  268. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_array_heatmaps.py +0 -0
  269. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_array_measurements.py +0 -0
  270. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_boolean_heatmap_missing.py +0 -0
  271. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_complex_heatmaps.py +0 -0
  272. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_complex_lines.py +0 -0
  273. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_coordinate_precision.py +0 -0
  274. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_heatmap_limits.py +0 -0
  275. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_nonfinite_sql_heatmaps.py +0 -0
  276. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_shaped_coordinate_validity.py +0 -0
  277. {qplotter-1.6.0 → qplotter-1.6.1}/tests/test_worker_sidecar_identities.py +0 -0
  278. {qplotter-1.6.0 → qplotter-1.6.1}/tests/widgets/test_operations.py +0 -0
  279. {qplotter-1.6.0 → qplotter-1.6.1}/tests/widgets/test_plot_preview_reuse.py +0 -0
  280. {qplotter-1.6.0 → qplotter-1.6.1}/tests/widgets/test_preview_database_instance.py +0 -0
  281. {qplotter-1.6.0 → qplotter-1.6.1}/tests/widgets/test_preview_dragdrop.py +0 -0
  282. {qplotter-1.6.0 → qplotter-1.6.1}/tests/widgets/test_preview_extreme_range.py +0 -0
  283. {qplotter-1.6.0 → qplotter-1.6.1}/tests/widgets/test_preview_placeholders.py +0 -0
  284. {qplotter-1.6.0 → qplotter-1.6.1}/tests/widgets/test_run_details.py +0 -0
  285. {qplotter-1.6.0 → qplotter-1.6.1}/tests/widgets/test_run_list.py +0 -0
  286. {qplotter-1.6.0 → qplotter-1.6.1}/tests/widgets/test_themes.py +0 -0
  287. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/_trusted_derived_wal_ui.py +0 -0
  288. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_appearance_swap_cuts.py +0 -0
  289. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_axis_auto_padding_overflow.py +0 -0
  290. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_axis_global_auto_validation.py +0 -0
  291. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_axis_limit_overflow.py +0 -0
  292. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_axis_limit_precision.py +0 -0
  293. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_bounded_shutdown.py +0 -0
  294. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_centering_extremes.py +0 -0
  295. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_color_scale_locale.py +0 -0
  296. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_commands.py +0 -0
  297. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_complex_line_data.py +0 -0
  298. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_config_transactions.py +0 -0
  299. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_csv_shared_coordinates.py +0 -0
  300. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_cursor_precision_preference.py +0 -0
  301. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_cut_cursor_integration.py +0 -0
  302. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_database_information.py +0 -0
  303. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_database_worker_errors.py +0 -0
  304. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_derivative_scale.py +0 -0
  305. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_differentiation_integration.py +0 -0
  306. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_export_paths.py +0 -0
  307. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_filtered_axis_autoscale.py +0 -0
  308. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_font_preferences.py +0 -0
  309. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_free_cursor_axis_assignment.py +0 -0
  310. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_heatmap_appearance.py +0 -0
  311. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_heatmap_color_range.py +0 -0
  312. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_heatmap_layer_integration.py +0 -0
  313. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_heatmap_limit_missing_samples.py +0 -0
  314. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_help_menu.py +0 -0
  315. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_independent_cancellation_mean.py +0 -0
  316. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_independent_native_extremes.py +0 -0
  317. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_limit_integer_integration.py +0 -0
  318. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_live_array_dtypes.py +0 -0
  319. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_marquee_statistics_accuracy.py +0 -0
  320. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_merged_trace_metadata.py +0 -0
  321. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_mixed_plot_drops.py +0 -0
  322. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_average_cancellation.py +0 -0
  323. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_averaging.py +0 -0
  324. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_boolean_derivatives.py +0 -0
  325. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_fft_coordinates.py +0 -0
  326. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_fft_dynamic_range.py +0 -0
  327. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_fft_float_precision.py +0 -0
  328. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_fft_integer_precision.py +0 -0
  329. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_float_transforms.py +0 -0
  330. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_integer_transforms.py +0 -0
  331. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_transform_labels.py +0 -0
  332. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_native_transform_snapping.py +0 -0
  333. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_nonuniform_gradient_overflow.py +0 -0
  334. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_numeric_sample_preservation.py +0 -0
  335. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_numerical_stability.py +0 -0
  336. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_offset_precision_regressions.py +0 -0
  337. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_pending_preview_drop.py +0 -0
  338. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_planned_integer_array_extent.py +0 -0
  339. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot1d.py +0 -0
  340. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot1d_snap_precision.py +0 -0
  341. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot2d.py +0 -0
  342. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot2d_layers.py +0 -0
  343. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_actions.py +0 -0
  344. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_annotation.py +0 -0
  345. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_csv_precision.py +0 -0
  346. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_dialog_lifecycle.py +0 -0
  347. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_integration.py +0 -0
  348. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_overlay_integration.py +0 -0
  349. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_progress_ui.py +0 -0
  350. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_sidecar_binding.py +0 -0
  351. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_tiling.py +0 -0
  352. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_plot_window.py +0 -0
  353. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_preferences.py +0 -0
  354. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_preferences_lifecycle.py +0 -0
  355. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_preferences_value_preservation.py +0 -0
  356. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_preview_drop_axes.py +0 -0
  357. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_refresh_interval_precision.py +0 -0
  358. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_refresh_lifecycle.py +0 -0
  359. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_run_csv_export_race.py +0 -0
  360. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_run_csv_mixed_integer_precision.py +0 -0
  361. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_run_duration_wal.py +0 -0
  362. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_settings_decoder_limits.py +0 -0
  363. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_svg_export_integration.py +0 -0
  364. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_testdata_gui.py +0 -0
  365. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_tiny_tick_labels.py +0 -0
  366. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_trusted_derived_live_counts.py +0 -0
  367. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_trusted_derived_qt.py +0 -0
  368. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_trusted_derived_wal_grid_ui.py +0 -0
  369. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_trusted_derived_wal_snapshot_ui.py +0 -0
  370. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_trusted_derived_wal_tiers_ui.py +0 -0
  371. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_trusted_derived_wal_ui.py +0 -0
  372. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_trusted_live_ui.py +0 -0
  373. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_unloaded_database_export.py +0 -0
  374. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_variable_array_records.py +0 -0
  375. {qplotter-1.6.0 → qplotter-1.6.1}/tests/windows/test_visual_smoke.py +0 -0
  376. {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.0` platform wheel with the application in editable
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
@@ -27,6 +27,7 @@ prune src/qplotter.egg-info
27
27
 
28
28
  global-exclude .DS_Store
29
29
  global-exclude *.py[cod]
30
+ global-exclude *.py[cod].*
30
31
  global-exclude *.dll
31
32
  global-exclude *.dylib
32
33
  global-exclude *.pyd
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qplotter
3
- Version: 1.6.0
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.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
  [![release](https://img.shields.io/github/v/release/lairdgrouplancaster/QCoDeS-Plotter?label=release)](https://github.com/lairdgrouplancaster/QCoDeS-Plotter/releases/latest)
49
+ [![CI](https://github.com/lairdgrouplancaster/QCoDeS-Plotter/actions/workflows/ci.yml/badge.svg?branch=main&event=push)](https://github.com/lairdgrouplancaster/QCoDeS-Plotter/actions/workflows/ci.yml)
50
+ [![License](https://img.shields.io/github/license/lairdgrouplancaster/QCoDeS-Plotter)](LICENSE)
51
+ [![Python](https://img.shields.io/badge/Python-3.11–3.14-blue?logo=python)](#requirements)
52
+ [![PyPI](https://img.shields.io/pypi/v/qplotter)](https://pypi.org/project/qplotter/)
53
+
49
54
  [![pre-release](https://img.shields.io/github/v/release/lairdgrouplancaster/QCoDeS-Plotter?include_prereleases&label=pre-release&sort=semver)](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.0` supplies the protected
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.0`, with native `1.0.0`.
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.0 explicitly after publication:
186
+ To select version 1.6.1 explicitly after publication:
182
187
  ```console
183
- python -m pip install --only-binary=:all: qplotter==1.6.0
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.0
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
  [![release](https://img.shields.io/github/v/release/lairdgrouplancaster/QCoDeS-Plotter?label=release)](https://github.com/lairdgrouplancaster/QCoDeS-Plotter/releases/latest)
4
+ [![CI](https://github.com/lairdgrouplancaster/QCoDeS-Plotter/actions/workflows/ci.yml/badge.svg?branch=main&event=push)](https://github.com/lairdgrouplancaster/QCoDeS-Plotter/actions/workflows/ci.yml)
5
+ [![License](https://img.shields.io/github/license/lairdgrouplancaster/QCoDeS-Plotter)](LICENSE)
6
+ [![Python](https://img.shields.io/badge/Python-3.11–3.14-blue?logo=python)](#requirements)
7
+ [![PyPI](https://img.shields.io/pypi/v/qplotter)](https://pypi.org/project/qplotter/)
8
+
4
9
  [![pre-release](https://img.shields.io/github/v/release/lairdgrouplancaster/QCoDeS-Plotter?include_prereleases&label=pre-release&sort=semver)](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.0` supplies the protected
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.0`, with native `1.0.0`.
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.0 explicitly after publication:
141
+ To select version 1.6.1 explicitly after publication:
137
142
  ```console
138
- python -m pip install --only-binary=:all: qplotter==1.6.0
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.0
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. Only explicit plot and CSV
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.0`,
33
- with exact native dependency `1.0.0`. Existing candidate tags do not establish
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.0`, with exact native
37
- dependency `1.0.0`. Once published, install that release explicitly:
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.0
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.0-cp311-abi3-win_amd64.whl dist/qplotter-1.6.0-py3-none-any.whl
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.0
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.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.0` | Build/validate native `1.0.0` at this revision, if unpublished | Native wheels first, then application wheel/sdist |
403
- | `v1.6.0` | Fetch/validate the application's exact published native pin | Application wheel/sdist only |
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.0` against the public PyPI index with all runtime dependencies.
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.0` resolved from public PyPI.
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 and fixed in a new release, rather than described as acceptance.
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
- For 1.6.0, use the paired tag below only if native 1.0.0 still needs
494
- publication. If that exact native version is already published and validated,
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.0` and native `1.0.0`, use the configured
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.0 -m "qPlot 1.6.0 with native reader 1.0.0"
507
- git push origin refs/tags/native-and-app/v1.6.0
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. Other callbacks, including SHM mapping/locking, retain their
269
- full existing checks. Newly opened or promoted WAL handles are fully validated.
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` retains its existing behavior for snapshot fallback sessions.
333
- Trusted live Stage 4 does not materialise an action-owned plot dataset
334
- automatically; use an explicit plot action instead.
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.0"
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.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
- validator.smoke_test_installation(repository, app_wheel, native, runtime,
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.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
- app.setApplicationDisplayName("qPlot")
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.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
- """Explicit plot data captured through the application's trusted broker.
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
- self.description = from_json_to_current(description)
50
- self._parameters = list(new_to_old(self.description.interdeps).paramspecs)
51
- if not 0 < len(self._parameters) <= MAX_PARAMETERS:
52
- raise ValueError("Plot parameter count exceeds the supported bound.")
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 ValueError("The requested plot GUID does not identify one run.")
98
+ raise TrustedLiveQueryError("The requested plot GUID does not identify one run.")
84
99
  return TrustedPlotDataset(service, rows[0])
85
100
 
86
101