Skip to content

Commit 94e8390

Browse files
authored
ENH: abi3 (cbrnr#251)
* ENH: abi3 * FIX: More * FIX: Ref * FIX: Wheel tag * FIX: Ig * FIX: Move on * FIX: Ver * FIX: Non seq * FIX: Naming * FIX: Append * FIX: Verbose * MAINT: Only test emulated on main * FIX: More * FIX: maybe * FIX: Name * FIX: More * FIX: Fixes * FIX: Cleaner * FIX: Missed * FIX: More * FIX: Add * FIX: Name * FIX: Cov
1 parent f358ca7 commit 94e8390

11 files changed

+241
-103
lines changed

.coveragerc

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[run]
2+
branch = True
3+
source = sleepecg
4+
omit =
5+
*/examples/*
6+
*/setup.py
7+
8+
[report]
9+
exclude_lines =
10+
pragma: no cover
11+
if __name__ == .__main__.:
12+
@abstractmethod
13+
@abstractclassmethod

.github/workflows/cibuildwheel.yml

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
name: Test
2+
concurrency:
3+
group: ${{ github.workflow }}-${{ github.event.number }}-${{ github.event.ref }}
4+
cancel-in-progress: true
5+
6+
on:
7+
pull_request:
8+
paths-ignore:
9+
- 'docs/**'
10+
push:
11+
branches:
12+
- main
13+
release:
14+
types:
15+
- published
16+
17+
jobs:
18+
style:
19+
name: Check style
20+
runs-on: ubuntu-22.04
21+
timeout-minutes: 2
22+
steps:
23+
- uses: actions/checkout@v4
24+
- uses: actions/setup-python@v5
25+
with:
26+
python-version: '3.12'
27+
- uses: pre-commit/action@v3.0.1
28+
29+
build_wheels:
30+
needs: style
31+
strategy:
32+
matrix:
33+
os: [ubuntu-22.04, windows-2022, macos-15, macos-13]
34+
arch: [native]
35+
include:
36+
- os: ubuntu-22.04
37+
arch: aarch64
38+
fail-fast: false
39+
timeout-minutes: 15 # Linux ~1 min, Windows ~4 min, aarch64 emulated ~8 min with tests (~3 min without)
40+
name: cibuildwheel (${{ matrix.os }} ${{ matrix.arch }})
41+
runs-on: ${{ matrix.os }}
42+
steps:
43+
- uses: actions/checkout@v4
44+
- name: Set wheel tests to be skipped on emulated archs on PRs
45+
run: |
46+
if [[ "${{ github.event_name }}" == "pull_request" ]] && [[ "${{ matrix.arch }}" == "aarch64" ]]; then
47+
echo "CIBW_TEST_SKIP=*" | tee -a $GITHUB_ENV
48+
fi
49+
shell: bash
50+
# For aarch64 support https://cibuildwheel.pypa.io/en/stable/faq/#emulation
51+
- uses: docker/setup-qemu-action@v3
52+
with:
53+
platforms: all
54+
if: runner.os == 'Linux' && matrix.arch == 'aarch64'
55+
- name: Build wheels and run tests
56+
uses: pypa/cibuildwheel@v2.22.0
57+
env:
58+
CIBW_ARCHS: ${{ matrix.arch }}
59+
- uses: actions/upload-artifact@v4
60+
with:
61+
name: artifact-${{ matrix.os }}-${{ matrix.arch }}
62+
path: ./wheelhouse/*.whl
63+
64+
test:
65+
needs: build_wheels
66+
strategy:
67+
matrix:
68+
os: [ubuntu-22.04, windows-2022, macos-15, macos-13]
69+
python-version: ['3.12']
70+
include:
71+
- os: ubuntu-22.04
72+
python-version: '3.13'
73+
fail-fast: false
74+
name: Test wheels (${{ matrix.os }} py${{ matrix.python-version }})
75+
runs-on: ${{ matrix.os }}
76+
timeout-minutes: 5
77+
defaults:
78+
run:
79+
shell: bash -eo pipefail {0}
80+
steps:
81+
- uses: actions/checkout@v4
82+
- uses: actions/setup-python@v5
83+
with:
84+
python-version: ${{ matrix.python-version }}
85+
- uses: actions/download-artifact@v4
86+
with:
87+
pattern: artifact-${{ matrix.os }}-native
88+
merge-multiple: true
89+
path: dist
90+
- run: ls -al dist
91+
- name: Triage dependencies
92+
run: |
93+
if [[ "${{ matrix.python-version }}" != "3.13" ]]; then
94+
echo "PIP_EXTRA=wfdb numpy<2 numba pytest-error-for-skips" | tee -a $GITHUB_ENV
95+
echo "PYTEST_EXTRA=--error-for-skips" | tee -a $GITHUB_ENV
96+
fi
97+
- run: python -m pip install ./dist/*.whl pytest pytest-cov edfio $PIP_EXTRA --only-binary="numpy,numba,edfio"
98+
- run: pytest -rfEXs --cov=sleepecg --cov-report=xml --tb=short --cov-branch --color=yes $PYTEST_EXTRA tests/
99+
- uses: codecov/codecov-action@v5
100+
with:
101+
token: ${{ secrets.CODECOV_TOKEN }}
102+
if: success() || failure()
103+
104+
build_sdist:
105+
needs: style
106+
name: Build source distribution
107+
runs-on: ubuntu-22.04
108+
steps:
109+
- uses: actions/checkout@v4
110+
- uses: actions/setup-python@v5
111+
name: Install Python
112+
with:
113+
python-version: 3.12
114+
- name: Build sdist
115+
run: |
116+
set -eo pipefail
117+
python -m pip install build numpy
118+
python -m build --sdist
119+
- uses: actions/upload-artifact@v4
120+
with:
121+
name: artifact-sdist
122+
path: dist/*.tar.gz
123+
124+
check_wheels:
125+
needs: [build_wheels, build_sdist]
126+
name: Check wheels and source distribution
127+
runs-on: ubuntu-22.04
128+
steps:
129+
- uses: actions/download-artifact@v4
130+
with:
131+
pattern: artifact-*
132+
merge-multiple: true
133+
path: dist
134+
- run: ls -al dist
135+
shell: bash
136+
- uses: actions/setup-python@v5
137+
with:
138+
python-version: 3.12
139+
- run: python -m pip install twine
140+
- run: python -m twine check --strict dist/*
141+
142+
upload-pypi:
143+
name: Upload to PyPI
144+
needs: [check_wheels, test]
145+
runs-on: ubuntu-latest
146+
if: github.event_name == 'release'
147+
steps:
148+
- uses: actions/download-artifact@v4
149+
with:
150+
pattern: artifact-*
151+
merge-multiple: true
152+
path: dist
153+
- uses: pypa/gh-action-pypi-publish@v1.12.3

.github/workflows/release.yml

-63
This file was deleted.

.github/workflows/test.yml

-33
This file was deleted.

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@
66
__pycache__/
77
site/
88
sleepecg.egg-info/
9+
/build
10+
/coverage.xml
11+
/.coverage

codecov.yml

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
comment: false
2+
github_checks: # too noisy, even though "a" interactively disables them
3+
annotations: false
4+
5+
codecov:
6+
notify:
7+
require_ci_to_pass: false
8+
9+
coverage:
10+
status:
11+
patch:
12+
default:
13+
informational: true
14+
target: 95%
15+
if_no_uploads: error
16+
if_not_found: success
17+
if_ci_failed: failure
18+
project:
19+
default: false
20+
library:
21+
informational: true
22+
target: 90%
23+
if_no_uploads: error
24+
if_not_found: success
25+
if_ci_failed: failure

pyproject.toml

+17-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[build-system]
2-
requires = ["setuptools", "setuptools-scm", "numpy"]
2+
requires = ["setuptools", "setuptools-scm", "wheel", "numpy>=2,<3"]
33
build-backend = "setuptools.build_meta"
44

55
[project]
@@ -11,7 +11,7 @@ authors = [
1111
{name = "Clemens Brunner", email = "clemens.brunner@gmail.com"},
1212
]
1313
readme = "README.md"
14-
requires-python = ">= 3.9, < 3.13"
14+
requires-python = ">= 3.9"
1515
classifiers = [
1616
"License :: OSI Approved :: BSD License",
1717
"Operating System :: Microsoft :: Windows",
@@ -27,7 +27,7 @@ classifiers = [
2727
]
2828
keywords = ["sleep", "ecg", "qrs", "peak"]
2929
dependencies = [
30-
"numpy >= 1.25.0, < 2.0.0",
30+
"numpy >= 1.25.0, < 3.0.0",
3131
"PyYAML >= 5.4.0",
3232
"requests >= 2.25.0",
3333
"scipy >= 1.7.0",
@@ -64,6 +64,8 @@ cibw = [ # cibuildwheel uses this for running the test suite
6464
"edfio >= 0.4.0",
6565
"numba >= 0.59.1",
6666
"wfdb >= 3.4.0",
67+
# https://github.com/MIT-LCP/wfdb-python/pull/511
68+
"numpy < 2.0.0", # TODO: just for wfdb!
6769
]
6870

6971
[project.urls]
@@ -77,6 +79,14 @@ test-requires = "pytest"
7779
test-extras = "cibw"
7880
test-command = "pytest {package}"
7981
skip = 'pp* *musllinux*'
82+
build = "cp39-*" # abi3
83+
84+
[[tool.cibuildwheel.overrides]]
85+
select = "*"
86+
inherit.repair-wheel-command = "append"
87+
repair-wheel-command = [
88+
"pipx run abi3audit --strict --report {wheel}",
89+
]
8090

8191
[tool.cibuildwheel.linux]
8292
manylinux-x86_64-image = "manylinux2014"
@@ -87,6 +97,10 @@ archs = "x86_64 arm64"
8797

8898
[tool.cibuildwheel.windows]
8999
archs = "AMD64"
100+
before-build = "pip install delvewheel"
101+
repair-wheel-command = [
102+
"delvewheel repair -w {dest_dir} {wheel}",
103+
]
90104

91105
[tool.mypy]
92106
ignore_missing_imports = true

setup.py

+22
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,34 @@
11
import numpy as np
22
from setuptools import Extension, setup
3+
from wheel.bdist_wheel import bdist_wheel
4+
5+
# Following https://github.com/joerick/python-abi3-package-sample
6+
7+
8+
# Currently set to 3.9. If this is bumped for example to 3.10, the hex
9+
# in the Extension needs to change to 0x030A0000, and the cibuildwheel `build`
10+
# selector needs to change in pyproject.toml
11+
12+
class bdist_wheel_abi3(bdist_wheel):
13+
def get_tag(self) -> tuple:
14+
python, abi, plat = super().get_tag()
15+
16+
if python.startswith("cp"):
17+
# on CPython, our wheels are abi3 and compatible back to 3.6
18+
return "cp39", "abi3", plat
19+
20+
return python, abi, plat
21+
322

423
setup(
524
ext_modules=[
625
Extension(
726
"sleepecg._heartbeat_detection",
827
["src/sleepecg/_heartbeat_detection.c"],
928
include_dirs=[np.get_include()],
29+
define_macros=[("Py_LIMITED_API", "0x03090000")],
30+
py_limited_api=True,
1031
),
1132
],
33+
cmdclass={"bdist_wheel": bdist_wheel_abi3},
1234
)

0 commit comments

Comments
 (0)