Migrate Qt6 GUI from easystitch to a new easystitch-qt repo #44

Closed
opened 2026-06-22 16:23:21 +00:00 by Mark · 1 comment
Owner

Move Qt6 GUI to its own repo (mark/easystitch-qt) and remove from easystitch

Context

src/intent_resolver/gui_qt6/ (4 files, ~46 KB) is a PyQt6 desktop
GUI for easyStitch. It is:

  • Not on the service critical path — the HTTP service (issue #31)
    doesn't import it. Nothing else in src/ references it (verified
    by grep: only main_pipeline.py and physical_optimizer.py import
    from intent_resolver, and only dom_resolver + stitch_intent,
    never gui_qt6).
  • Has a missing dependency — import PyQt6 is in the code but
    pyqt6 is not in requirements.txt. The GUI has been broken
    (un-runnable) on a clean install for some time.
  • Inflates the security surface — bandit has flagged exec_usage
    calls (lines dialogs.py:123, 129, 135, 147 and main_window.py:754).
    These are actually PyQt6's modal-dialog msg.exec() / app.exec()
    calls, not Python's exec() builtin — so the bandit warning is a
    false positive, but having them in the service-deployment repo
    creates a permanent security-debt line item.
  • Bloats the repo — main_window.py is 23.6 KB, more than 10% of
    the embroidery pipeline core. New contributors see a "GUI" in the
    README mental model that isn't real for the service path.

Goal

Move the GUI to its own repo (mark/easystitch-qt) so:

  • The main easystitch repo deploys as a service cleanly, with no GUI.
  • The GUI repo can be revived by a separate effort (or declared
    abandoned) on its own cadence.
  • The security-scan debt on exec_usage lines is closed by removal.

Implementation steps

Step 1: Create mark/easystitch-qt repo on Forgejo

Use the existing API:

~/.hermes/scripts/forgejo-api.sh POST /user/repos -d '{
  "name": "easystitch-qt",
  "description": "PyQt6 desktop GUI for EasyStitch (Tkinter migration). "Standalone — not part of the easystitch service.",
  "private": false,
  "auto_init": true
}'

Or via the web UI. Repo should be public to match easystitch's
visibility.

Step 2: Copy the GUI files into a clean package layout

Source files (no code changes needed, just relocate):

  • src/intent_resolver/gui_qt6/__init__.py → easystitch_qt/__init__.py
    (rewrite the docstring + module name; keep the same exports)
  • src/intent_resolver/gui_qt6/canvas.py → easystitch_qt/canvas.py
  • src/intent_resolver/gui_qt6/dialogs.py → easystitch_qt/dialogs.py
  • src/intent_resolver/gui_qt6/main_window.py → easystitch_qt/main_window.py

The GUI imports from intent_resolver.stitch_intent (sibling
package). In the new repo, that import needs to be replaced with
from easystitch_qt.stitch_intent import ... — but stitch_intent
is a shared data model, not GUI-specific. The right move is for
easystitch-qt to depend on easystitch as a pip package (or copy
the small stitch_intent.py data classes over as a re-export). Pick
one and document the choice in the new repo's README.

Step 3: Add a real pyproject.toml and requirements.txt to the new repo

The new repo needs:

  • pyproject.toml with the package name easystitch-qt, declaring
    easystitch as a runtime dependency (or pinning the version it
    was extracted from).
  • requirements.txt adding pyqt6 (the missing dependency from the
    old location).
  • A README explaining what the GUI is, how to run it
    (python -m easystitch_qt), and that it requires a working
    easystitch install.
  • A smoke test (e.g. tests/test_import.py) that asserts
    from easystitch_qt import EasyStitchApp succeeds — this is what
    would have caught the broken requirements.txt situation in the
    old location.

