Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
14e8ad8
chore: fail fast and clearly when Py_LIMITED_API is defined
henryiii Oct 7, 2026
39c0c2e
chore: add a stable-ABI tag to PYBIND11_INTERNALS_ID and PYBIND11_MOD…
henryiii Oct 7, 2026
27629ed
refactor: add detail::get_bases()/get_mro() and use them instead of t…
henryiii Oct 7, 2026
a865adc
refactor: add detail::get_tp_name()/tp_name_equals() and use them ins…
henryiii Oct 7, 2026
d0e4536
refactor: add detail::type_lookup() and use it instead of _PyType_Lookup
henryiii Oct 7, 2026
cff7bfa
refactor: add PYBIND11_HAS_DIRECT_STRUCT_ACCESS for the struct-access…
henryiii Oct 7, 2026
c6ad3df
refactor: replace PyTuple/PyList/PyByteArray/PyCFunction macro accessors
henryiii Oct 7, 2026
7f7584e
refactor: forward to type/property slots through PyType_GetSlot()
henryiii Oct 7, 2026
b672a8f
refactor: wrap instance tp_alloc/tp_free and the __dict__ slot pointer
henryiii Oct 7, 2026
651af12
feat: support the Python stable ABI (Py_LIMITED_API >= 0x030C0000)
henryiii Oct 7, 2026
4bddb32
feat(cmake): add STABLE_ABI to pybind11_add_module()
henryiii Oct 7, 2026
3160e95
feat(setup_helpers): Pybind11Extension(py_limited_api=True)
henryiii Oct 7, 2026
457d050
ci: build and test the suite for the stable ABI
henryiii Oct 7, 2026
28b56e5
docs: describe stable ABI (abi3) support
henryiii Oct 7, 2026
f7caed3
fix(cmake): export SABIModule target and Python_SOSABI to callers
henryiii Oct 7, 2026
e6a7932
feat: support the free-threaded stable ABI (abi3t, CPython 3.15+)
henryiii Oct 8, 2026
7408676
feat(numpy): support numpy.h under the abi3t stable ABI
henryiii Oct 8, 2026
090bb27
feat(chrono): support chrono.h under the stable ABI
henryiii Oct 8, 2026
731a66f
perf(stable-abi): use the default type getattro under the limited API
henryiii Oct 8, 2026
6001633
perf(stable-abi): bind methods with PyObject_Vectorcall
henryiii Oct 8, 2026
65fa5bf
refactor(stable-abi): share type attribute, slot and spec helpers
henryiii Oct 8, 2026
f4d6e40
fix(stable-abi): gate 3.13+ API use on Py_LIMITED_API, not the headers
henryiii Oct 8, 2026
c4deb0b
perf(stable-abi): make instancemethod a vectorcall method descriptor
henryiii Oct 8, 2026
5510456
fix(chrono): import the datetime C API per translation unit
henryiii Oct 8, 2026
203ee17
fix(stable-abi): keep instance lookup safe across critical-section su…
henryiii Oct 8, 2026
a33955e
test(stable-abi): check the method-descriptor flag only under the lim…
henryiii Oct 8, 2026
6bfd92f
fix(cmake): do not link libpython into SHARED STABLE_ABI libraries
henryiii Oct 8, 2026
ce9fb4d
ci(stable-abi): resolve forward-test ignores relative to build/tests
henryiii Oct 8, 2026
c5bbfd0
fix(pypy): use the accessors PyPy provides
henryiii Oct 8, 2026
d9fc94b
fix: MSVC C4456 shadowing and clang-tidy macro parentheses
henryiii Oct 8, 2026
0e8dc09
feat: build abi3t from GIL-enabled Python; fix stable ABI CI failures
henryiii Oct 8, 2026
7387dbb
fix(stable-abi): Windows abi3t export symbol, MSVC C4702, .pyd name c…
henryiii Oct 8, 2026
e7d0de5
docs: describe the scikit-build-core stable ABI setup
henryiii Oct 8, 2026
7310033
fix(stable-abi): gate PyDict_*Ref helpers on the limited API version
henryiii Oct 8, 2026
10f4e8f
fix(stable-abi): address review findings
henryiii Oct 10, 2026
f0fd847
fix(stable-abi): repair the rebase onto master
henryiii Oct 29, 2026
6e5f221
fix(stable-abi): match the C API for datetime fields and __complex__ …
henryiii Oct 29, 2026
104cd87
fix(stable-abi): consume WITH_SOABI and look __complex__ up on the type
henryiii Oct 29, 2026
b1fe56d
fix(stable-abi): one instance layout, header checks in setup_helpers,…
henryiii Oct 29, 2026
b08d061
test: skip tests whose module is not built under the stable ABI or wh…
henryiii Oct 29, 2026
1a7ffa0
fix(stable-abi): initialize Python type caches without GIL inversion
rwgk Oct 30, 2026
1a89de8
fix(stable-abi): bind complex conversion descriptors correctly
rwgk Oct 30, 2026
770d60e
fix(cmake): propagate Python headers to Windows abi3t consumers
rwgk Oct 30, 2026
19726eb
fix(cmake): preserve Python module names without SOABI
rwgk Oct 30, 2026
f408a04
fix: use the legacy type path with PYBIND11_BACKWARD_COMPATIBILITY_TP…
henryiii Oct 30, 2026
ce9bbd9
fix(setuptools): derive the abi3t file name and export symbol from ex…
henryiii Oct 30, 2026
90f46d7
fix(stable-abi): encode the limited API version in the precompiled li…
henryiii Oct 30, 2026
0dab0c3
fix(stable-abi): reject PYBIND11_PLUGIN under abi3t; document downstr…
henryiii Oct 30, 2026
2c8f883
docs(stable-abi): note find_package(Python), NumPy 2.5, and PyModExpo…
henryiii Oct 30, 2026
26cbafb
fix(cmake): treat an empty PYBIND11_STABLE_ABI_VERSION as the default
henryiii Oct 30, 2026
5838965
docs(stable-abi): note old scikit-build-core and Py_GIL_DISABLED unde…
henryiii Oct 30, 2026
091b4ca
docs(stable-abi): note Development.SABIModule for CMake, Python_EXECU…
henryiii Oct 30, 2026
6f3e790
fix(stable-abi): keep the wrapper alive in get_object_handle(); exact…
henryiii Nov 3, 2026
aa32860
refactor(stable-abi): drop duplicate type_from_spec() declaration; fi…
henryiii Nov 3, 2026
bd38b69
refactor(stable-abi): one __dict__ slot lookup for instances and stat…
henryiii Nov 3, 2026
3c6c309
fix(stable-abi): get_object_handle() returns a borrowed handle again
henryiii Nov 3, 2026
9af1762
fix(stable-abi): GIL-safe generator type cache; read numpy void scala…
henryiii Nov 3, 2026
6f94025
test(stable-abi): skip the numpy __buffer__ override test where the o…
henryiii Nov 3, 2026
64485c0
Merge branch 'master' into rwgk/review-pr6198
rwgk Nov 7, 2026
bdcd3c3
fix(numpy): pair base scalar buffer acquisition and release
rwgk Nov 7, 2026
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
242 changes: 240 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ jobs:
python-version: ${{ matrix.python-version }}
cmake-args: -DPYBIND11_TEST_PRECOMPILE=ON

