Skip to content

Commit 18bcc2f

Browse files
authored
Add python-stretch 0.3.1 (#2717)
* Add python-stretch riscv64 wheel build python-stretch wraps the header-only Signalsmith Stretch C++ library with nanobind and builds a cp312-abi3 wheel via scikit-build-core. Upstream never tags releases, so the workflow pins the 0.3.1 release commit ac1fbfc, whose tree (with the include/stretch submodule at ffa4598) is byte-identical to the PyPI sdist apart from PKG-INFO. One abi3 build per libc on cp312, re-tested on cp313/cp314. musllinux runs a numpy-free smoke test since numpy has no musllinux riscv64 wheel. The wheel also ships the Signalsmith (MIT) and nanobind (BSD-3-Clause) notices for the code compiled into the extension. * python-stretch: fix musllinux smoke test expected interval Signalsmith's default preset at 44.1 kHz uses a 5292-sample block and a 1323-sample interval (input latency 2646); the first run asserted the latency value as the interval. * python-stretch: match both libc artifacts in the publish pattern The artifacts end in -manylinux_riscv64/-musllinux_riscv64, so the '-*-riscv64' glob matched neither and the publish dry-run found no wheels.
1 parent 0ec8790 commit 18bcc2f

2 files changed

Lines changed: 149 additions & 0 deletions

File tree

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# SPDX-FileCopyrightText: 2026 The RISE Project
2+
# SPDX-License-Identifier: MIT
3+
---
4+
# This workflow is based on upstream's own wheel build setup:
5+
# https://github.com/gregogiudici/python-stretch/blob/ac1fbfc9f5d6b912e2a9248d8e0f53888846588b/.github/workflows/wheels.yml
6+
# https://github.com/gregogiudici/python-stretch/blob/ac1fbfc9f5d6b912e2a9248d8e0f53888846588b/pyproject.toml
7+
name: Build python-stretch wheels (riscv64)
8+
9+
on:
10+
workflow_dispatch:
11+
inputs:
12+
version:
13+
description: 'Version glob to (re)build; empty builds every version of docs/packages/python-stretch.yaml not released yet'
14+
required: false
15+
default: ''
16+
pull_request:
17+
branches: [main]
18+
paths:
19+
- '.github/workflows/build-python-stretch.yml'
20+
- 'docs/packages/python-stretch.yaml'
21+
push:
22+
branches: [main]
23+
paths:
24+
- '.github/workflows/build-python-stretch.yml'
25+
- 'docs/packages/python-stretch.yaml'
26+
27+
concurrency:
28+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
29+
cancel-in-progress: true
30+
31+
permissions:
32+
contents: read # to fetch code (actions/checkout)
33+
34+
env:
35+
# Upstream releases without git tags; this is the 0.3.1 release commit, byte-identical
36+
# to the PyPI sdist (submodule included). Update alongside the version in the docs YAML.
37+
PYTHON_STRETCH_REF: ac1fbfc9f5d6b912e2a9248d8e0f53888846588b
38+
MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64
39+
MUSLLINUX_RISCV64_IMAGE: quay.io/pypa/musllinux_1_2_riscv64
40+
41+
jobs:
42+
setup:
43+
uses: $/.github/workflows/_setup.yml
44+
with:
45+
package: python-stretch
46+
version: ${{ inputs.version }}
47+
48+
build_wheels:
49+
needs: [setup]
50+
if: needs.setup.outputs.versions != '[]'
51+
name: Build python-stretch ${{ matrix.version }} cp312-abi3-${{ matrix.libc }}_riscv64
52+
runs-on: ubuntu-24.04-riscv
53+
strategy:
54+
fail-fast: false
55+
matrix:
56+
version: ${{ fromJSON(needs.setup.outputs.versions) }}
57+
libc: [manylinux, musllinux]
58+
include:
59+
- libc: manylinux
60+
test_requires: pytest numpy
61+
test_command: pytest {project}/tests
62+
# No musllinux riscv64 numpy wheel exists, and every process() call takes one.
63+
- libc: musllinux
64+
test_requires: ''
65+
test_command: >-
66+
python -c "import python_stretch as ps;
67+
s = ps.Signalsmith.Stretch();
68+
s.preset(2, 44100.0);
69+
s.setTimeFactor(0.5);
70+
s.setTransposeSemitones(12);
71+
assert (s.blockSamples(), s.intervalSamples(), s.inputLatency()) == (5292, 1323, 2646), (s.blockSamples(), s.intervalSamples(), s.inputLatency());
72+
print('python_stretch OK')"
73+
74+
env:
75+
PYTHON_STRETCH_VERSION: ${{ matrix.version }}
76+
77+
steps:
78+
- name: Checkout python-stretch ${{ env.PYTHON_STRETCH_VERSION }}
79+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
80+
with:
81+
repository: gregogiudici/python-stretch
82+
ref: ${{ env.PYTHON_STRETCH_REF }}
83+
submodules: true
84+
persist-credentials: false
85+
86+
- name: Check version
87+
run: grep -qx "version = \"${PYTHON_STRETCH_VERSION}\"" pyproject.toml
88+
89+
- name: Stage bundled licences
90+
run: |
91+
cp include/stretch/LICENSE.txt LICENSE.signalsmith-stretch.txt
92+
cp include/stretch/dsp/LICENSE.txt LICENSE.signalsmith-dsp.txt
93+
94+
- uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
95+
env:
96+
CIBW_BEFORE_BUILD: >-
97+
python -m pip install nanobind &&
98+
python -c "import importlib.metadata as m, shutil; shutil.copy(next(f.locate() for f in m.files('nanobind') if f.name == 'LICENSE'), '{project}/LICENSE.nanobind')"
99+
CIBW_ARCHS: riscv64
100+
CIBW_BUILD: >-
101+
cp312-${{ matrix.libc }}_riscv64
102+
cp313-${{ matrix.libc }}_riscv64
103+
cp314-${{ matrix.libc }}_riscv64
104+
CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }}
105+
CIBW_MUSLLINUX_RISCV64_IMAGE: ${{ env.MUSLLINUX_RISCV64_IMAGE }}
106+
CIBW_ENVIRONMENT: PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/
107+
CIBW_TEST_REQUIRES: ${{ matrix.test_requires }}
108+
CIBW_TEST_COMMAND: ${{ matrix.test_command }}
109+
110+
- name: Check the bundled licences made it into the wheel
111+
run: |
112+
python3 - wheelhouse/*.whl <<'EOF'
113+
import sys, zipfile
114+
expected = {"LICENSE", "LICENSE.signalsmith-stretch.txt", "LICENSE.signalsmith-dsp.txt", "LICENSE.nanobind"}
115+
for whl in sys.argv[1:]:
116+
names = zipfile.ZipFile(whl).namelist()
117+
found = {n.rsplit("/", 1)[1] for n in names if ".dist-info/licenses/" in n}
118+
assert expected <= found, f"{whl}: missing {expected - found}"
119+
assert "-cp312-abi3-" in whl, whl
120+
print(whl, sorted(found))
121+
EOF
122+
123+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
124+
with:
125+
name: python-stretch-${{ env.PYTHON_STRETCH_VERSION }}-cp312-abi3-${{ matrix.libc }}_riscv64
126+
path: ./wheelhouse/*.whl
127+
if-no-files-found: error
128+
129+
publish:
130+
name: Publish python-stretch ${{ matrix.version }}
131+
needs: [setup, build_wheels]
132+
if: needs.setup.outputs.versions != '[]'
133+
strategy:
134+
fail-fast: false
135+
matrix:
136+
version: ${{ fromJSON(needs.setup.outputs.versions) }}
137+
permissions:
138+
contents: write
139+
pull-requests: write
140+
uses: $/.github/workflows/_publish-wheel.yml
141+
secrets:
142+
app-private-key: ${{ secrets.RISEPROJECT_APP_PRIVATE_KEY }}
143+
with:
144+
artifact-pattern: python-stretch-${{ matrix.version }}-*riscv64

‎docs/packages/python-stretch.yaml‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package-name: python-stretch
2+
source-code: https://github.com/gregogiudici/python-stretch
3+
license: MIT
4+
versions:
5+
- version: 0.3.1

0 commit comments

Comments
 (0)