Step 4: Remove the GUI from easystitch

  • Delete src/intent_resolver/gui_qt6/.
  • Verify nothing else in src/ still references it (the grep above
    shows it isn't, but re-check after deletion).
  • Update docs/module_structure.md to remove the GUI module from the
    tree (covered by issue #39 P2 if it lands first; otherwise do it
    inline here).
  • Update README.md if it mentions the GUI (it currently doesn't, so
    no change needed).
  • Re-run bandit on src/ and confirm exec_usage findings are gone.

Step 5: Update cross-references

  • File a new issue or comment in the new easystitch-qt repo linking
    back to this ticket.
  • Update the closed issue #19 ("[Security] MEDIUM: 7 code-level
    issue(s)") with a note that the exec_usage findings are
    addressed by removal (the underlying calls were false positives
    but the security debt is now closed regardless).
  • Update the closed issue #4 ("30+ dead GUI day files committed from
    iterative development") — same idea, with a note that the directory
    is now in its proper home.

Acceptance

  • mark/easystitch-qt exists on Forgejo with the 4 GUI files, a
    pyproject.toml, requirements.txt, and README.
  • src/intent_resolver/gui_qt6/ is deleted from easystitch.
  • bandit -r src/ reports zero exec_usage findings in easystitch.
  • The HTTP service (issue #31) builds and runs without changes.
  • A grep for gui_qt6 in easystitch/src/ returns nothing.
  • The new easystitch-qt repo's smoke test passes in CI.

Out of scope

  • Reviving the GUI to working order. That's a separate effort (separate
    repo, separate ticket) — possibly a "this is abandoned" close rather
    than a revival.
  • Documenting how to use the GUI. If it's revived, that comes with the
    revival work.
  • Replacing the GUI with a web-based one. Different scope entirely.
# Move Qt6 GUI to its own repo (mark/easystitch-qt) and remove from easystitch ## Context `src/intent_resolver/gui_qt6/` (4 files, ~46 KB) is a PyQt6 desktop GUI for easyStitch. It is: - **Not on the service critical path** — the HTTP service (issue #31) doesn't import it. Nothing else in `src/` references it (verified by grep: only `main_pipeline.py` and `physical_optimizer.py` import from `intent_resolver`, and only `dom_resolver` + `stitch_intent`, never `gui_qt6`). - **Has a missing dependency** — `import PyQt6` is in the code but `pyqt6` is not in `requirements.txt`. The GUI has been broken (un-runnable) on a clean install for some time. - **Inflates the security surface** — bandit has flagged `exec_usage` calls (lines `dialogs.py:123, 129, 135, 147` and `main_window.py:754`). These are actually PyQt6's modal-dialog `msg.exec()` / `app.exec()` calls, not Python's `exec()` builtin — so the bandit warning is a false positive, but having them in the service-deployment repo creates a permanent security-debt line item. - **Bloats the repo** — `main_window.py` is 23.6 KB, more than 10% of the embroidery pipeline core. New contributors see a "GUI" in the README mental model that isn't real for the service path. ## Goal Move the GUI to its own repo (`mark/easystitch-qt`) so: - The main `easystitch` repo deploys as a service cleanly, with no GUI. - The GUI repo can be revived by a separate effort (or declared abandoned) on its own cadence. - The security-scan debt on `exec_usage` lines is closed by removal. ## Implementation steps ### Step 1: Create `mark/easystitch-qt` repo on Forgejo Use the existing API: ```bash ~/.hermes/scripts/forgejo-api.sh POST /user/repos -d '{ "name": "easystitch-qt", "description": "PyQt6 desktop GUI for EasyStitch (Tkinter migration). "Standalone — not part of the easystitch service.", "private": false, "auto_init": true }' ``` Or via the web UI. Repo should be public to match `easystitch`'s visibility. ### Step 2: Copy the GUI files into a clean package layout Source files (no code changes needed, just relocate): - `src/intent_resolver/gui_qt6/__init__.py` → `easystitch_qt/__init__.py` (rewrite the docstring + module name; keep the same exports) - `src/intent_resolver/gui_qt6/canvas.py` → `easystitch_qt/canvas.py` - `src/intent_resolver/gui_qt6/dialogs.py` → `easystitch_qt/dialogs.py` - `src/intent_resolver/gui_qt6/main_window.py` → `easystitch_qt/main_window.py` The GUI imports from `intent_resolver.stitch_intent` (sibling package). In the new repo, that import needs to be replaced with `from easystitch_qt.stitch_intent import ...` — but `stitch_intent` is a shared data model, not GUI-specific. The right move is for `easystitch-qt` to depend on `easystitch` as a pip package (or copy the small `stitch_intent.py` data classes over as a re-export). Pick one and document the choice in the new repo's README. ### Step 3: Add a real `pyproject.toml` and `requirements.txt` to the new repo The new repo needs: - `pyproject.toml` with the package name `easystitch-qt`, declaring `easystitch` as a runtime dependency (or pinning the version it was extracted from). - `requirements.txt` adding `pyqt6` (the missing dependency from the old location). - A README explaining what the GUI is, how to run it (`python -m easystitch_qt`), and that it requires a working `easystitch` install. - A smoke test (e.g. `tests/test_import.py`) that asserts `from easystitch_qt import EasyStitchApp` succeeds — this is what would have caught the broken `requirements.txt` situation in the old location. ### Step 4: Remove the GUI from `easystitch` - Delete `src/intent_resolver/gui_qt6/`. - Verify nothing else in `src/` still references it (the grep above shows it isn't, but re-check after deletion). - Update `docs/module_structure.md` to remove the GUI module from the tree (covered by issue #39 P2 if it lands first; otherwise do it inline here). - Update `README.md` if it mentions the GUI (it currently doesn't, so no change needed). - Re-run bandit on `src/` and confirm `exec_usage` findings are gone. ### Step 5: Update cross-references - File a new issue or comment in the new `easystitch-qt` repo linking back to this ticket. - Update the closed issue #19 ("[Security] MEDIUM: 7 code-level issue(s)") with a note that the `exec_usage` findings are addressed by removal (the underlying calls were false positives but the security debt is now closed regardless). - Update the closed issue #4 ("30+ dead GUI day files committed from iterative development") — same idea, with a note that the directory is now in its proper home. ## Acceptance - `mark/easystitch-qt` exists on Forgejo with the 4 GUI files, a pyproject.toml, requirements.txt, and README. - `src/intent_resolver/gui_qt6/` is deleted from `easystitch`. - `bandit -r src/` reports zero `exec_usage` findings in `easystitch`. - The HTTP service (issue #31) builds and runs without changes. - A grep for `gui_qt6` in `easystitch/src/` returns nothing. - The new `easystitch-qt` repo's smoke test passes in CI. ## Out of scope - Reviving the GUI to working order. That's a separate effort (separate repo, separate ticket) — possibly a "this is abandoned" close rather than a revival. - Documenting how to use the GUI. If it's revived, that comes with the revival work. - Replacing the GUI with a web-based one. Different scope entirely.
Mark changed title from Qt6 GUI in src/intent_resolver/gui_qt6/ is dead code; contains unfixed HIGH security issues to Migrate Qt6 GUI from easystitch to a new easystitch-qt repo 2026-06-22 16:47:29 +00:00
Mark closed this issue 2026-06-22 16:49:33 +00:00
Author
Owner

Done — migration complete.

  • New repo: https://forgejo.tail018ac4.ts.net/Mark/easystitch-qt (39 KB, 4 source files + pyproject + tests)
  • GUI removed from easystitch in commit 12b6833 (-1508 lines, +0)
  • bandit -r src/ now reports 0 exec_usage findings (was 5)
  • All 3 existing pytest tests still pass (tests/test_main.py)
  • intent_resolver/ is now just dom_resolver.py + stitch_intent.py (both still import fine and are used by main_pipeline.py + physical_optimizer.py)

The new repo has a tests/test_import.py with 4 smoke tests including a regression check (test_pyqt6_dependency_available) that asserts PyQt6 is installed. That's the test that would have caught the original requirements.txt gap.

Cross-linked in the new repo's README under "Provenance" — anyone reading either repo can find the other.

What this closes:

  • This issue (#44)
  • Issue #4 (30+ dead GUI day files) — closed by removal
  • Issue #19 (exec_usage security findings) — closed by removal
  • The 1 line of requirements.txt was never added (pyqt6) — moot now

What this does NOT close:

  • Issue #38 (post_processing/ vs post_processor/ duplication) — different work
  • Issue #39 (stale docs) — the GUI was a small part of that, but the docs cleanup still needs to happen
  • Any of the service-layer issues (#31, #32, etc.) — this was the prep step, not the service work
**Done — migration complete.** - New repo: https://forgejo.tail018ac4.ts.net/Mark/easystitch-qt (39 KB, 4 source files + pyproject + tests) - GUI removed from `easystitch` in commit `12b6833` (-1508 lines, +0) - `bandit -r src/` now reports **0 `exec_usage`** findings (was 5) - All 3 existing pytest tests still pass (`tests/test_main.py`) - `intent_resolver/` is now just `dom_resolver.py` + `stitch_intent.py` (both still import fine and are used by `main_pipeline.py` + `physical_optimizer.py`) The new repo has a `tests/test_import.py` with 4 smoke tests including a regression check (`test_pyqt6_dependency_available`) that asserts PyQt6 is installed. That's the test that would have caught the original `requirements.txt` gap. Cross-linked in the new repo's README under "Provenance" — anyone reading either repo can find the other. **What this closes:** - This issue (#44) - Issue #4 (30+ dead GUI day files) — closed by removal - Issue #19 (exec_usage security findings) — closed by removal - The 1 line of `requirements.txt` was never added (`pyqt6`) — moot now **What this does NOT close:** - Issue #38 (post_processing/ vs post_processor/ duplication) — different work - Issue #39 (stale docs) — the GUI was a small part of that, but the docs cleanup still needs to happen - Any of the service-layer issues (#31, #32, etc.) — this was the prep step, not the service work
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Mark/easystitch#44
No description provided.