# The legacy PyHeapTypeObject type-creation path on CPython 3.12+
# (PyType_FromMetaclass is the default there).
# PyType_FromMetaclass type creation is the default on CPython 3.12+ (and the only
# path under the stable ABI); this job covers the legacy opt-out.
type-creation-legacy:
if: github.event.pull_request.draft == false
strategy:
Expand All @@ -135,6 +135,244 @@ jobs:
python-version: ${{ matrix.python-version }}
cmake-args: ${{ matrix.cmake-args }}

# Stable ABI (Py_LIMITED_API): every test module is built as *.abi3.
stable-abi:
if: github.event.pull_request.draft == false
strategy:
fail-fast: false
matrix:
include:
- runs-on: ubuntu-latest
python-version: '3.12'
cmake-args: -DPYBIND11_TEST_STABLE_ABI=ON
# precompiled: the -inl.h files must not read any non-limited struct field
- runs-on: ubuntu-latest
python-version: '3.14'
cmake-args: -DPYBIND11_TEST_STABLE_ABI=ON -DPYBIND11_TEST_PRECOMPILE=ON
# A newer limited API target: gates must follow the limited API, not PY_VERSION_HEX
- runs-on: ubuntu-latest
python-version: '3.14'
cmake-args: -DPYBIND11_TEST_STABLE_ABI=ON -DPYBIND11_STABLE_ABI_VERSION=3.14
- runs-on: macos-latest
python-version: '3.13'
cmake-args: -DPYBIND11_TEST_STABLE_ABI=ON -DCMAKE_CXX_STANDARD=17
- runs-on: windows-2022
python-version: '3.12'
cmake-args: -DPYBIND11_TEST_STABLE_ABI=ON
# free-threaded stable ABI (abi3t, PEP 803): PyObject is opaque
- runs-on: ubuntu-latest
python-version: '3.15t'
cmake-args: -DPYBIND11_TEST_STABLE_ABI=ON
- runs-on: macos-latest
python-version: '3.15t'
cmake-args: -DPYBIND11_TEST_STABLE_ABI=ON -DPYBIND11_TEST_PRECOMPILE=ON

