migrate pyqt5 to pyside6

This commit is contained in:
ykcheungab
2026-09-21 09:34:56 +08:00
parent e276b5de0f
commit ccedb9ddd9
66 changed files with 2184 additions and 395 deletions
+124 -7
View File
@@ -17,6 +17,7 @@ import pytest
from conftest import pump
from orisys_autocal.sequence_io import SequenceFormatError, SequencePoint
from orisys_autocal.ui.workspace import TABS
@@ -187,13 +188,7 @@ def test_every_pending_control_names_the_phase_that_owns_it(make_window):
"""A disabled control must say why, or it reads as a broken button."""
window = _show(make_window())
panel = window.sequence_panel
assert panel.pending_controls() == [
"generate",
"simulate",
"dry_run",
"save",
"load",
]
assert panel.pending_controls() == ["generate", "simulate", "dry_run"]
for name, phase in panel.pending_phases().items():
button = panel._pending_buttons[name]
assert not button.isEnabled(), f"{name} is usable but not implemented"
@@ -201,6 +196,24 @@ def test_every_pending_control_names_the_phase_that_owns_it(make_window):
assert button.text(), f"{name} has no label"
def test_import_and_export_are_live_controls(make_window):
"""A sequence is a document, and P8 says it is a versioned artifact."""
window = _show(make_window())
panel = window.sequence_panel
for name in ("export", "import"):
button = panel._live_buttons[name]
assert button.isEnabled(), f"{name} is not usable"
assert button.text(), f"{name} has no label"
assert button.toolTip()
def test_the_point_list_has_no_empty_action_column(make_window):
"""An empty action cell reads as a broken control."""
window = _show(make_window())
panel = window.sequence_panel
assert "actions" not in panel.column_keys()
def test_the_sequence_tab_hands_out_no_runnable_steps(make_window):
"""A runner must not be able to start from points nothing has validated."""
window = _show(make_window())
@@ -456,6 +469,110 @@ def test_the_status_bar_uses_its_own_theme_token(make_window):
assert "QStatusBar" in window.statusBar().styleSheet()
def test_the_sequence_summary_reports_count_and_span(make_window):
"""The two numbers an operator reasons with, before anything runs."""
window = _show(make_window())
panel = window.sequence_panel
panel.set_points(
[
SequencePoint(id=1, target_mm={"x": 0.0, "y": 0.0, "z": 12.4}),
SequencePoint(id=2, target_mm={"x": 10.0, "y": 0.0, "z": 12.4}),
]
)
text = panel.summary_label.text()
assert "2" in text
# A nil Z span prints once, and the real X span prints both ends.
assert "0.000–10.000" in text
assert "12.400" in text
def test_the_sequence_summary_updates_with_the_profile(make_window):
window = _show(make_window())
panel = window.sequence_panel
panel.set_points([SequencePoint(id=1, target_mm={"x": 0.0, "y": 0.0, "z": 1.0})])
before = panel.summary_label.text()
panel.field("repeats").setText("10")
assert panel.summary_label.text() != before
def test_an_empty_sequence_says_so_rather_than_showing_zeros(make_window):
window = _show(make_window())
panel = window.sequence_panel
panel.set_points([])
assert panel.summary_label.text()
assert "0" not in panel.summary_label.text()[:2]
def test_the_design_is_dirty_until_it_is_saved_or_loaded(make_window):
"""Import replaces the design, and there is no autosave."""
window = _show(make_window())
panel = window.sequence_panel
panel.mark_clean()
assert not panel.dirty
panel.field("pitch_mm").setText("9")
assert panel.dirty, "a profile edit did not mark the design dirty"
def test_export_then_import_restores_the_design(make_window, tmp_dir):
"""The round trip through the real panel, not just the format module."""
window = _show(make_window())
panel = window.sequence_panel
panel.set_name("bench sweep")
panel.field("pitch_mm").setText("3.5")
panel.set_points(
[
SequencePoint(id=1, target_mm={"x": 0.0, "y": 0.0, "z": 12.4}),
SequencePoint(id=2, target_mm={"x": 3.5, "y": 0.0, "z": 12.4}),
]
)
path = tmp_dir / "sweep.oryseq"
window.export_sequence(str(path))
assert path.is_file()
assert not panel.dirty, "export did not clear the dirty flag"
# Change everything, then import it back.
panel.set_name("")
panel.field("pitch_mm").setText("1")
panel.set_points([])
document = window.import_sequence(str(path))
assert document.point_count == 2
assert panel.name() == "bench sweep"
assert panel.profile()["pitch_mm"] == 3.5
assert panel.point_row_count() == 2
assert not panel.dirty
def test_importing_a_bad_file_reports_and_changes_nothing(make_window, tmp_dir):
window = _show(make_window())
panel = window.sequence_panel
panel.field("pitch_mm").setText("4")
path = tmp_dir / "bad.oryseq"
path.write_text("not json at all", encoding="utf-8")
with pytest.raises(SequenceFormatError) as excinfo:
window.import_sequence(str(path))
assert "not valid JSON" in str(excinfo.value)
# The design is untouched: a refused import is not a partial import.
assert panel.profile()["pitch_mm"] == 4
def test_an_exported_sequence_names_the_sensor_it_was_designed_for(make_window, tmp_dir):
import json
window = _show(make_window())
window.prefs["sensor_setup"] = {
"sensor_type": "finger",
"geometry_id": "finger-1.0.0",
"probe_tip_set": True,
}
path = tmp_dir / "named.oryseq"
window.export_sequence(str(path))
document = json.loads(path.read_text(encoding="utf-8"))
assert document["device"]["sensor_type"] == "finger"
assert document["device"]["geometry_id"] == "finger-1.0.0"
assert document["versions"]["app"]
def test_language_switch_relabels_the_new_shell(make_window):
from orisys_app_shared.i18n import t