From bb22626078614a9e93461c46b1181fe7ed2e3864 Mon Sep 17 00:00:00 2001 From: "riseproject-dev[bot]" <330740410+riseproject-dev[bot]@users.noreply.github.com> Date: Fri, 18 Sep 2026 13:36:03 +0000 Subject: [PATCH 1/7] scikit-image: Add version 0.26.0 Signed-off-by: riseproject-dev[bot] <330740410+riseproject-dev[bot]@users.noreply.github.com> --- docs/packages/scikit-image.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/packages/scikit-image.yaml b/docs/packages/scikit-image.yaml index 555917ccba..e4c8d9e8ee 100644 --- a/docs/packages/scikit-image.yaml +++ b/docs/packages/scikit-image.yaml @@ -33,3 +33,4 @@ versions: - filename: scikit_image-0.25.2-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_35_riscv64.whl sha256: ba9c3502fa62fc72879d0a98a8eb6cebbab6c9f33b1f577d7e1958510a1942ce requires-python: '>=3.10' +- version: 0.26.0 From 0fcc0fac3010fad345e2cf0cde54b2d582929f14 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 18 Sep 2026 13:57:38 +0000 Subject: [PATCH 2/7] scikit-image: add build-scikit-image.yml and backport the removed cpython-freethreading enable group scikit-image v0.26.0's pyproject.toml sets [tool.cibuildwheel] enable="cpython-freethreading", but cibuildwheel 4.2.0 (the version this repo pins for riscv64 builds) no longer recognises that enable group -- it errors "Failed to parse enable group" before any build starts, on every interpreter, since [tool.cibuildwheel] is parsed as a whole. Free-threaded builds (cp314t) no longer need an opt-in. scikit-image's own next commit (2c3a869aebcc82c7802a9ec3d112df0878df2d4d, "Drop 3.13t builds from cibuildwheel configuration (#8127)") drops the same line with no replacement, confirming this is upstream's own bug. patches/scikit-image/0.26.0/ backports that line removal, and build-scikit-image.yml checks out python-wheels alongside the upstream tag and applies it before the cibuildwheel step. --- .github/workflows/build-scikit-image.yml | 111 ++++++++++++++++++ ...d-cpython-freethreading-enable-group.patch | 29 +++++ 2 files changed, 140 insertions(+) create mode 100644 .github/workflows/build-scikit-image.yml create mode 100644 patches/scikit-image/0.26.0/0001-pyproject-drop-the-removed-cpython-freethreading-enable-group.patch diff --git a/.github/workflows/build-scikit-image.yml b/.github/workflows/build-scikit-image.yml new file mode 100644 index 0000000000..871d7c8d1d --- /dev/null +++ b/.github/workflows/build-scikit-image.yml @@ -0,0 +1,111 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# This workflow is based on the `build_wheel_linux` job of +# https://github.com/scikit-image/scikit-image/blob/v0.26.0/.github/workflows/wheels-recipe.yaml +name: Build scikit-image wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'Version glob to (re)build; empty builds every version of docs/packages/scikit-image.yaml not released yet' + required: false + default: '' + pull_request: + branches: [main] + paths: + - '.github/workflows/build-scikit-image.yml' + - 'docs/packages/scikit-image.yaml' + - 'patches/scikit-image/**' + push: + branches: [main] + paths: + - '.github/workflows/build-scikit-image.yml' + - 'docs/packages/scikit-image.yaml' + - 'patches/scikit-image/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +env: + MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64 + +jobs: + setup: + uses: $/.github/workflows/_setup.yml + with: + package: scikit-image + version: ${{ inputs.version }} + + build_wheels: + needs: [setup] + if: needs.setup.outputs.versions != '[]' + name: Build scikit-image ${{ matrix.version }} ${{ matrix.python }}-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 300 + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + python: ["cp312", "cp313", "cp314", "cp314t"] + + env: + SCIKIT_IMAGE_VERSION: ${{ matrix.version }} + + steps: + - name: Checkout scikit-image v${{ env.SCIKIT_IMAGE_VERSION }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: scikit-image/scikit-image + ref: v${{ env.SCIKIT_IMAGE_VERSION }} + persist-credentials: false + + - name: Checkout python-wheels + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + path: python-wheels + persist-credentials: false + + - name: Apply patches + run: git apply -v python-wheels/patches/scikit-image/${{ env.SCIKIT_IMAGE_VERSION }}/*.patch + + - name: Build wheels + uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0 + with: + output-dir: wheelhouse/ + only: ${{ matrix.python }}-manylinux_riscv64 + env: + CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} + # numpy/scipy have riscv64 wheels only on our registry; cython/meson-python/ + # pythran build from sdist there, same as upstream's own build-time resolution. + CIBW_ENVIRONMENT: >- + PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ + PIP_ONLY_BINARY=numpy,scipy + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: scikit-image-${{ env.SCIKIT_IMAGE_VERSION }}-${{ matrix.python }}-manylinux_riscv64 + path: wheelhouse/*.whl + if-no-files-found: error + + publish: + name: Publish scikit-image ${{ matrix.version }} + needs: [setup, build_wheels] + if: needs.setup.outputs.versions != '[]' + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + permissions: + contents: write + pull-requests: write + uses: $/.github/workflows/_publish-wheel.yml + secrets: + app-private-key: ${{ secrets.RISEPROJECT_APP_PRIVATE_KEY }} + with: + artifact-pattern: scikit-image-${{ matrix.version }}-*-manylinux_riscv64 diff --git a/patches/scikit-image/0.26.0/0001-pyproject-drop-the-removed-cpython-freethreading-enable-group.patch b/patches/scikit-image/0.26.0/0001-pyproject-drop-the-removed-cpython-freethreading-enable-group.patch new file mode 100644 index 0000000000..8611c6703c --- /dev/null +++ b/patches/scikit-image/0.26.0/0001-pyproject-drop-the-removed-cpython-freethreading-enable-group.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Fri, 18 Sep 2026 14:00:00 +0200 +Subject: [PATCH] pyproject: drop the removed cpython-freethreading enable + group + +cibuildwheel 4.2.0 (the version this repo pins for riscv64 builds) no +longer recognises "cpython-freethreading" as an enable group -- it +errors "Failed to parse enable group" before any build starts, on +every interpreter, since [tool.cibuildwheel] is parsed as a whole. +Free-threaded builds (cp314t) no longer need an opt-in. + +Upstream-Status: Backport [https://github.com/scikit-image/scikit-image/commit/2c3a869aebcc82c7802a9ec3d112df0878df2d4d] +--- + pyproject.toml | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/pyproject.toml b/pyproject.toml +index c47263d..f397dcd 100644 +--- a/pyproject.toml ++++ b/pyproject.toml +@@ -223,7 +223,6 @@ test-sources = ["tests", "pyproject.toml"] + environment = {PIP_PREFER_BINARY=1} + environment-pass = ["SKIMAGE_LINK_FLAGS", "PIP_EXTRA_INDEX_URL", "COLUMNS"] + build-verbosity = 0 +-enable="cpython-freethreading" + + [tool.cibuildwheel.config-settings] + setup-args = "-Dinclude-v2=false" From ccd542445cf9caf50ca460528c6bc2128f8b7c69 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sat, 19 Sep 2026 06:04:24 +0000 Subject: [PATCH 3/7] scikit-image: override CIBW_TEST_EXTRAS to skip SimpleITK on riscv64 Upstream's default test-extras ("test", "optional") pulls in SimpleITK, which has no riscv64 wheel and fails to build from source (CMake cannot find PythonLibs on this platform). Upstream already excludes SimpleITK on aarch64/win_arm64/musllinux via a "optional_free_threaded" test-extras override; apply the same set for riscv64 (gotcha 336). --- .github/workflows/build-scikit-image.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build-scikit-image.yml b/.github/workflows/build-scikit-image.yml index 871d7c8d1d..974314e854 100644 --- a/.github/workflows/build-scikit-image.yml +++ b/.github/workflows/build-scikit-image.yml @@ -86,6 +86,10 @@ jobs: CIBW_ENVIRONMENT: >- PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ PIP_ONLY_BINARY=numpy,scipy + # Upstream's default test-extras ("test", "optional") pulls in SimpleITK, which has + # no riscv64 wheel and fails to build from source; use upstream's own aarch64/ + # win_arm64/musllinux override (gotcha 336) instead. + CIBW_TEST_EXTRAS: test optional_free_threaded - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: From 2609787277a74ac0ed1d1eccd110a585732be524 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sat, 19 Sep 2026 10:22:02 +0000 Subject: [PATCH 4/7] scikit-image: fix CIBW_TEST_EXTRAS separator CIBW_TEST_EXTRAS is substituted directly into pip's requirement string as []; pip requires a comma between extra names, not a space. The space-separated value produced an invalid requirement ("Expected comma between extra names") and failed every matrix leg at the test-install step. --- .github/workflows/build-scikit-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-scikit-image.yml b/.github/workflows/build-scikit-image.yml index 974314e854..49d38c3850 100644 --- a/.github/workflows/build-scikit-image.yml +++ b/.github/workflows/build-scikit-image.yml @@ -89,7 +89,7 @@ jobs: # Upstream's default test-extras ("test", "optional") pulls in SimpleITK, which has # no riscv64 wheel and fails to build from source; use upstream's own aarch64/ # win_arm64/musllinux override (gotcha 336) instead. - CIBW_TEST_EXTRAS: test optional_free_threaded + CIBW_TEST_EXTRAS: test,optional_free_threaded - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: From 322cf8f899bfe9d1b46bfdfc1e41f25a06fa45c5 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sat, 19 Sep 2026 17:29:04 +0000 Subject: [PATCH 5/7] scikit-image: pin pytest<9.1 in CIBW_TEST_REQUIRES 0.26.0's own test suite passes raw itertools.product() generators to @pytest.mark.parametrize(); pytest 9.1 deprecates that shape, and scikit-image's filterwarnings = ["error"] turns the deprecation into a hard collection error on every interpreter (cp312/cp313/cp314/cp314t all failed identically in run 35437213081). Not riscv64-specific: upstream fixed this on main post-0.26.0 by wrapping the calls in list(...) and bumping to pytest>=9, confirming 0.26.0 itself was never tested against pytest 9.1 (gotcha 339: pin to the project's own working ceiling instead of patching the test). --- .github/workflows/build-scikit-image.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build-scikit-image.yml b/.github/workflows/build-scikit-image.yml index 49d38c3850..857b33a155 100644 --- a/.github/workflows/build-scikit-image.yml +++ b/.github/workflows/build-scikit-image.yml @@ -90,6 +90,11 @@ jobs: # no riscv64 wheel and fails to build from source; use upstream's own aarch64/ # win_arm64/musllinux override (gotcha 336) instead. CIBW_TEST_EXTRAS: test,optional_free_threaded + # 0.26.0's own tests pass raw itertools.product() generators to parametrize(); + # pytest 9.1 deprecates that and this project's filterwarnings=error turns it + # into a collection error (fixed upstream post-0.26.0). Cap at the ceiling + # 0.26.0 was actually tested against (gotcha 339). + CIBW_TEST_REQUIRES: pytest<9.1 - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: From 30d85fdfabf7e300adbde6268fa3af8c072f6a8a Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sun, 20 Sep 2026 07:17:14 +0000 Subject: [PATCH 6/7] scikit-image: pin numpy<2.5 in CIBW_TEST_REQUIRES With pytest<9.1 fixing the earlier collection-time error, all four matrix legs (cp312/cp313/cp314/cp314t) still failed, now further in: UNEXPECTED EXCEPTION: DeprecationWarning('Setting the shape on a NumPy array has been deprecated in NumPy 2.5...') from skimage/morphology/grayreconstruct.py:216, reached via the h_maxima/h_minima/CircleModel/EllipseModel/ransac doctests. reconstruction() assigns `rec_img.shape = ...` in place; NumPy 2.5 deprecation-warns on that, and scikit-image's own filterwarnings=["error"] turns the warning fatal. scikit-image 0.26.0's pyproject.toml requires numpy>=2.0 with no upper bound, so cibuildwheel resolves the latest available release (confirmed numpy==2.5.3 installed in run 35461367550) -- a version that postdates 0.26.0 and triggers a deprecation the project was never tested against. Same class of bug as the pytest<9.1 pin above (gotcha 339, generalized by gotcha 355 to any unpinned test-venv dependency): pin numpy below the version that introduced the new deprecation, scoped to the test venv only, rather than patch scikit-image's own library code. --- .github/workflows/build-scikit-image.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-scikit-image.yml b/.github/workflows/build-scikit-image.yml index 857b33a155..5ef32cfa30 100644 --- a/.github/workflows/build-scikit-image.yml +++ b/.github/workflows/build-scikit-image.yml @@ -94,7 +94,17 @@ jobs: # pytest 9.1 deprecates that and this project's filterwarnings=error turns it # into a collection error (fixed upstream post-0.26.0). Cap at the ceiling # 0.26.0 was actually tested against (gotcha 339). - CIBW_TEST_REQUIRES: pytest<9.1 + # + # skimage/morphology/grayreconstruct.py:216 (reconstruction(), reached from the + # h_maxima/h_minima/CircleModel/EllipseModel/ransac doctests) assigns + # `rec_img.shape = ...` in place; NumPy 2.5 deprecation-warns on in-place .shape + # assignment, which filterwarnings=error again turns fatal. scikit-image's own + # pyproject.toml only requires numpy>=2.0 with no upper bound, so cibuildwheel + # resolves the latest available (2.5.3) and hits a warning that didn't exist when + # 0.26.0 shipped. Same class of bug as pytest<9.1 above (gotcha 339/355): pin the + # test venv's numpy below the version that introduced the new deprecation, rather + # than patch scikit-image's own library code. + CIBW_TEST_REQUIRES: pytest<9.1 numpy<2.5 - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: From 4c5d59f7c697c42a2cde538c21bbee2fb833959e Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sun, 20 Sep 2026 15:53:48 +0000 Subject: [PATCH 7/7] scikit-image: pin Pillow<12.1.0 and scipy<1.18 in CIBW_TEST_REQUIRES Round 3 of the same unpinned-test-dependency bug class (gotcha 339/355): scikit-image 0.26.0's pyproject.toml requires pillow>=10.1 and scipy>=1.11.4 with no upper bound, so cibuildwheel resolves the latest available Pillow (12.3.0) and SciPy (1.18.1). - skimage/io/_plugins/pil_plugin.py calls the now-deprecated Image.getdata() (deprecated in Pillow 12.1.0 in favor of get_flattened_data()), reached via io.imread()/MultiImage and exercised by test_multi_image.py's test_len/test_slicing/ test_concatenate. - skimage/measure/fit.py and skimage/transform/_thin_plate_splines.py call scipy.spatial.minkowski_distance/distance_matrix, both deprecated as of SciPy 1.18.0 in favor of scipy.spatial.distance.minkowski/cdist, reached via the CircleModel and ThinPlateSplineTransform doctests. filterwarnings=["error"] in scikit-image's own pytest config turns both deprecations fatal. Pin the test venv below the version that introduced each deprecation, same as the existing pytest<9.1 and numpy<2.5 pins. --- .github/workflows/build-scikit-image.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-scikit-image.yml b/.github/workflows/build-scikit-image.yml index 5ef32cfa30..bdb2b5254a 100644 --- a/.github/workflows/build-scikit-image.yml +++ b/.github/workflows/build-scikit-image.yml @@ -104,7 +104,24 @@ jobs: # 0.26.0 shipped. Same class of bug as pytest<9.1 above (gotcha 339/355): pin the # test venv's numpy below the version that introduced the new deprecation, rather # than patch scikit-image's own library code. - CIBW_TEST_REQUIRES: pytest<9.1 numpy<2.5 + # + # Same class again, twice more (gotcha 339/355): + # - skimage/io/_plugins/pil_plugin.py:52 (pil_to_ndarray(), reached from + # io.imread()/io.MultiImage, exercised by test_multi_image.py's + # test_len/test_slicing/test_concatenate) calls the now-deprecated + # `Image.getdata()`. Pillow deprecated it in favor of `get_flattened_data()` + # in 12.1.0 (2026); scikit-image's pyproject.toml only requires pillow>=10.1 + # with no upper bound, so cibuildwheel resolves the latest available (12.3.0). + # - skimage/measure/fit.py:624 (CircleModel/EllipseModel._estimate(), reached + # from the CircleModel doctest) calls `scipy.spatial.minkowski_distance`, and + # skimage/transform/_thin_plate_splines.py:183 (ThinPlateSplineTransform._estimate(), + # reached from its own doctest) calls `scipy.spatial.distance_matrix` — both + # deprecated by SciPy in favor of `scipy.spatial.distance.minkowski`/`cdist` as + # of SciPy 1.18.0. scikit-image's pyproject.toml only requires scipy>=1.11.4 + # with no upper bound, so cibuildwheel resolves the latest available (1.18.1). + # Pin both test venv deps below the version that introduced their respective new + # deprecation, rather than patch scikit-image's own library code. + CIBW_TEST_REQUIRES: pytest<9.1 numpy<2.5 Pillow<12.1.0 scipy<1.18 - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: