fix(deps): resolve Pillow from piwheels on ARM32 - #72134
Conversation
3502719 to
42253dd
Compare
teknium1
left a comment
There was a problem hiding this comment.
Thanks for the focused ARM32 investigation. The current lock still lacks an ARMv6/ARMv7 Pillow wheel, so the reported failure is real.
Problems
pyproject.toml:320adds the piwheels source only through[tool.uv.sources], but the shell installer exportsUV_NO_CONFIG=1atscripts/install.sh:31-33. If locked sync fails, its fallback invokesuv pip install -eatscripts/install.sh:1632-1645; that path does not discover the project-level uv configuration, so it can still resolve Pillow from PyPI and attempt the ARM32 source build.
Suggested changes
- Cover the installer fallback/recovery route as well as locked sync, while preserving the existing isolation from user/home uv configuration.
- The PR is currently conflicting with main; current main regenerated
uv.lockwith CI's uv 0.11.33 in3d2cc39158, so the lock should be regenerated during salvage.
Automated hermes-sweeper review.
| # On matching versions, a missing piwheels wheel is a hard resolution failure; | ||
| # uv does not fall back to the sdist. See #72132. | ||
| [tool.uv.sources] | ||
| pillow = [ |
There was a problem hiding this comment.
Blocking: this source table is bypassed by the shell installer's UV_NO_CONFIG=1 (scripts/install.sh:31-33). When locked sync fails, its uv pip install -e fallback (scripts/install.sh:1632-1645) will not discover this configuration, leaving ARM32 able to fall back to the PyPI Pillow sdist. Please cover that fallback/recovery route too.
There was a problem hiding this comment.
Addressed in 2d6724d5c.
The branch is rebased onto main at 338bca796, and uv.lock is regenerated for Pillow==12.3.0.
tests/test_install_sh_uv_sources.py now executes the actual scripts/install.sh --stage python-deps path. The test forces locked sync to fail, verifies a negative control with UV_NO_SOURCES=1, and then verifies that the real fallback succeeds while the installer exports UV_NO_CONFIG=1. This covers the recovery route without weakening isolation from user/home uv configuration.
The same installer regression test passed on the reported ARMv7 / Python 3.11.2 host with both CI uv 0.9.28 and current uv 0.12.3. Separately, the piwheels Pillow==12.3.0 artifact installed on that host and its native _imaging.cpython-311-arm-linux-gnueabihf.so extension imported successfully; file identifies it as ELF 32-bit ARM EABI5.
The current PR CI is fully green, including all 12 Python slices, uv lock --check, supply-chain checks, and amd64/arm64 Docker builds.
No runtime installer change was required: UV_NO_CONFIG=1 isolates ambient configuration but does not disable project tool.uv.sources; UV_NO_SOURCES=1 is the control that disables those sources.
42253dd to
9e2b9cc
Compare
SummaryOne PR addresses issue #72132. #72134 adds package-scoped piwheels routing and hash-locked ARM32 Pillow wheels for Python 3.11 and 3.13, directly targeting the reported PyPI source-build failure, but its diff does not add coverage for the installer's fallback path. Related pull requests
Suggested consolidationKeep #72134 open with a salvage path: retain its scoped piwheels routing and locked ARM32 artifacts, rebase onto main and regenerate Complex graphflowchart LR
classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
classDef best stroke-width:3px,stroke:#b45309
classDef target stroke-width:3px,stroke:#4338ca
I72132(["issue #72132 (open)"])
P72134["PR #72134 (open)"]
P72134 -->|best fix| I72132
class I72132 open
class P72134 open
class P72134 best
class P72134 target
click I72132 "https://github.com/NousResearch/hermes-agent/issues/72132"
click P72134 "https://github.com/NousResearch/hermes-agent/pull/72134"
Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label). Cross-PR triage: Reviewed 1 pull request and 1 issue in this complex. Each diff was read against this issue; Assessment working set: 12 kB of PR diffs, 11 kB of issue/PR text, 3 kB of discussion (3 comments), 3 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch. |
9e2b9cc to
2d6724d
Compare
What does this PR do?
Prevents Pillow source builds during Hermes install and update on supported
32-bit Raspberry Pi platforms.
PyPI does not publish ARMv6/ARMv7 wheels for the locked
Pillow==12.3.0release. piwheels publishes compatible CPython 3.11 and 3.13 wheels, but uv
does not read Raspberry Pi OS's pip-specific
/etc/pip.conf. Without aproject source declaration, uv therefore selects the PyPI sdist and Pillow
requires native JPEG/zlib development headers.
This change declares piwheels as an explicit, package-scoped uv source:
pillowcan resolve from piwheels;armv6l/armv7lon Python 3.11 or 3.13 use that source;uv.lock.Using
explicit = trueavoids the unrelated-package resolution problem of aglobal extra index: uv cannot select any other dependency from piwheels.
Related Issue
Fixes #72132
Type of Change
Changes Made
pyproject.toml.uv.lockwith separate PyPI and piwheels Pillow entries.fallback, and SHA256-locked ARM32 wheels.
scripts/install.sh --stage python-depsroute, forces locked sync to fail,and verifies the fallback under the installer's
UV_NO_CONFIG=1isolation.Compatibility and Risk
needs the JPEG/zlib build headers. Raspberry Pi OS Bookworm uses Python 3.11
and Trixie uses Python 3.13, so the practical unsupported gap is narrow.
dependency. If it is unreachable or the selected wheel disappears, uv fails
resolution instead of falling back to the PyPI sdist.
/etc/pip.confto a repository-scoped packagesource. The source is restricted to Pillow with
explicit = true; lockedsync verifies each selected wheel against its SHA256 in
uv.lock.exclude-newer-package.pillow = falsedisables that gate package-wide forPillow. The exact version pin, package-scoped explicit source, and lock
hashes bound the locked-sync exposure. The existing unlocked installer
fallback does not enforce lock hashes.
same artifact under both platform tags.
and Nix was unavailable locally. The marker is false on the common
x86_64/aarch64 Nix hosts, but lock parsing remains an unverified risk.
How to Test
scripts/run_tests.sh tests/test_install_sh_uv_sources.py tests/test_project_metadata.py -q.uv lock --check --offline.Pillow version from piwheels and confirm that
PIL/_imaging.cpython-311-arm-linux-gnueabihf.soimports successfully.Verification performed
Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — N/A; the non-obvious source invariants are documented next to the configurationcli-config.yaml.exampleif I added/changed config keys — N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — N/AScreenshots / Logs
Original report (
Pillow==12.2.0):Current branch (
Pillow==12.3.0):