From 65a2f2877603e32f5447308cd9fdf99436eaaa26 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sun, 6 Sep 2026 16:18:28 +0200 Subject: [PATCH 1/7] moyopy: add build-moyopy.yml for riscv64 wheels Builds moyo's Rust crystal-symmetry library into the moyopy PyO3 extension via cibuildwheel + maturin, mirroring upstream's rw-python-release.yaml narrowed to the riscv64 image. --- .github/workflows/build-moyopy.yml | 119 +++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 .github/workflows/build-moyopy.yml diff --git a/.github/workflows/build-moyopy.yml b/.github/workflows/build-moyopy.yml new file mode 100644 index 000000000..f3193872a --- /dev/null +++ b/.github/workflows/build-moyopy.yml @@ -0,0 +1,119 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# This workflow is based on: +# https://github.com/spglib/moyo/blob/v0.18.0/.github/workflows/rw-python-release.yaml +name: Build moyopy wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'moyopy version to build (git tag without leading v, e.g. 0.18.0)' + required: true + default: '0.18.0' + pull_request: + paths: + - '.github/workflows/build-moyopy.yml' + +concurrency: + group: ${{ github.workflow }}-${{ inputs.version || '0.18.0' }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +env: + # `inputs.version` is empty on pull_request events; default to 0.18.0 there. + MOYOPY_VERSION: ${{ inputs.version || '0.18.0' }} + MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64 + +jobs: + setup: + uses: $/.github/workflows/_setup.yml + + build_wheels: + needs: [setup] + name: Build moyopy ${{ inputs.version || '0.18.0' }} ${{ matrix.tag }}-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 120 + strategy: + fail-fast: false + matrix: + include: + # pyo3's abi3-py310 feature is on unconditionally in moyopy/Cargo.toml, + # so one abi3 wheel serves every GIL-ful interpreter; pyo3 disables + # abi3 under Py_GIL_DISABLED, giving the free-threaded build its own + # wheel. cp313t is dropped: cibuildwheel 4.2.0 has no cp313t build + # identifier on any platform (gotcha 204). + - tag: cp310-abi3 + # Built on cp310 -- the oldest interpreter the abi3 tag claims -- + # and re-tested on the newer ones via find_compatible_wheel + # (gotcha 96). + build: >- + cp310-manylinux_riscv64 cp311-manylinux_riscv64 + cp312-manylinux_riscv64 cp313-manylinux_riscv64 + cp314-manylinux_riscv64 + - tag: cp314t + build: cp314t-manylinux_riscv64 + + steps: + - name: Checkout moyo v${{ env.MOYOPY_VERSION }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: spglib/moyo + ref: v${{ env.MOYOPY_VERSION }} + persist-credentials: false + + - name: Stage the dual licence beside moyopy's pyproject.toml + # maturin globs LICEN[CS]E* relative to the pyproject directory, which + # is moyopy/ in this workspace -- the licence files live at the repo + # root instead, so upstream's own published wheels carry no licence + # text at all (build-primp.yml hits the same gap). + run: cp LICENSE-APACHE LICENSE-MIT moyopy/ + + - name: Build wheels + uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0 + with: + package-dir: moyopy + output-dir: wheelhouse/ + env: + # musllinux is dropped: rustup.rs ships no riscv64 musl toolchain. + CIBW_BUILD: ${{ matrix.build }} + CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} + # moyopy's pyproject.toml carries no [tool.cibuildwheel], so the Rust + # toolchain its maturin backend needs is installed in-container here. + CIBW_BEFORE_ALL_LINUX: >- + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + # numpy has no riscv64 wheel on public PyPI; pymatgen and ase are + # pure-Python (py3-none-any) and resolve from public PyPI either way. + CIBW_ENVIRONMENT_LINUX: >- + PATH="$PATH:$HOME/.cargo/bin" + PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ + # Mirrors upstream's own `py-test` (moyopy[testing,interface] + pytest + # -v moyopy/python/tests); prek (also in the testing extra) is a + # pre-commit lint runner the suite itself never imports, so it's + # dropped. + CIBW_TEST_REQUIRES: >- + pytest numpy pymatgen ase>=3.23 + # Stage only the test tree, not the sibling `moyopy/python/moyopy` + # source package, so pytest imports the installed wheel rather than + # shadowing it with the local source (testing-and-shadowing gotchas). + CIBW_TEST_SOURCES: moyopy/python/tests + CIBW_TEST_COMMAND: python -m pytest -v moyopy/python/tests + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: moyopy-${{ env.MOYOPY_VERSION }}-${{ matrix.tag }}-manylinux_riscv64 + path: wheelhouse/*.whl + if-no-files-found: error + + publish: + name: Publish moyopy ${{ inputs.version || '0.18.0' }} + needs: [setup, build_wheels] + permissions: + contents: write + pull-requests: write + uses: $/.github/workflows/_publish-wheel.yml + with: + artifact-pattern: moyopy-${{ inputs.version || '0.18.0' }}-*-manylinux_riscv64 From 99ef3421360061e3c83a90f9966e10d003b8a969 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sun, 6 Sep 2026 17:12:10 +0200 Subject: [PATCH 2/7] moyopy: skip pymatgen/ase interface tests on cp314t pymatgen hard-requires orjson, and orjson's build script refuses to compile under a free-threaded interpreter. Narrow test coverage for that one identifier instead of dropping the build. --- .github/workflows/build-moyopy.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-moyopy.yml b/.github/workflows/build-moyopy.yml index f3193872a..c0e43f933 100644 --- a/.github/workflows/build-moyopy.yml +++ b/.github/workflows/build-moyopy.yml @@ -54,8 +54,18 @@ jobs: cp310-manylinux_riscv64 cp311-manylinux_riscv64 cp312-manylinux_riscv64 cp313-manylinux_riscv64 cp314-manylinux_riscv64 + test-requires: pytest numpy pymatgen ase>=3.23 + test-ignore: '' - tag: cp314t build: cp314t-manylinux_riscv64 + # pymatgen hard-requires orjson, whose build script refuses to + # compile under a free-threaded interpreter ("orjson v3.12.0 does + # not support free-threaded Python") on every release so far -- so + # pymatgen/ase and the interface tests that need them are dropped + # for this one identifier only (gotcha 216's shape: the build is + # unaffected, only test coverage has a gap). + test-requires: pytest numpy + test-ignore: --ignore=moyopy/python/tests/test_interface.py steps: - name: Checkout moyo v${{ env.MOYOPY_VERSION }} @@ -94,13 +104,12 @@ jobs: # -v moyopy/python/tests); prek (also in the testing extra) is a # pre-commit lint runner the suite itself never imports, so it's # dropped. - CIBW_TEST_REQUIRES: >- - pytest numpy pymatgen ase>=3.23 + CIBW_TEST_REQUIRES: ${{ matrix.test-requires }} # Stage only the test tree, not the sibling `moyopy/python/moyopy` # source package, so pytest imports the installed wheel rather than # shadowing it with the local source (testing-and-shadowing gotchas). CIBW_TEST_SOURCES: moyopy/python/tests - CIBW_TEST_COMMAND: python -m pytest -v moyopy/python/tests + CIBW_TEST_COMMAND: python -m pytest -v moyopy/python/tests ${{ matrix.test-ignore }} - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: From 9ccee74dd492e911bc9f21edbb786b1222779989 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sun, 6 Sep 2026 19:05:57 +0200 Subject: [PATCH 3/7] moyopy: pin numpy/scipy/pandas/orjson to riscv64 wheels in test-requires pymatgen (test-requires, sdist-only on riscv64) pulls in scipy/numpy/pandas/ orjson as runtime deps; without PIP_ONLY_BINARY pip resolved PyPI's newer sdist-only releases over our registry's riscv64 wheels and tried to compile scipy from source, failing on missing OpenBLAS. --- .github/workflows/build-moyopy.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-moyopy.yml b/.github/workflows/build-moyopy.yml index c0e43f933..9a40b2ed3 100644 --- a/.github/workflows/build-moyopy.yml +++ b/.github/workflows/build-moyopy.yml @@ -95,11 +95,19 @@ jobs: # toolchain its maturin backend needs is installed in-container here. CIBW_BEFORE_ALL_LINUX: >- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - # numpy has no riscv64 wheel on public PyPI; pymatgen and ase are - # pure-Python (py3-none-any) and resolve from public PyPI either way. + # numpy/scipy/pandas/orjson have no riscv64 wheel on public PyPI, and + # pymatgen (itself sdist-only on our registry) pulls all four in as + # runtime deps; pymatgen and ase are otherwise pure-Python + # (py3-none-any) and resolve from public PyPI either way. Without + # PIP_ONLY_BINARY, pip picks the highest version across both indexes + # regardless of whether it has a riscv64 wheel, so it reaches past + # our registry's build to PyPI's newer sdist-only release and + # compiles it -- scipy's meson build then fails outright with no + # OpenBLAS in the container (dependencies-and-registry.md gotcha 67/84). CIBW_ENVIRONMENT_LINUX: >- PATH="$PATH:$HOME/.cargo/bin" PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ + PIP_ONLY_BINARY=numpy,scipy,pandas,orjson # Mirrors upstream's own `py-test` (moyopy[testing,interface] + pytest # -v moyopy/python/tests); prek (also in the testing extra) is a # pre-commit lint runner the suite itself never imports, so it's From ddd071cc6583eca452d3b1389645a4c4b9d92b27 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sun, 6 Sep 2026 20:10:04 +0200 Subject: [PATCH 4/7] moyopy: extend PIP_ONLY_BINARY for the rest of pymatgen-core's compiled deps pillow (pulled in via matplotlib) surfaced the same only-binary gap gotcha 291 fixed for numpy/scipy/pandas/orjson: pip reached past our registry's riscv64 wheel to a newer PyPI sdist-only pillow release and failed to compile it (missing libjpeg headers). Checked pymatgen-core's declared deps for the rest of the same class: matplotlib, contourpy, and kiwisolver (all dragged in by matplotlib) and spglib (a direct dep) all lack a riscv64 wheel on public PyPI's newest release but have one on ours, so add all five in one pass. --- .github/workflows/build-moyopy.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-moyopy.yml b/.github/workflows/build-moyopy.yml index 9a40b2ed3..43fd25045 100644 --- a/.github/workflows/build-moyopy.yml +++ b/.github/workflows/build-moyopy.yml @@ -95,19 +95,22 @@ jobs: # toolchain its maturin backend needs is installed in-container here. CIBW_BEFORE_ALL_LINUX: >- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - # numpy/scipy/pandas/orjson have no riscv64 wheel on public PyPI, and - # pymatgen (itself sdist-only on our registry) pulls all four in as - # runtime deps; pymatgen and ase are otherwise pure-Python + # numpy/scipy/pandas/orjson/spglib are pymatgen-core's own runtime + # deps, and matplotlib (also pymatgen-core, dragging in contourpy/ + # kiwisolver/pillow) is one too -- none of these nine has a riscv64 + # wheel on public PyPI's newest release, but all do on our + # registry; pymatgen and ase are otherwise pure-Python # (py3-none-any) and resolve from public PyPI either way. Without # PIP_ONLY_BINARY, pip picks the highest version across both indexes # regardless of whether it has a riscv64 wheel, so it reaches past # our registry's build to PyPI's newer sdist-only release and - # compiles it -- scipy's meson build then fails outright with no - # OpenBLAS in the container (dependencies-and-registry.md gotcha 67/84). + # compiles it from source -- scipy needs OpenBLAS headers the + # container lacks, pillow needs libjpeg headers it also lacks, and + # so on (dependencies-and-registry.md gotcha 67/84/291). CIBW_ENVIRONMENT_LINUX: >- PATH="$PATH:$HOME/.cargo/bin" PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ - PIP_ONLY_BINARY=numpy,scipy,pandas,orjson + PIP_ONLY_BINARY=numpy,scipy,pandas,orjson,pillow,matplotlib,contourpy,kiwisolver,spglib # Mirrors upstream's own `py-test` (moyopy[testing,interface] + pytest # -v moyopy/python/tests); prek (also in the testing extra) is a # pre-commit lint runner the suite itself never imports, so it's From 596d54e0423243fe783f64c00fc674a6209cba0a Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sun, 6 Sep 2026 20:11:28 +0200 Subject: [PATCH 5/7] skill: extend gotcha 291 with the pillow/matplotlib/spglib recurrence from the moyopy port --- .../gotchas/dependencies-and-registry.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/skills/python-project-porting/references/gotchas/dependencies-and-registry.md b/skills/python-project-porting/references/gotchas/dependencies-and-registry.md index fe7ddae4d..dc6159c35 100644 --- a/skills/python-project-porting/references/gotchas/dependencies-and-registry.md +++ b/skills/python-project-porting/references/gotchas/dependencies-and-registry.md @@ -552,3 +552,19 @@ To pull up one entry: `grep -n '^N\. ' references/gotchas/dependencies-and-regis Find the full set by watching which `Collecting ` lines download a `.tar.gz` instead of a `.whl` in a dry run, then check each one against the registry (gotcha 30) before naming it. + - **This is a recurring, multi-hop problem for pymatgen specifically, not a one-time + fix.** A later moyopy run hit the identical mechanism one hop further down the same + tree: `pymatgen` (via `pymatgen-core`) depends on `matplotlib`, whose own runtime deps + `contourpy` and `kiwisolver` (plus `pillow`, pulled in as a `matplotlib` dep too) each + lack a riscv64 wheel on public PyPI's newest release; pillow's sdist build failed with + `RequiredDependencyException: jpeg` (no libjpeg headers in the manylinux image). + `pymatgen-core` also depends directly on `spglib`, which has the same gap. Reading + `pymatgen-core`'s declared `requires_dist` up front (rather than discovering each + culprit via a fresh CI cycle) would have caught all of matplotlib/contourpy/ + kiwisolver/pillow/spglib in one pass — the final list ended up + `PIP_ONLY_BINARY=numpy,scipy,pandas,orjson,pillow,matplotlib,contourpy,kiwisolver,spglib`. + build-lightgbm.yml and build-wordcloud.yml already carry the matplotlib/contourpy/ + kiwisolver/pillow half of this list for the same reason; `fonttools` (also a + matplotlib dep, also registry-only) is deliberately absent from all of them because + its native extension is optional and its `setup.py` falls back to pure Python on a + failed compile instead of failing the install. From 549996a2f665877c7b3eb551c8da611e9fd7297d Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sun, 6 Sep 2026 22:46:52 +0200 Subject: [PATCH 6/7] moyopy: drop spglib from PIP_ONLY_BINARY, extend gotcha 291 build-spglib.yml's own matrix only builds cp312+ riscv64 wheels, so forcing spglib wheel-only starved cp310/cp311 test venvs of any candidate at all. pip's resolver responded by backtracking through pymatgen's entire release history looking for one old enough to not depend on spglib, and crashed 85 minutes later on pymatgen 4.4.11's ancient numpy-distutils setup.py -- a red herring unrelated to which numpy version pip resolved. spglib's registry version doesn't lag PyPI's today, so leaving it unpinned still prefers our wheel where one exists (cp312+) and falls back to building the sdist where it doesn't (cp310/cp311); spglib's build-time tools (cmake/ninja) ship interpreter-agnostic py3-none wheels on the registry already, and build-spglib.yml needs no before-build step, so the same toolchain an sdist build invokes is already proven on this image. --- .github/workflows/build-moyopy.yml | 25 +++++++++--- .../gotchas/dependencies-and-registry.md | 39 +++++++++++++++++++ 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-moyopy.yml b/.github/workflows/build-moyopy.yml index 43fd25045..8249442bb 100644 --- a/.github/workflows/build-moyopy.yml +++ b/.github/workflows/build-moyopy.yml @@ -95,10 +95,10 @@ jobs: # toolchain its maturin backend needs is installed in-container here. CIBW_BEFORE_ALL_LINUX: >- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - # numpy/scipy/pandas/orjson/spglib are pymatgen-core's own runtime - # deps, and matplotlib (also pymatgen-core, dragging in contourpy/ - # kiwisolver/pillow) is one too -- none of these nine has a riscv64 - # wheel on public PyPI's newest release, but all do on our + # numpy/scipy/pandas/orjson are pymatgen-core's own runtime deps, + # and matplotlib (also pymatgen-core, dragging in contourpy/ + # kiwisolver/pillow) is one too -- none of these eight has a + # riscv64 wheel on public PyPI's newest release, but all do on our # registry; pymatgen and ase are otherwise pure-Python # (py3-none-any) and resolve from public PyPI either way. Without # PIP_ONLY_BINARY, pip picks the highest version across both indexes @@ -106,11 +106,24 @@ jobs: # our registry's build to PyPI's newer sdist-only release and # compiles it from source -- scipy needs OpenBLAS headers the # container lacks, pillow needs libjpeg headers it also lacks, and - # so on (dependencies-and-registry.md gotcha 67/84/291). + # so on (dependencies-and-registry.md gotcha 67/84/291). spglib + # (also pymatgen-core) is deliberately left OUT of this list: our + # registry only carries cp312+ spglib wheels (build-spglib.yml's + # own matrix), so forcing it wheel-only starves cp310/cp311 of any + # candidate at all and sends pip's resolver backtracking through + # every pymatgen release ever published looking for one old enough + # to not depend on spglib -- eventually reaching one (4.4.11) whose + # numpy-distutils-era setup.py hard-crashes under modern numpy + # (gotcha 291's addendum below). Leaving spglib unpinned lets pip + # take our registry's wheel where one exists (cp312+, same version + # as PyPI's so the wheel still wins the tie) and fall back to + # building the sdist where it doesn't (cp310/cp311) -- spglib's + # sdist has no riscv64-specific build step upstream doesn't already + # exercise for other architectures. CIBW_ENVIRONMENT_LINUX: >- PATH="$PATH:$HOME/.cargo/bin" PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ - PIP_ONLY_BINARY=numpy,scipy,pandas,orjson,pillow,matplotlib,contourpy,kiwisolver,spglib + PIP_ONLY_BINARY=numpy,scipy,pandas,orjson,pillow,matplotlib,contourpy,kiwisolver # Mirrors upstream's own `py-test` (moyopy[testing,interface] + pytest # -v moyopy/python/tests); prek (also in the testing extra) is a # pre-commit lint runner the suite itself never imports, so it's diff --git a/skills/python-project-porting/references/gotchas/dependencies-and-registry.md b/skills/python-project-porting/references/gotchas/dependencies-and-registry.md index dc6159c35..14115047d 100644 --- a/skills/python-project-porting/references/gotchas/dependencies-and-registry.md +++ b/skills/python-project-porting/references/gotchas/dependencies-and-registry.md @@ -568,3 +568,42 @@ To pull up one entry: `grep -n '^N\. ' references/gotchas/dependencies-and-regis matplotlib dep, also registry-only) is deliberately absent from all of them because its native extension is optional and its `setup.py` falls back to pure Python on a failed compile instead of failing the install. + - **Adding a package to `PIP_ONLY_BINARY` assumes our *own* registry covers every + interpreter in the matrix — verify that per-package, not just per-registry-vs-PyPI.** + The `spglib` entry above was wrong: `build-spglib.yml`'s own matrix only builds + `cp312`/`cp313`/`cp314`/`cp314t` (mirroring upstream's *wheel-building* CI, which is + narrower than upstream's `requires-python>=3.9` and its own published cp39-cp314 + wheels for every other platform), so `pypi.riseproject.dev` carries no cp310/cp311 + `spglib` wheel at all. Forcing `spglib` wheel-only starved every cp310/cp311 test venv + of *any* candidate — not "wrong version", *zero* versions — and pip's resolver + responded by backtracking through pymatgen's entire release history (fetching and + running `Preparing metadata` on some 200+ `pymatgen` sdists, from `2025.10.7` down + through the pre-CalVer `4.x` series) hunting for a release old enough to not declare + `spglib` as a dependency at all, burning the full 85-minute job timeout. It very + nearly found one — metadata generation succeeded all the way down to `4.4.12` — before + hard-crashing on `4.4.11`'s ancient `numpy.distutils`-era `setup.py` + (`AttributeError: 'dict' object has no attribute '__NUMPY_SETUP__'`, a + `__builtins__`-is-a-dict-under-`exec()` bug in that release's `finalize_options`, + unrelated to which numpy version pip resolved). That crash is a red herring: the + *real* bug is upstream of it — pip should never have been trying `pymatgen==4.4.11` + in the first place, and pinning `pymatgen` to an exact recent version would only have + made the resolver fail *faster*, not fixed the install. + - **The fix is dropping `spglib` from `PIP_ONLY_BINARY` entirely, not narrowing the + matrix or pinning pymatgen.** Unlike `numpy`/`scipy`/`pandas`/`orjson`/`pillow`/ + `matplotlib`/`contourpy`/`kiwisolver`, `spglib`'s newest release on our registry + (`2.7.0`) is not behind PyPI's (also `2.7.0`) — there is no version-skew risk *today* + — so leaving it unpinned lets pip prefer our wheel where one exists (cp312+, same + version wins the wheel-over-sdist tie) and fall back to building the sdist where it + doesn't (cp310/cp311), rather than being blocked outright. Confirm an sdist fallback + is actually safe before relying on it: `spglib`'s only build-time tool dependencies + (`cmake`, `ninja`, both via PyPI's `cmake`/`ninja` wrapper packages) publish + `py3-none-*` wheels on our registry — interpreter-agnostic — and `build-spglib.yml` + itself builds spglib with no `CIBW_BEFORE_BUILD` at all, so the same toolchain an + sdist build would invoke is already proven to work on this manylinux_riscv64 image; + the only reason our own port doesn't build cp310/cp311 *wheels* for it is that + nobody has asked yet, not a real incompatibility. + - **A permanently-narrower matrix on our own `build-.yml` is itself worth + grepping for before trusting "our registry has it".** `pypi.riseproject.dev/simple/ + /` (gotcha 30) shows what's *published*, which is downstream of whatever + matrix that dependency's own port workflow builds — check the workflow, not just + the index, when a dependency is itself one of this repo's ports. From a5a9d7aae4906ac7c99bc6afc795f064b64cce13 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Mon, 7 Sep 2026 10:30:47 +0200 Subject: [PATCH 7/7] moyopy: remove skill-file changes that belong on main only The gotcha 291 extension has been pushed directly to main (commit 066c4a8d8), per repo convention that skill/gotcha edits never ride on a port PR branch. --- .../gotchas/dependencies-and-registry.md | 55 ------------------- 1 file changed, 55 deletions(-) diff --git a/skills/python-project-porting/references/gotchas/dependencies-and-registry.md b/skills/python-project-porting/references/gotchas/dependencies-and-registry.md index 14115047d..fe7ddae4d 100644 --- a/skills/python-project-porting/references/gotchas/dependencies-and-registry.md +++ b/skills/python-project-porting/references/gotchas/dependencies-and-registry.md @@ -552,58 +552,3 @@ To pull up one entry: `grep -n '^N\. ' references/gotchas/dependencies-and-regis Find the full set by watching which `Collecting ` lines download a `.tar.gz` instead of a `.whl` in a dry run, then check each one against the registry (gotcha 30) before naming it. - - **This is a recurring, multi-hop problem for pymatgen specifically, not a one-time - fix.** A later moyopy run hit the identical mechanism one hop further down the same - tree: `pymatgen` (via `pymatgen-core`) depends on `matplotlib`, whose own runtime deps - `contourpy` and `kiwisolver` (plus `pillow`, pulled in as a `matplotlib` dep too) each - lack a riscv64 wheel on public PyPI's newest release; pillow's sdist build failed with - `RequiredDependencyException: jpeg` (no libjpeg headers in the manylinux image). - `pymatgen-core` also depends directly on `spglib`, which has the same gap. Reading - `pymatgen-core`'s declared `requires_dist` up front (rather than discovering each - culprit via a fresh CI cycle) would have caught all of matplotlib/contourpy/ - kiwisolver/pillow/spglib in one pass — the final list ended up - `PIP_ONLY_BINARY=numpy,scipy,pandas,orjson,pillow,matplotlib,contourpy,kiwisolver,spglib`. - build-lightgbm.yml and build-wordcloud.yml already carry the matplotlib/contourpy/ - kiwisolver/pillow half of this list for the same reason; `fonttools` (also a - matplotlib dep, also registry-only) is deliberately absent from all of them because - its native extension is optional and its `setup.py` falls back to pure Python on a - failed compile instead of failing the install. - - **Adding a package to `PIP_ONLY_BINARY` assumes our *own* registry covers every - interpreter in the matrix — verify that per-package, not just per-registry-vs-PyPI.** - The `spglib` entry above was wrong: `build-spglib.yml`'s own matrix only builds - `cp312`/`cp313`/`cp314`/`cp314t` (mirroring upstream's *wheel-building* CI, which is - narrower than upstream's `requires-python>=3.9` and its own published cp39-cp314 - wheels for every other platform), so `pypi.riseproject.dev` carries no cp310/cp311 - `spglib` wheel at all. Forcing `spglib` wheel-only starved every cp310/cp311 test venv - of *any* candidate — not "wrong version", *zero* versions — and pip's resolver - responded by backtracking through pymatgen's entire release history (fetching and - running `Preparing metadata` on some 200+ `pymatgen` sdists, from `2025.10.7` down - through the pre-CalVer `4.x` series) hunting for a release old enough to not declare - `spglib` as a dependency at all, burning the full 85-minute job timeout. It very - nearly found one — metadata generation succeeded all the way down to `4.4.12` — before - hard-crashing on `4.4.11`'s ancient `numpy.distutils`-era `setup.py` - (`AttributeError: 'dict' object has no attribute '__NUMPY_SETUP__'`, a - `__builtins__`-is-a-dict-under-`exec()` bug in that release's `finalize_options`, - unrelated to which numpy version pip resolved). That crash is a red herring: the - *real* bug is upstream of it — pip should never have been trying `pymatgen==4.4.11` - in the first place, and pinning `pymatgen` to an exact recent version would only have - made the resolver fail *faster*, not fixed the install. - - **The fix is dropping `spglib` from `PIP_ONLY_BINARY` entirely, not narrowing the - matrix or pinning pymatgen.** Unlike `numpy`/`scipy`/`pandas`/`orjson`/`pillow`/ - `matplotlib`/`contourpy`/`kiwisolver`, `spglib`'s newest release on our registry - (`2.7.0`) is not behind PyPI's (also `2.7.0`) — there is no version-skew risk *today* - — so leaving it unpinned lets pip prefer our wheel where one exists (cp312+, same - version wins the wheel-over-sdist tie) and fall back to building the sdist where it - doesn't (cp310/cp311), rather than being blocked outright. Confirm an sdist fallback - is actually safe before relying on it: `spglib`'s only build-time tool dependencies - (`cmake`, `ninja`, both via PyPI's `cmake`/`ninja` wrapper packages) publish - `py3-none-*` wheels on our registry — interpreter-agnostic — and `build-spglib.yml` - itself builds spglib with no `CIBW_BEFORE_BUILD` at all, so the same toolchain an - sdist build would invoke is already proven to work on this manylinux_riscv64 image; - the only reason our own port doesn't build cp310/cp311 *wheels* for it is that - nobody has asked yet, not a real incompatibility. - - **A permanently-narrower matrix on our own `build-.yml` is itself worth - grepping for before trusting "our registry has it".** `pypi.riseproject.dev/simple/ - /` (gotcha 30) shows what's *published*, which is downstream of whatever - matrix that dependency's own port workflow builds — check the workflow, not just - the index, when a dependency is itself one of this repo's ports.