From 6b90e1d3cc81890bae7ce47244c51c1f723e41d3 Mon Sep 17 00:00:00 2001 From: Jordan Borean Date: Tue, 9 Dec 2025 05:38:32 +1000 Subject: [PATCH] Add Free-Threading and Limited API/Stable ABI Add support for building wheels with the free-threaded interpreter and also with the limited API/stable ABI on Python 3.11+. There is limited testing for the free-threading setup but this become usable for people running on that interpreter without reverting back to locking the GIL. --- .github/workflows/ci.yml | 87 +++++++++++++------------------ .github/workflows/deploy-docs.yml | 4 +- .github/workflows/stale.yml | 2 +- README.txt | 12 +++++ pyproject.toml | 2 +- setup.py | 34 +++++++++++- 6 files changed, 85 insertions(+), 56 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eff23d9..17ca806 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,10 +11,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Select python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.12 @@ -28,7 +28,7 @@ jobs: GSSAPI_COMPILER_ARGS: '' - name: Upload sdist - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: artifact-sdist path: ./dist/*.tar.gz @@ -43,47 +43,31 @@ jobs: fail-fast: false matrix: include: - - os: macOS-13 - version: cp314-macosx_x86_64 - prerelease: true - - os: macOS-15 - version: cp314-macosx_arm64 - prerelease: true - - os: macOS-13 - version: cp313-macosx_x86_64 - - os: macOS-15 - version: cp313-macosx_arm64 - - os: macOS-13 - version: cp312-macosx_x86_64 - - os: macOS-15 - version: cp312-macosx_arm64 - - os: macOS-13 + # Free-threading does not support Limited API/Stable ABI yet + # 3.11+ can use the Limited API/Stable ABI + - os: macos-15-intel + version: cp314t-macosx_x86_64 + - os: macos-15 + version: cp314t-macosx_arm64 + + - os: macos-15-intel version: cp311-macosx_x86_64 - - os: macOS-15 + - os: macos-15 version: cp311-macosx_arm64 - - os: macOS-13 + - os: macos-15-intel version: cp310-macosx_x86_64 - - os: macOS-15 + - os: macos-15 version: cp310-macosx_arm64 - - os: macOS-13 + - os: macos-15-intel version: cp39-macosx_x86_64 - - os: macOS-15 + - os: macos-15 version: cp39-macosx_arm64 - os: windows-2022 - version: cp314-win_amd64 - prerelease: true + version: cp314t-win_amd64 - os: windows-2022 - version: cp314-win32 - prerelease: true - - os: windows-2022 - version: cp313-win_amd64 - - os: windows-2022 - version: cp313-win32 - - os: windows-2022 - version: cp312-win_amd64 - - os: windows-2022 - version: cp312-win32 + version: cp314t-win32 + - os: windows-2022 version: cp311-win_amd64 - os: windows-2022 @@ -113,7 +97,7 @@ jobs: echo "C:\Program Files${{ endsWith(matrix.version, '-win32') && ' (x86)' || '' }}\MIT\Kerberos\bin;$PATH" >> $GITHUB_PATH - name: Download gssapi sdist - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v6 with: name: artifact-sdist path: ./ @@ -127,14 +111,14 @@ jobs: rm gssapi-*.tar.gz - name: Build wheel - uses: pypa/cibuildwheel@v3.1.4 + uses: pypa/cibuildwheel@v3.3.0 env: CIBW_BUILD: ${{ matrix.version }} CIBW_BUILD_VERBOSITY: 1 CIBW_PRERELEASE_PYTHONS: ${{ matrix.prerelease || 'false' }} - name: Upload wheel - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: path: ./wheelhouse/*.whl name: artifact-wheel-${{ matrix.version }} @@ -147,7 +131,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Download gssapi sdist - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v6 with: name: artifact-sdist path: ./dist @@ -204,10 +188,10 @@ jobs: steps: - name: Check out code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Download built project - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v6 with: pattern: artifact-* merge-multiple: true @@ -230,6 +214,7 @@ jobs: fail-fast: false matrix: name: + - win-py-3.14t - win-py-3.14 - win-py-3.13 - win-py-3.12 @@ -240,8 +225,10 @@ jobs: - x64 - x86 include: + - name: win-py-3.14t + pyenv: '3.14t' - name: win-py-3.14 - pyenv: '3.14.0-rc.2' + pyenv: '3.14' - name: win-py-3.13 pyenv: '3.13' - name: win-py-3.12 @@ -255,17 +242,17 @@ jobs: steps: - name: Check out code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Download built project - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v6 with: pattern: artifact-* merge-multiple: true path: ./dist - name: Install the right python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.pyenv }} architecture: ${{ matrix.arch }} @@ -284,10 +271,10 @@ jobs: runs-on: macos-latest steps: - name: Check out code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Download built project - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v6 with: pattern: artifact-* merge-multiple: true @@ -316,10 +303,10 @@ jobs: steps: - name: Check out code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Download built project - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v6 with: pattern: artifact-* merge-multiple: true @@ -339,7 +326,7 @@ jobs: run: echo "checksum=`ls tag_build/*.sha512sum | awk -F/ '{print $2}'`" >> $GITHUB_OUTPUT - name: Upload tagged build artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: path: tag_build/${{ steps.tarball.outputs.tarball }} name: release-asset diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index de3384e..939cd74 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -8,10 +8,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Select python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.12 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index f3fffc4..ff6427b 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/stale@v9.1.0 + - uses: actions/stale@v10.1.1 id: stale with: days-before-stale: -1 diff --git a/README.txt b/README.txt index ddd5734..0962f17 100644 --- a/README.txt +++ b/README.txt @@ -161,6 +161,18 @@ In addition to RFC 2743/2744, Python-GSSAPI also has support for: * Kerberos specific extensions +Python Free-Threading (PEP 779) +------------------------------- + +This library supports Python Free-Threading and will build +free-threading-compatible extension files if installed under a free-threading +interpreter. Python 3.14t is tested in CI and a wheel will be created for +3.14t+. Python 3.13t is not officially tested or supported but may or may not +work. There is limited testing for free-threading in this library and it does +not aim to be thread safe out of the box. If you encounter any issues or +problems with this scenario please raise an issue and we can look at possible +options to fix this. + The Team ======== diff --git a/pyproject.toml b/pyproject.toml index 3de21b8..53f1c77 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [build-system] requires = [ - "Cython == 3.1.3", + "Cython == 3.2.1", "setuptools >= 40.6.0", # Start of PEP 517 support for setuptools ] build-backend = "setuptools.build_meta" diff --git a/setup.py b/setup.py index ad9b543..75ad2a3 100755 --- a/setup.py +++ b/setup.py @@ -3,6 +3,7 @@ import platform import re import sys +import sysconfig import os import shutil import shlex @@ -18,6 +19,17 @@ from Cython.Build import cythonize # noqa: E402 +# Enable limited API for Python 3.11+ +USE_LIMITED_API = sys.version_info >= (3, 11) +LIMITED_API_VERSION = 0x030B0000 # Python 3.11 ABI + +IS_FREE_THREADED = False +if sysconfig.get_config_var("Py_GIL_DISABLED") == 1: + # Free-threaded Python does not support the limited API. + USE_LIMITED_API = False + IS_FREE_THREADED = True + + def get_output(*args, **kwargs): res = subprocess.check_output(*args, shell=True, **kwargs) decoded = res.decode('utf-8') @@ -215,6 +227,11 @@ def make_extension(name_fmt, module, **kwargs): source = name_fmt.replace('.', '/') % module + '.pyx' if not os.path.exists(source): raise OSError(source) + + define_macros = kwargs.pop('define_macros', []) + if USE_LIMITED_API: + define_macros.append(('Py_LIMITED_API', LIMITED_API_VERSION)) + return Extension( name_fmt % module, extra_link_args=link_args, @@ -222,6 +239,8 @@ def make_extension(name_fmt, module, **kwargs): library_dirs=library_dirs, libraries=libraries, sources=[source], + define_macros=define_macros, + py_limited_api=USE_LIMITED_API, **kwargs ) @@ -264,7 +283,12 @@ def gssapi_modules(lst): # add in any present enum extension files res.extend(ENUM_EXTS) - return cythonize(res, language_level=2) + compiler_directives = {} + if IS_FREE_THREADED: + # Enable free-threading support in Cython + compiler_directives["freethreading_compatible"] = True + + return cythonize(res, language_level=2, compiler_directives=compiler_directives) long_desc = re.sub(r'\.\. role:: \w+\(code\)\s*\n\s*.+', '', @@ -276,9 +300,13 @@ def gssapi_modules(lst): 'decorator', ] +setup_options = {} +if USE_LIMITED_API: + setup_options["bdist_wheel"] = {"py_limited_api": "cp311"} + setup( name='gssapi', - version='1.10.1', + version='1.11.0', author='The Python GSSAPI Team', author_email='jborean93@gmail.com', packages=['gssapi', 'gssapi.raw', 'gssapi.raw._enum_extensions', @@ -304,6 +332,7 @@ def gssapi_modules(lst): 'Programming Language :: Python :: 3.12', 'Programming Language :: Python :: 3.13', 'Programming Language :: Python :: 3.14', + "Programming Language :: Python :: Free Threading :: 2 - Beta" 'Intended Audience :: Developers', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Cython', @@ -344,6 +373,7 @@ def gssapi_modules(lst): extension_file('krb5', 'gss_krb5_ccache_name'), ]), + options=setup_options, keywords=['gssapi', 'security'], install_requires=install_requires )