Skip to content

Port from PySide2/Qt5 to PySide6/Qt6 - #48

Open
mgoodness wants to merge 1 commit into
secondfry:masterfrom
mgoodness:port-pyside6-qt6
Open

mgoodness wants to merge 1 commit into
secondfry:masterfrom
mgoodness:port-pyside6-qt6

Conversation

@mgoodness

@mgoodness mgoodness commented Oct 7, 2026 •

Copy link
Copy Markdown

Summary

Swap the GUI toolkit and build both macOS slices.

 Pipfile
-pyside2 = "*"
-python_version = "3.10"
+pyside6 = "*"
+python_version = "3.13"

 .github/workflows/main.yml
-os: [windows-latest, macos-15-intel]
+include:
+  - os: windows-latest
+  - os: macos-15        # arm64
+  - os: macos-15-intel  # x86_64

 build_mac_installer.sh
+target_arch="${1:-}"   # -> --target-arch "$target_arch"

PySide2/Qt5 is end-of-life and has no native Apple Silicon build, so the current macOS binary is x86_64-only (Rosetta on Apple Silicon). PySide6 ships a single universal2 wheel, so both arches build from the same dependency set — only the PyInstaller target differs. QSettings stays IniFormat/UserScope, which Qt6 reads unchanged, so existing users keep their credentials and avoid list. The API port is mechanical: import rename, .exec_() → .exec(), and regenerated .ui/.qrc modules.

Evidence

  • Before: macOS CI built macos-15-intel only (x86_64; Rosetta on Apple Silicon).
    After: run 37653925240 — all three legs green, uploading shortcircuit-arm64.app.tar.gz, shortcircuit-x86_64.app.tar.gz, and shortcircuit.exe.
  • New suites lock the contract: test_pyside6_migration.py (generated modules build under PySide6; no PySide2/exec_(); Qt5-written QSettings read back) and test_ci_macos_builds.py (both arches wired up; Windows-only lock entries retained).

Trade-offs

  • Pipfile.lock, requirements.txt, and the generated gui_*.py/resources_rc.py are large diffs — inherent to a toolkit bump.
  • importlib-resources is dropped as unused; no replacement.
  • Actions are re-pinned to commit SHAs while the workflow is being touched.

Merge Danger

Door: two-way — reverting restores Qt5; the settings format is unchanged, so nothing must be migrated back.
Blast Radius: packaging

PySide2/Qt5 is end-of-life and has no native Apple Silicon build, so move to
PySide6/Qt6. This also bumps the interpreter from Python 3.10 (end-of-life
October 2026) to 3.13.

The port is mechanical: rename the imports, drop the deprecated .exec_()
alias (PySide6 only warns today, but it is slated for removal in PySide7),
regenerate the .ui- and .qrc-derived modules with pyside6-uic/pyside6-rcc,
and require PyInstaller >= 6.4 for its macOS arm64 and QtNetwork/OpenSSL
fixes. No .ui/.qrc source changes were needed -- Qt6 keeps both schemas.
QSettings was always written with IniFormat/UserScope, which Qt6 reads
unchanged, so existing users keep their credentials and avoid list.

PySide6 ships a single universal2 macOS wheel, so CI now builds native Apple
Silicon alongside the existing Intel build: macos-15 produces an arm64 app and
macos-15-intel keeps producing the x86_64 app, each thinned with PyInstaller's
--target-arch and uploaded as a distinctly named artifact. Windows is
unchanged.

While the workflow is being touched, its actions are also re-pinned to commit
SHAs (with ``# vX.Y.Z`` comments) rather than floating tags, and checkout drops
persisted credentials it never uses. No other CI behavior changes.
@mgoodness
mgoodness marked this pull request as ready for review October 7, 2026 16:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant