From df2e9ff407878727d99d44f20d1b0debe639cf64 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 13 Oct 2026 14:10:56 +0000 Subject: [PATCH 1/2] Add riscv64 wheel build for pyvista-zstd 0.4.1 pyvista-zstd builds a small CMake C++ core (libpvzstd.so) that vendors and statically links zstd 1.5.7 from source, loaded via ctypes and tagged py3-none- (no CPython ABI dependency), so one cp312 build serves every interpreter. zstd is portable C with existing riscv64 precedent in this repo (zstd, zstandard, pyzstd). Adds a patch to carry the vendored Zstandard BSD licence into the wheel, matching the fix already applied to the python-zstd port. --- .github/workflows/build-pyvista-zstd.yml | 112 ++++++++++++++++++ docs/packages/pyvista-zstd.yaml | 5 + ...ed-Zstandard-licence-with-the-wheels.patch | 84 +++++++++++++ 3 files changed, 201 insertions(+) create mode 100644 .github/workflows/build-pyvista-zstd.yml create mode 100644 docs/packages/pyvista-zstd.yaml create mode 100644 patches/pyvista-zstd/0.4.1/0001-package-the-vendored-Zstandard-licence-with-the-wheels.patch diff --git a/.github/workflows/build-pyvista-zstd.yml b/.github/workflows/build-pyvista-zstd.yml new file mode 100644 index 000000000000..fa61b13a3fff --- /dev/null +++ b/.github/workflows/build-pyvista-zstd.yml @@ -0,0 +1,112 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# Based on upstream's own wheel-building job: +# https://github.com/pyvista/pyvista-zstd/blob/v0.4.1/.github/workflows/ci_cd.yml +name: Build pyvista-zstd wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'Version glob to (re)build; empty builds every version of docs/packages/pyvista-zstd.yaml not released yet' + required: false + default: '' + pull_request: + branches: [main] + paths: + - '.github/workflows/build-pyvista-zstd.yml' + - 'docs/packages/pyvista-zstd.yaml' + - 'patches/pyvista-zstd/**' + push: + branches: [main] + paths: + - '.github/workflows/build-pyvista-zstd.yml' + - 'docs/packages/pyvista-zstd.yaml' + - 'patches/pyvista-zstd/**' + +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: pyvista-zstd + version: ${{ inputs.version }} + + build_wheels: + needs: [setup] + if: needs.setup.outputs.versions != '[]' + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + name: Build pyvista-zstd ${{ matrix.version }} py3-none-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 90 + + env: + PYVISTA_ZSTD_VERSION: ${{ matrix.version }} + + steps: + - name: Checkout pyvista-zstd v${{ env.PYVISTA_ZSTD_VERSION }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: pyvista/pyvista-zstd + ref: v${{ env.PYVISTA_ZSTD_VERSION }} + fetch-depth: 0 + persist-credentials: false + + - name: Checkout python-wheels + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + path: python-wheels + persist-credentials: false + + - name: Patch pyvista-zstd source + run: git apply python-wheels/patches/pyvista-zstd/${{ env.PYVISTA_ZSTD_VERSION }}/*.patch + + - name: Build wheel + uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0 + with: + output-dir: wheelhouse/ + # Wheels are py3-none-, so one build serves every interpreter. + only: cp312-manylinux_riscv64 + env: + CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} + CIBW_ENVIRONMENT: PVZSTD_BUILD_CORE=1 + CIBW_TEST_COMMAND: > + python -c + "from pyvista_zstd import _capi; + print('C++ core loaded from', _capi.library_path())" + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: pyvista-zstd-${{ env.PYVISTA_ZSTD_VERSION }}-py3-none-manylinux_riscv64 + path: wheelhouse/*.whl + if-no-files-found: error + + publish: + name: Publish pyvista-zstd ${{ 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: pyvista-zstd-${{ matrix.version }}-*-manylinux_riscv64 diff --git a/docs/packages/pyvista-zstd.yaml b/docs/packages/pyvista-zstd.yaml new file mode 100644 index 000000000000..0c6200e32d76 --- /dev/null +++ b/docs/packages/pyvista-zstd.yaml @@ -0,0 +1,5 @@ +package-name: pyvista-zstd +source-code: https://github.com/pyvista/pyvista-zstd +license: MIT +versions: +- version: 0.4.1 diff --git a/patches/pyvista-zstd/0.4.1/0001-package-the-vendored-Zstandard-licence-with-the-wheels.patch b/patches/pyvista-zstd/0.4.1/0001-package-the-vendored-Zstandard-licence-with-the-wheels.patch new file mode 100644 index 000000000000..90cb9cdc3b50 --- /dev/null +++ b/patches/pyvista-zstd/0.4.1/0001-package-the-vendored-Zstandard-licence-with-the-wheels.patch @@ -0,0 +1,84 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Tue, 13 Oct 2026 14:08:52 +0000 +Subject: [PATCH] package the vendored Zstandard licence with the wheels + +Upstream-Status: To upstream [not yet submitted; same gap as the python-zstd case already fixed in this repo (patches/zstd/1.5.7.2), needs a maintainer discussion rather than a drive-by PR] + +cpp/CMakeLists.txt's PVZSTD_VENDOR_ZSTD path fetches and statically links +zstd 1.5.7's source into libpvzstd.so, but pyproject.toml's license-files +only lists the wrapper's own LICENSE. The resulting wheel redistributes +Zstandard in binary form without the copyright notice its BSD licence +requires to travel with it. + +Add zstd 1.5.7's own LICENSE at the project root and list it explicitly: +license-files has no default glob behind it (PEP 639), so the new file +would otherwise ship nowhere. +--- + LICENSE.zstd | 30 ++++++++++++++++++++++++++++++ + MANIFEST.in | 1 + + pyproject.toml | 2 +- + 3 files changed, 32 insertions(+), 1 deletion(-) + create mode 100644 LICENSE.zstd + +diff --git a/LICENSE.zstd b/LICENSE.zstd +new file mode 100644 +index 0000000..7580028 +--- /dev/null ++++ b/LICENSE.zstd +@@ -0,0 +1,30 @@ ++BSD License ++ ++For Zstandard software ++ ++Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without modification, ++are permitted provided that the following conditions are met: ++ ++ * Redistributions of source code must retain the above copyright notice, this ++ list of conditions and the following disclaimer. ++ ++ * Redistributions in binary form must reproduce the above copyright notice, ++ this list of conditions and the following disclaimer in the documentation ++ and/or other materials provided with the distribution. ++ ++ * Neither the name Facebook, nor Meta, nor the names of its contributors may ++ be used to endorse or promote products derived from this software without ++ specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +diff --git a/MANIFEST.in b/MANIFEST.in +index 60ed217..7e1c60b 100644 +--- a/MANIFEST.in ++++ b/MANIFEST.in +@@ -1,6 +1,7 @@ + # The C++ sources are the library; a source install cannot build without them. + graft cpp + include LICENSE ++include LICENSE.zstd + include README.rst + recursive-include tests *.py + recursive-include doc/format *.md +diff --git a/pyproject.toml b/pyproject.toml +index d168146..3d005d4 100644 +--- a/pyproject.toml ++++ b/pyproject.toml +@@ -22,7 +22,7 @@ dependencies = ["pyvista>=0.45.0", "tqdm>=4.0.0"] + description = "VTK zstandard compression library." + dynamic = ["version"] + license = "MIT" +-license-files = ["LICENSE"] ++license-files = ["LICENSE", "LICENSE.zstd"] + name = "pyvista-zstd" + readme = "README.rst" + requires-python = ">=3.10" From 94e9d312fedf494972368895ab72412f9c6afc70 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 23 Oct 2026 16:31:47 +0000 Subject: [PATCH 2/2] pyvista-zstd: pin the version and resolve test deps from our registry Applying the licence patch leaves the v0.4.1 checkout dirty, so setuptools_scm versioned the wheel 0.4.2.dev0+ge3cbe68.d20261014 instead of 0.4.1. Pin it with SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYVISTA_ZSTD and drop the fetch-depth: 0 that only existed to reach the tag. The test install then failed with ResolutionImpossible: pyvista needs vtk, which has no riscv64 wheel on PyPI. Add our registry as an extra index (it carries vtk 9.7.1 for cp312), and set PIP_PREFER_BINARY for the test phase so numpy and matplotlib resolve to our wheels rather than building PyPI's newer sdist-only releases from source; pyvista-validation, which has no riscv64 wheel anywhere, still builds from its sdist. --- .github/workflows/build-pyvista-zstd.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-pyvista-zstd.yml b/.github/workflows/build-pyvista-zstd.yml index fa61b13a3fff..cd160f8f13e0 100644 --- a/.github/workflows/build-pyvista-zstd.yml +++ b/.github/workflows/build-pyvista-zstd.yml @@ -62,7 +62,6 @@ jobs: with: repository: pyvista/pyvista-zstd ref: v${{ env.PYVISTA_ZSTD_VERSION }} - fetch-depth: 0 persist-credentials: false - name: Checkout python-wheels @@ -82,7 +81,11 @@ jobs: only: cp312-manylinux_riscv64 env: CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} - CIBW_ENVIRONMENT: PVZSTD_BUILD_CORE=1 + CIBW_ENVIRONMENT: >- + PVZSTD_BUILD_CORE=1 + SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYVISTA_ZSTD=${{ env.PYVISTA_ZSTD_VERSION }} + PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ + CIBW_TEST_ENVIRONMENT: PIP_PREFER_BINARY=1 CIBW_TEST_COMMAND: > python -c "from pyvista_zstd import _capi;