Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/CI-wheels.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
name: Build wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
Comment thread
benoit74 marked this conversation as resolved.
matrix:
os: [macos-26, windows-2025, ubuntu-26.04]

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Add a CI job building the documentation on every PR/push so this kind of breakage is caught automatically (#279)
- Add support for Python 3.15 (#281)
- Build wheels against the stable ABI (abi3) so a single wheel per platform covers all supported CPython versions (#263)

## [3.13.1] - 2026-10-05

Expand Down
31 changes: 31 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,11 @@ def can_sign_apple(self) -> bool:
]
)

@property
def can_use_limited_api(self) -> bool:
"""whether runtime can use ABIv3 (free-threaded cannot)"""
return not self.profiling and not sysconfig.get_config_var("Py_GIL_DISABLED")


config = Config()

Expand All @@ -403,6 +408,8 @@ def get_cython_extension() -> list[Extension]:
("CYTHON_USE_SYS_MONITORING", "0"),
]
compiler_directives.update(linetrace="true")
elif config.can_use_limited_api:
define_macros += [("Py_LIMITED_API", "0x030B0000")]

include_dirs: list[str] = []
library_dirs: list[str] = []
Expand Down Expand Up @@ -458,11 +465,30 @@ def get_cython_extension() -> list[Extension]:
extra_compile_args=extra_compile_args,
language="c++",
define_macros=define_macros,
py_limited_api=config.can_use_limited_api,
)
return cythonize([wrapper_extension], compiler_directives=compiler_directives)


class LibzimBuildExt(build_ext):

def get_ext_filename(self, ext_name):
# set proper filename for abi3 usage on all Python versions
filename = super().get_ext_filename(ext_name)

if not config.can_use_limited_api:
return filename

if config.platform == "Windows":
ext_path = Path(*ext_name.split("."))
return str(ext_path.with_suffix(".pyd"))
else:
ext_suffix = sysconfig.get_config_var("EXT_SUFFIX")
filename = (
filename[: -len(ext_suffix)] + ".abi3" + os.path.splitext(ext_suffix)[1]
)
return filename

def finalize_options(self):
"""Workaround for rpath bug in distutils for macOS"""
super().finalize_options()
Expand Down Expand Up @@ -637,4 +663,9 @@ def run(self):
"repair_win_wheel": RepairWindowsWheel,
},
ext_modules=ext_modules,
options=(
{"bdist_wheel": {"py_limited_api": "cp311"}}
if config.can_use_limited_api
else {}
),
)
Loading