- Add MANIFEST.in to include utils/ and setup/ in source distributions - Add utils/build_all.py - unified multi-platform build orchestrator (Linux amd64/arm64, macOS amd64/arm64, Windows amd64/arm64) - Add BUILD_LINUX.md - Linux build guide with .deb and AppImage options - Add RELEASE.md - complete release process with versioning (YYYY/MM.####), platform support matrix, and release workflow - Fix .gitignore to exclude UmbraEdit_Projects/, Inner_Demon_1.2a.docm, UmbraEdit_deb_Build_Script.txt, requirements.txt, .DS_Store - All source distributions now include build scripts for Linux packages
8.4 KiB
UmbraEdit — Toolchain & Dependency Update Plan
Copyright (C) 2026 B.D. Murphy and novelWriter contributors. Plan for upgrading UmbraEdit (Python/PyQt6) toolchain and dependencies.
Goal: Bring UmbraEdit (Python/PyQt6) up to the latest stable versions of its tools and dependencies, starting from the current baseline.
Baseline (as of 2026-11-05):
- System Python: 3.9.6 (
/usr/bin/python3) — below the project'srequires-python >=3.11 - Available runtimes: Python 3.11.15, 3.12.13 (via
uvin~/.local/bin) uv: 0.11.7 (2026-04-15) — outdated- PyQt6: not yet installed in the 3.11 environment
pyproject.tomldeps:pyqt6>=6.4,pyenchant>=3.3.0,pyobjc-framework-Cocoa(darwin)- Lockfile:
uv.lock(referencesnovelwriterpackage name — will need regen)
1. Target Versions
| Tool | Current | Target | Source |
|---|---|---|---|
| Python runtime | 3.9.6 (system) | 3.12.x (latest 3.12) or 3.13.x | uv / python.org |
| PyQt6 | not installed | latest 6.x | PyPI |
| pyenchant | >=3.3.0 | latest 3.x | PyPI |
| pyobjc-framework-Cocoa | pinned by pyproject | latest (macOS only) | PyPI |
| uv | 0.11.7 | latest | github.com/astral-sh/uv |
| ruff | (in uv.lock) |
latest | PyPI |
| pyright | (in uv.lock) |
latest | npm/PyPI |
| pytest | (in uv.lock) |
latest 8.x | PyPI |
| pytest-qt | (in uv.lock) |
latest | PyPI |
| coverage | (in uv.lock) |
latest | PyPI |
| Sphinx + theme | (in uv.lock) |
latest | PyPI |
| setuptools | 82.0.1 | latest | PyPI |
| pip | 26.0.1 | latest | ensure via uv |
Prefer Python 3.12 as the primary target (mature, PyQt6 wheels widely available). Keep 3.11 as a secondary CI matrix entry since
requires-pythonis>=3.11.
2. Phased Execution
Phase 0 — Preparation & Safety
- Ensure working tree is clean and all changes committed on
main(already done). - Tag the current state as a rollback point:
git tag umbraedit/pre-toolchain-update git push origin umbraedit/pre-toolchain-update - Record current working commands (
python3 UmbraEdit.py, test runner) so you can compare before/after. - Back up
uv.lockandpyproject.toml.
Phase 1 — Upgrade uv and Python runtimes
- Upgrade
uvitself:uv self upgrade # or: curl -LsSf https://astral.sh/uv/install.sh | sh - Install the target Python(s) via
uv(so they are isolated and reproducible):uv python install 3.12 uv python install 3.11 # keep for CI matrix uv python list uv python pin 3.12 # sets default for this project (writes .python-version) - Verify:
uv run python --version # should report 3.12.x
Phase 2 — Upgrade core runtime dependencies
Create a fresh virtual environment with the target Python and install the project's runtime deps at their latest compatible versions:
cd /Volumes/1TB_APL_Storage/UmbraEdit
uv venv --python 3.12
uv pip install "pyqt6>=6.4" "pyenchant>=3.3.0"
# macOS only:
uv pip install "pyobjc-framework-Cocoa"
Then:
- Run the app to confirm it starts:
uv run python UmbraEdit.py # or, after venv activation: python UmbraEdit.py - If
pyqt6wheels fail on the target Python, fall back to 3.11 or file an issue.
Phase 3 — Upgrade build / lint / test tooling
Update the dependency groups in pyproject.toml (build, docs, test, lint) to latest, then sync:
[dependency-groups]
dev = [
{ include-group = "build" },
{ include-group = "docs" },
{ include-group = "test" },
{ include-group = "lint" },
]
build = ["pyyaml", "tzdata; sys_platform == 'win32'"]
docs = [
"docutils>=0.17.1",
"pygments>=2.7",
"sphinx-book-theme",
"sphinx-copybutton",
"sphinx-design",
"sphinx-favicon",
"sphinx-intl",
"sphinx>=5.0",
]
test = [
"coverage>=7.16.0",
"pytest-qt",
"pytest-timeout",
"pytest>=6.0.0",
"tzdata; sys_platform == 'win32'",
]
lint = ["pyright", "ruff"]
Suggested edits:
- Bump
pytest>=6.0.0→pytest>=8.0(check PyPI for latest 8.x) - Bump
coverage>=7.16.0→ latest - Bump
sphinx>=5.0→ latest 7.x/8.x - Keep
ruffandpyrightunpinned or with generous lower bounds souv lockresolves latest
Then sync:
uv lock --upgrade # resolve all groups to latest
uv sync --all-groups # create .venv with everything
Phase 4 — Regenerate uv.lock
uv.lock currently references the old novelwriter package name and is stale.
uv lock --upgrade
git diff uv.lock # review before committing
Commit the regenerated lockfile with the toolchain update.
Phase 5 — Update requires-python and classifiers (optional)
If you want to drop 3.11 and standardize on 3.12+:
requires-python = ">=3.12"
And update classifiers accordingly. Otherwise keep >=3.11 and test both 3.11 and 3.12 in CI.
Phase 6 — Update Gitea CI workflows
The .github/workflows/*.yml files reference Python setup steps. Update them to:
- Use
actions/setup-pythonwithpython-version: ["3.11", "3.12"](or your Gitea Actions equivalent) - Install via
uv sync --all-groupsinstead ofpip install -e . - Run
uv run ruff check,uv run pyright,uv run pytest
If your Gitea instance uses Gitea Actions, mirror the same matrix. If not, update the workflows to call uv explicitly.
Phase 7 — Packaging scripts review
The utils/ build scripts (build_appimage.py, build_debian.py, build_flatpak.py, build_pypi.py, build_windows.py) and setup/ packaging may pin Python/Qt versions. Check each for:
- Hardcoded
python3→ should target the new runtime qt_version = "6.11"in[tool.novelwriter.build] flatpak→ verify against latest Qt6pyqt6>=6.4lower bound → keep or raise
Phase 8 — Validation
- Syntax/compile:
uv run python -m py_compile umbraedit/ tests/ utils/ - Import smoke:
uv run python -c "import umbraedit; umbraedit.main(['--help'])" - Lint:
uv run ruff check .anduv run pyright - Tests:
uv run pytest(oruv run python run_tests.py) - App launch:
uv run python UmbraEdit.py— confirm main window opens - Export formats: exercise DOCX/EPUB/HTML/ODT export paths if sample data exists
Phase 9 — Commit & publish
git add -A
git commit -m "chore: upgrade toolchain to Python 3.12 and latest deps
- Upgrade uv and pin Python 3.12 via .python-version
- Refresh pyproject.toml dependency groups to latest compatible versions
- Regenerate uv.lock
- Update Gitea CI workflows for uv + Python 3.11/3.12 matrix
- Review packaging scripts for hardcoded python/qt versions"
git push origin main
3. Rollback Plan
If anything breaks after the update:
# Restore previous state
git checkout umbraedit/pre-toolchain-update .
# or reset hard to the tag
git reset --hard umbraedit/pre-toolchain-update
git push origin main --force # only if already pushed and you need to undo
Also keep the old system Python 3.9.6 available (do not remove /usr/bin/python3), and keep the upstream remote pointing at the original novelWriter for reference.
4. Recommended Command Sequence (copy-paste ready)
cd /Volumes/1TB_APL_Storage/UmbraEdit
# 0. Tag rollback point
git tag umbraedit/pre-toolchain-update
git push origin umbraedit/pre-toolchain-update
# 1. Upgrade uv and pin Python 3.12
uv self upgrade
uv python install 3.12
uv python pin 3.12
uv run python --version
# 2. Create venv and install runtime deps at latest
uv venv --python 3.12
uv pip install "pyqt6>=6.4" "pyenchant>=3.3.0"
# 3. Smoke-test the app
uv run python UmbraEdit.py
# 4. Sync dev toolchains (lint/test/docs)
uv sync --all-groups
# 5. Regenerate lockfile
uv lock --upgrade
git diff uv.lock | head -100
# 6. Validate
uv run python -m py_compile umbraedit/ tests/ utils/
uv run ruff check .
uv run pytest
5. Notes & Risks
- PyQt6 on Python 3.13: Wheels may lag; if 3.13 is required, verify PyQt6 availability first. 3.12 is the safer target.
pyobjc-framework-Cocoa: macOS-only; only install/test on darwin.uv.lockdiff: Expect a large diff since the lockfile is stale; review that no unexpected major-version jumps occur (especially PyQt6 6.x → 7.x, which would be breaking).- CI: Gitea Actions runners must have
uvinstalled, or the workflows must install it as a step. - Application still runs on Python 3.9.6? No —
match/casesyntax requires 3.10+, andrequires-pythonis>=3.11. The system 3.9.6 must not be used to run UmbraEdit.