name: 🧱
uses: ./.github/workflows/reusable-standard.yml
with:
runs-on: ${{ matrix.runs-on }}
python-version: ${{ matrix.python-version }}
cmake-args: ${{ matrix.cmake-args }}

# The point of the stable ABI: build the suite once against the 3.12 headers
# and run the same .abi3 modules on newer interpreters.
stable-abi-forward:
if: github.event.pull_request.draft == false
name: 🧱 abi3 on newer Pythons
runs-on: ubuntu-latest
timeout-minutes: 60
env:
# Relative to the working directory of the forward steps, build/tests
PYBIND11_STABLE_ABI_SKIPPED_TESTS: >-
--ignore=../../tests/test_custom_type_setup.py
--ignore=../../tests/test_multiple_interpreters.py
--ignore=../../tests/test_class_release_gil_before_calling_cpp_dtor.py

steps:
- uses: actions/checkout@v7

- name: Setup Python 3.12 (build)
id: py312
uses: actions/setup-python@v7
with:
python-version: '3.12'

- name: Setup Python 3.13 and 3.14 (run)
uses: actions/setup-python@v7
with:
python-version: |
3.13
3.14
allow-prereleases: true

- name: Install uv
uses: astral-sh/setup-uv@v10.0.1
with:
enable-cache: true

- name: Prepare env
run: |
for py in "${{ steps.py312.outputs.python-path }}" python3.13 python3.14; do
uv pip install --python="$py" --system -r tests/requirements.txt
done

- name: Configure (Python 3.12, stable ABI)
run: >
cmake -S. -Bbuild -Werror=dev -GNinja
-DPYBIND11_WERROR=ON
-DDOWNLOAD_CATCH=ON
-DDOWNLOAD_EIGEN=ON
-DPYBIND11_TEST_STABLE_ABI=ON
-DPYTHON_EXECUTABLE=${{ steps.py312.outputs.python-path }}

- name: Build
run: cmake --build build

- name: Python tests (3.12)
run: cmake --build build --target pytest

- name: Python tests (3.13, same binaries)
working-directory: build/tests
run: python3.13 -m pytest -v ../../tests ${{ env.PYBIND11_STABLE_ABI_SKIPPED_TESTS }}

- name: Python tests (3.14, same binaries)
working-directory: build/tests
run: python3.14 -m pytest -v ../../tests ${{ env.PYBIND11_STABLE_ABI_SKIPPED_TESTS }}

# abi3t modules also load on GIL-enabled interpreters: build the suite with
# 3.15t and run the same .abi3t modules on 3.15.
stable-abi-forward-ft:
if: github.event.pull_request.draft == false
name: 🧱 abi3t on GIL-enabled Python
runs-on: ubuntu-latest
timeout-minutes: 60
env:
# Relative to the working directory of the forward steps, build/tests
PYBIND11_STABLE_ABI_SKIPPED_TESTS: >-
--ignore=../../tests/test_custom_type_setup.py
--ignore=../../tests/test_multiple_interpreters.py
--ignore=../../tests/test_class_release_gil_before_calling_cpp_dtor.py

steps:
- uses: actions/checkout@v7

- name: Setup Python 3.15t (build)
id: py315t
uses: actions/setup-python@v7
with:
python-version: '3.15t'
allow-prereleases: true

- name: Setup Python 3.15 (run)
uses: actions/setup-python@v7
with:
python-version: '3.15'
allow-prereleases: true

- name: Install uv
uses: astral-sh/setup-uv@v10.0.1
with:
enable-cache: true

- name: Prepare env
run: |
for py in "${{ steps.py315t.outputs.python-path }}" python3.15; do
uv pip install --python="$py" --system -r tests/requirements.txt
done

- name: Configure (Python 3.15t, stable ABI)
run: >
cmake -S. -Bbuild -Werror=dev -GNinja
-DPYBIND11_WERROR=ON
-DDOWNLOAD_CATCH=ON
-DDOWNLOAD_EIGEN=ON
-DPYBIND11_TEST_STABLE_ABI=ON
-DPYTHON_EXECUTABLE=${{ steps.py315t.outputs.python-path }}

- name: Build
run: cmake --build build

- name: Python tests (3.15t)
run: cmake --build build --target pytest

- name: Python tests (3.15, same binaries)
working-directory: build/tests
run: python3.15 -m pytest -v ../../tests ${{ env.PYBIND11_STABLE_ABI_SKIPPED_TESTS }}

# PYBIND11_ABI3T builds abi3t from GIL-enabled Python; run the same modules on 3.15t.
stable-abi-abi3t-from-gil:
if: github.event.pull_request.draft == false
strategy:
fail-fast: false
matrix:
runs-on: [ubuntu-latest, windows-latest]
name: 🧱 abi3t from GIL-enabled Python • ${{ matrix.runs-on }}
runs-on: ${{ matrix.runs-on }}
timeout-minutes: 60
defaults:
run:
shell: bash
env:
# Relative to the working directory of the forward steps, build/tests
PYBIND11_STABLE_ABI_SKIPPED_TESTS: >-
--ignore=../../tests/test_custom_type_setup.py
--ignore=../../tests/test_multiple_interpreters.py
--ignore=../../tests/test_class_release_gil_before_calling_cpp_dtor.py

steps:
- uses: actions/checkout@v7

- name: Setup Python 3.15t (run)
id: py315t
uses: actions/setup-python@v7
with:
python-version: '3.15t'
allow-prereleases: true

- name: Setup Python 3.15 (build)
id: py315
uses: actions/setup-python@v7
with:
python-version: '3.15'
allow-prereleases: true

- name: Install uv
uses: astral-sh/setup-uv@v10.0.1
with:
enable-cache: true

- name: Prepare env
run: |
for py in "${{ steps.py315t.outputs.python-path }}" "${{ steps.py315.outputs.python-path }}"; do
uv pip install --python="$py" --system -r tests/requirements.txt
done

- name: Configure (Python 3.15, abi3t)
run: >
cmake -S. -Bbuild -Werror=dev
-DPYBIND11_WERROR=ON
-DDOWNLOAD_CATCH=ON
-DDOWNLOAD_EIGEN=ON
-DPYBIND11_TEST_STABLE_ABI=ON
-DPYBIND11_ABI3T=ON
-DCMAKE_BUILD_TYPE=Release
-DPYTHON_EXECUTABLE="${{ steps.py315.outputs.python-path }}"

- name: Build
run: cmake --build build --config Release -j 4

- name: CMake stable ABI consumer build
run: cmake --build build --config Release --target test_build_subdirectory_stable_abi

- name: Python tests (3.15)
run: cmake --build build --config Release --target pytest

- name: Python tests (3.15t, same binaries)
working-directory: build/tests
run: >
"${{ steps.py315t.outputs.python-path }}" -m pytest -v ../../tests
${{ env.PYBIND11_STABLE_ABI_SKIPPED_TESTS }}

standard-large:
if: github.event.pull_request.draft == false
strategy:
Expand Down
Loading
Loading