From a6af6eeb6a53c599365bc405539c1ec044fefb32 Mon Sep 17 00:00:00 2001 From: Nicholas Junge Date: Wed, 6 Nov 2024 14:15:22 +0100 Subject: [PATCH] Add a Python matrix to ensure the bindings build on all supported versions (#1871) Also contains a run of `pre-commit autoupdate`, and a bump of cibuildwheel to its latest tag for CPython 3.13 support. But, since we build for 3.10+ with SABI from 3.12 onwards, we don't even need a dedicated Python 3.13 build job or toolchain - the wheels from 3.12 can be reused. Simplifies some version-dependent logic around assembling the bazel build command in setup.py, and fixes a possible unbound local error in the toolchain patch context manager. --- .github/workflows/test_bindings.yml | 12 ++++++------ .github/workflows/wheels.yml | 2 +- .pre-commit-config.yaml | 6 +++--- setup.py | 22 ++++++++++++++-------- 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/.github/workflows/test_bindings.yml b/.github/workflows/test_bindings.yml index 436a8f90..b6ac9be8 100644 --- a/.github/workflows/test_bindings.yml +++ b/.github/workflows/test_bindings.yml @@ -8,23 +8,23 @@ on: jobs: python_bindings: - name: Test GBM Python bindings on ${{ matrix.os }} + name: Test GBM Python ${{ matrix.python-version }} bindings on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ ubuntu-latest, macos-latest, windows-latest ] + python-version: [ "3.10", "3.11", "3.12", "3.13" ] steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Set up Python 3.11 + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: - python-version: 3.11 + python-version: ${{ matrix.python-version }} - name: Install GBM Python bindings on ${{ matrix.os }} run: python -m pip install . - - name: Run bindings example on ${{ matrix.os }} - run: - python bindings/python/google_benchmark/example.py + - name: Run example on ${{ matrix.os }} under Python ${{ matrix.python-version }} + run: python bindings/python/google_benchmark/example.py diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 7544b247..b463ff83 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -53,7 +53,7 @@ jobs: platforms: all - name: Build wheels on ${{ matrix.os }} using cibuildwheel - uses: pypa/cibuildwheel@v2.20 + uses: pypa/cibuildwheel@v2.21.3 env: CIBW_BUILD: "cp310-* cp311-* cp312-*" CIBW_BUILD_FRONTEND: "build[uv]" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ef13c1da..2a51592e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,17 +1,17 @@ repos: - repo: https://github.com/keith/pre-commit-buildifier - rev: 7.1.2 + rev: 7.3.1 hooks: - id: buildifier - id: buildifier-lint - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.11.1 + rev: v1.13.0 hooks: - id: mypy types_or: [ python, pyi ] args: [ "--ignore-missing-imports", "--scripts-are-modules" ] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.6.1 + rev: v0.7.2 hooks: - id: ruff args: [ --fix, --exit-non-zero-on-fix ] diff --git a/setup.py b/setup.py index 1e4c0db7..238d9d89 100644 --- a/setup.py +++ b/setup.py @@ -3,6 +3,7 @@ import os import platform import re import shutil +import sys from pathlib import Path from typing import Any, Generator @@ -15,8 +16,7 @@ IS_LINUX = platform.system() == "Linux" # hardcoded SABI-related options. Requires that each Python interpreter # (hermetic or not) participating is of the same major-minor version. -version_tuple = tuple(int(i) for i in platform.python_version_tuple()) -py_limited_api = version_tuple >= (3, 12) +py_limited_api = sys.version_info >= (3, 12) options = {"bdist_wheel": {"py_limited_api": "cp312"}} if py_limited_api else {} @@ -43,10 +43,10 @@ def _maybe_patch_toolchains() -> Generator[None, None, None]: return "python.toolchain(" + callargs + ")" CIBW_LINUX = is_cibuildwheel() and IS_LINUX + module_bazel = Path("MODULE.bazel") + content: str = module_bazel.read_text() try: if CIBW_LINUX: - module_bazel = Path("MODULE.bazel") - content: str = module_bazel.read_text() module_bazel.write_text( re.sub( r"python.toolchain\(([\w\"\s,.=]*)\)", @@ -92,10 +92,16 @@ class BuildBazelExtension(build_ext.build_ext): def bazel_build(self, ext: BazelExtension) -> None: """Runs the bazel build to create the package.""" temp_path = Path(self.build_temp) - # omit the patch version to avoid build errors if the toolchain is not - # yet registered in the current @rules_python version. - # patch version differences should be fine. - python_version = ".".join(platform.python_version_tuple()[:2]) + if py_limited_api: + # We only need to know the minimum ABI version, + # since it is stable across minor versions by definition. + # The value here is calculated as the minimum of a) the minimum + # Python version required, and b) the stable ABI version target. + # NB: This needs to be kept in sync with [project.requires-python] + # in pyproject.toml. + python_version = "3.12" + else: + python_version = "{0}.{1}".format(*sys.version_info[:2]) bazel_argv = [ "bazel",