From 3e51b800b612952b598aa9ab806427fb3ffefa7a Mon Sep 17 00:00:00 2001 From: Rob Evans Date: Thu, 22 Oct 2026 22:24:59 +1100 Subject: [PATCH 1/2] chore(deps): Pillow 13, PyMuPDF 2 (import pymupdf), customtkinter 6, azure, pytest, pyinstaller; derivatives byte-identical on fixtures --- Image_Processor_Pro_Summary.md | 2 +- pyproject.toml | 14 +++++++------- requirements.txt | 4 ++-- src/image_processor.py | 12 ++++++------ 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Image_Processor_Pro_Summary.md b/Image_Processor_Pro_Summary.md index 2eb9a64..b8e5d28 100644 --- a/Image_Processor_Pro_Summary.md +++ b/Image_Processor_Pro_Summary.md @@ -113,7 +113,7 @@ ImageProcessorMJWProject/ - **Pillow (PIL) 11.3.0** - Advanced image processing - **OpenCV 4.12.0** - Computer vision operations - **PyMuPDF 1.26.3** - PDF processing -- **CustomTkinter 5.2.2** - Modern GUI framework +- **CustomTkinter 6.0.0** - Modern GUI framework - **Flask 3.1.1** - HTTP API server - **Azure SDK** - Cloud integration - **NumPy 2.2.6** - Numerical operations diff --git a/pyproject.toml b/pyproject.toml index ca4303a..8a76404 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,19 +8,19 @@ version = "2.0.0" description = "Local-first, fixity-aware MJW archive derivative renderer" requires-python = ">=3.11" dependencies = [ - "Pillow==12.3.0", + "Pillow==13.0.0", "PyYAML==6.0.3", "loguru==0.7.3", ] [project.optional-dependencies] -gui = ["customtkinter==5.2.2"] -pdf = ["PyMuPDF==1.28.0"] +gui = ["customtkinter==6.0.0"] +pdf = ["PyMuPDF==2.0"] api = ["Flask==3.1.3"] -azure = ["azure-storage-blob==12.30.0", "azure-identity==1.25.1"] -vision-legacy = ["azure-cognitiveservices-vision-computervision==0.9.0"] -build = ["pyinstaller==6.19.0"] -dev = ["pytest==9.0.3", "pytest-cov==7.0.0", "pip-audit==2.10.0"] +azure = ["azure-storage-blob==12.31.0", "azure-identity==1.26.0"] +vision-legacy = ["azure-cognitiveservices-vision-computervision==0.9.1"] +build = ["pyinstaller==6.22.3"] +dev = ["pytest==9.1.1", "pytest-cov==7.1.0", "pip-audit==2.10.1"] [tool.setuptools] package-dir = {"" = "src"} diff --git a/requirements.txt b/requirements.txt index 0bb5d69..ca06841 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # Python >=3.11. Core + desktop UI. Optional capabilities use pyproject extras. -Pillow==12.3.0 +Pillow==13.0.0 PyYAML==6.0.3 loguru==0.7.3 -customtkinter==5.2.2 +customtkinter==6.0.0 diff --git a/src/image_processor.py b/src/image_processor.py index 455620e..bac3b1f 100644 --- a/src/image_processor.py +++ b/src/image_processor.py @@ -17,9 +17,9 @@ from PIL import Image, ImageCms, ImageDraw, ImageFont, ImageOps try: - import fitz + import pymupdf except ImportError: # PDF support is an explicit, separately licensed extra. - fitz = None + pymupdf = None Path("logs").mkdir(exist_ok=True) @@ -515,14 +515,14 @@ def _write_manifest( if os.path.exists(temporary): os.unlink(temporary) def _iter_pdf_pages(self, pdf_path: str) -> Iterator[Tuple[int, Image.Image]]: - if fitz is None: + if pymupdf is None: raise RuntimeError("PDF support is not installed; install ImageProcessorPro with the 'pdf' extra") path = Path(pdf_path) self._source_ok(path) - document = fitz.open(path) + document = pymupdf.open(path) try: if document.page_count > self.config.max_pdf_pages: raise ValueError("PDF page count exceeds configured limit") - matrix = fitz.Matrix(self.config.pdf_dpi / 72, self.config.pdf_dpi / 72) + matrix = pymupdf.Matrix(self.config.pdf_dpi / 72, self.config.pdf_dpi / 72) for number, page in enumerate(document, 1): pixmap = page.get_pixmap(matrix=matrix, alpha=False) if pixmap.width * pixmap.height > self.config.max_pixels: raise ValueError("PDF page exceeds pixel limit") @@ -575,7 +575,7 @@ def save_optimized_image(self, image: Image.Image, output_path: str) -> None: def get_image_files(self, folder_path: str) -> List[str]: root_path = Path(folder_path); files: List[str] = [] - supported = self.supported_formats if fitz is not None else self.supported_formats - {".pdf"} + supported = self.supported_formats if pymupdf is not None else self.supported_formats - {".pdf"} for root, dirs, names in os.walk(root_path): dirs[:] = [name for name in dirs if name.lower() != self.config.subfolder_name.lower()] for name in names: From 58aab7bf17ff53920193b3b69f1c0ce8c18e510c Mon Sep 17 00:00:00 2001 From: Rob Evans Date: Thu, 22 Oct 2026 22:24:59 +1100 Subject: [PATCH 2/2] ci: actions/checkout v7, actions/setup-python v7 --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d89b00a..43b25ee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,8 +9,8 @@ jobs: matrix: python-version: ["3.11", "3.12", "3.13"] steps: - - uses: actions/checkout@v5 - - uses: actions/setup-python@v6 + - uses: actions/checkout@v7 + - uses: actions/setup-python@v7 with: python-version: ${{ matrix.python-version }} - run: python -m pip install --upgrade pip "setuptools>=83" wheel