From 39ecfbd77a610c017ffa27e7b44d9e870df5ebe0 Mon Sep 17 00:00:00 2001 From: zacharyburnett Date: Mon, 6 Jul 2026 13:03:46 -0400 Subject: [PATCH 1/3] [SCSB-237] build Stable ABI3 wheels with `Py_LIMITED_API` --- .github/workflows/build.yml | 120 ++++++++++++++++++------------------ pyproject.toml | 5 ++ setup.py | 5 +- 3 files changed, 70 insertions(+), 60 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 48a8f447..0b15c704 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,68 +2,70 @@ name: build on: pull_request: - # We also want this workflow triggered if the 'Build all wheels' - # label is added or present when PR is updated - types: - - opened - - synchronize - - labeled - push: - branches: - - main - tags: - - "*" release: - types: - - released + types: [released] + workflow_dispatch: -permissions: - contents: read +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true -jobs: - build_quick: - # This ensures that a couple of targets work fine in pull requests - permissions: - contents: none - uses: OpenAstronomy/github-actions-workflows/.github/workflows/publish.yml@v3 - if: github.event_name == 'pull_request' - with: - upload_to_pypi: false - upload_to_anaconda: false - targets: | - - cp311-manylinux_x86_64 +permissions: {} +jobs: build: - # This job builds the wheels and publishes them to PyPI for all - # releases. For PRs with the "Build wheels" label, wheels are built, - # but are not uploaded to PyPI. - + strategy: + matrix: + runs-on: + - ubuntu-latest + - macos-latest + runs-on: ${{ matrix.runs-on }} + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + fetch-tags: true + fetch-depth: 0 + persist-credentials: false + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version: "3" + - if: ${{ runner.os == 'Linux' }} + uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0 + with: + platforms: all + - uses: pypa/cibuildwheel@294735312765b09d24a2fbec22660ce817587d55 # v4.1.0 + with: + package-dir: ./ + output-dir: dist/ + - run: pip install build + - run: python -m build --sdist + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: dist-${{ runner.os }}-${{ runner.arch }} + path: ./dist/ + publish: + if: (github.event_name == 'release') && (github.event.action == 'released') + needs: [build] + runs-on: ubuntu-latest permissions: - contents: none - - uses: OpenAstronomy/github-actions-workflows/.github/workflows/publish.yml@v3 - - if: ((github.event_name == 'release') && (github.event.action == 'released')) || contains(github.event.pull_request.labels.*.name, 'Build wheels') - with: - upload_to_pypi: ${{ (github.event_name == 'release') && (github.event.action == 'released') }} - - # BUG: https://github.com/spacetelescope/spherical_geometry/issues/244 - # BUG: https://github.com/spacetelescope/spherical_geometry/issues/245 - targets: | - # Linux wheels - - cp3*-manylinux_x86_64 - - cp3*-musllinux_x86_64 - # FIXME: https://github.com/spacetelescope/spherical_geometry/issues/247 - #- cp3*-manylinux_aarch64 - - # MacOS X wheels - we deliberately do not build universal2 wheels. - # Note that the arm64 wheels are not actually tested so we - # rely on local manual testing of these to make sure they are ok. - - cp3*macosx_x86_64 - - cp3*macosx_arm64 - - # Windows wheels - - cp3*win32 - - cp3*win_amd64 - secrets: - pypi_token: ${{ secrets.PYPI_TOKEN }} + id-token: write + attestations: write + # To add required reviewers before deployment, + # edit the protection rules in GitHub Settings: + # Settings > Environments > pypi > Add required reviewers + environment: + name: pypi + url: https://pypi.org/p/spherical_geometry + steps: + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: dist* + path: dist/ + merge-multiple: true + - uses: actions/attest@a1948c3f048ba23858d222213b7c278aabede763 # v4.1.1 + with: + subject-path: "dist/*" + # To upload to PyPI without a token, add this workflow file as a Trusted Publisher in the project settings on the PyPI website + - uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 + with: + password: ${{ secrets.PYPI_PASSWORD_STSCI_MAINTAINER }} diff --git a/pyproject.toml b/pyproject.toml index d6bb2d8f..581af4cd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,6 +41,11 @@ documentation = "http://spherical-geometry.readthedocs.io/" requires = ["setuptools>=61.2", "setuptools_scm[toml]>=3.6", "numpy>=2.0.0"] build-backend = "setuptools.build_meta" +[tool.cibuildwheel] +build = "cp311-*" # build for CPython 3.11 Stable API +skip = ["cp3??t-*"] # explicitly skip free-threaded builds +test-command = "python -c 'import spherical_geometry'" + [tool.setuptools] include-package-data = false license-files = ["licenses/*.rst"] diff --git a/setup.py b/setup.py index 6e3a0383..a81e27ec 100644 --- a/setup.py +++ b/setup.py @@ -86,7 +86,9 @@ def qd_config(arg): 'libraries': [], 'extra_link_args': [], 'extra_compile_args': [], - 'define_macros': [], + 'define_macros': [ + ("Py_LIMITED_API", 0x030B0000), # PY_VERSION_HEX for 3.11 + ], } @@ -116,4 +118,5 @@ def qd_config(arg): ext_modules=[ Extension('spherical_geometry.math_util', sources, **ext_info) ], + options={'bdist_wheel': {'py_limited_api': 'cp311'}}, ) From 3b2ba36119be1725f8f4c72674079160530a7ad2 Mon Sep 17 00:00:00 2001 From: zacharyburnett Date: Tue, 7 Jul 2026 13:32:08 -0400 Subject: [PATCH 2/3] conditional on GIL --- .github/workflows/build.yml | 2 +- pyproject.toml | 2 +- setup.py | 27 +++++++++++++++++---------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0b15c704..37d1a4b2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,6 +29,7 @@ jobs: - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: "3" + pip-install: build - if: ${{ runner.os == 'Linux' }} uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0 with: @@ -37,7 +38,6 @@ jobs: with: package-dir: ./ output-dir: dist/ - - run: pip install build - run: python -m build --sdist - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: diff --git a/pyproject.toml b/pyproject.toml index 581af4cd..7eb6983c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ build-backend = "setuptools.build_meta" [tool.cibuildwheel] build = "cp311-*" # build for CPython 3.11 Stable API -skip = ["cp3??t-*"] # explicitly skip free-threaded builds +skip = ["cp3*t-*"] # explicitly skip free-threaded builds test-command = "python -c 'import spherical_geometry'" [tool.setuptools] diff --git a/setup.py b/setup.py index a81e27ec..dccee1a4 100644 --- a/setup.py +++ b/setup.py @@ -2,11 +2,14 @@ # Licensed under a 3-clause BSD style license - see LICENSE.rst import os -import sys import shutil +import sys +import sysconfig from glob import glob -from setuptools import setup -from setuptools import Extension + +from setuptools import Extension, setup + +FREE_THREADED_PYTHON = sysconfig.get_config_var("Py_GIL_DISABLED") == 1 use_system_qd = os.environ.get('USE_SYSTEM_QD', '') have_windows = bool(sys.platform.startswith('win')) @@ -86,11 +89,13 @@ def qd_config(arg): 'libraries': [], 'extra_link_args': [], 'extra_compile_args': [], - 'define_macros': [ - ("Py_LIMITED_API", 0x030B0000), # PY_VERSION_HEX for 3.11 - ], + 'define_macros': [], } +if not FREE_THREADED_PYTHON: + ext_info["define_macros"].append(("Py_LIMITED_API", 0x030B0000)) # PY_VERSION_HEX for 3.11 + ext_info["py_limited_api"] = True + if not use_system_qd: sources += qd_sources @@ -114,9 +119,11 @@ def qd_config(arg): ext_info['language'] = 'c++' +SETUPTOOLS_OPTIONS = {} +if not FREE_THREADED_PYTHON: + SETUPTOOLS_OPTIONS["bdist_wheel"] = {"py_limited_api": "cp311"} + setup( - ext_modules=[ - Extension('spherical_geometry.math_util', sources, **ext_info) - ], - options={'bdist_wheel': {'py_limited_api': 'cp311'}}, + ext_modules=[Extension("spherical_geometry.math_util", sources, **ext_info)], + options=SETUPTOOLS_OPTIONS, ) From 6855bbf914256f33bfbbe0e611803cf7c3d4bb59 Mon Sep 17 00:00:00 2001 From: zacharyburnett Date: Tue, 7 Jul 2026 13:37:11 -0400 Subject: [PATCH 3/3] try free-threaded --- pyproject.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7eb6983c..3750b91a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,8 +42,10 @@ requires = ["setuptools>=61.2", "setuptools_scm[toml]>=3.6", "numpy>=2.0.0"] build-backend = "setuptools.build_meta" [tool.cibuildwheel] -build = "cp311-*" # build for CPython 3.11 Stable API -skip = ["cp3*t-*"] # explicitly skip free-threaded builds +build = [ + "cp311-*", # build for CPython 3.11 Stable API + "cp3*t-*", # build for free-threaded Python +] test-command = "python -c 'import spherical_geometry'" [tool.setuptools]