Skip to content

Commit 2c6b1ff

Browse files
committed
Merge tag 'v3.0.3' into stable
v3.0.3 release
2 parents 04cfb45 + 1b49908 commit 2c6b1ff

41 files changed

Lines changed: 1511 additions & 129 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/nightlies.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
nox -s build
3434
nox -s build_global
3535
36-
- uses: actions/upload-artifact@v6
36+
- uses: actions/upload-artifact@v7
3737
with:
3838
name: Packages
3939
path: dist/*
@@ -44,7 +44,7 @@ jobs:
4444
needs: [build_wheel]
4545
runs-on: ubuntu-latest
4646
steps:
47-
- uses: actions/download-artifact@v7
47+
- uses: actions/download-artifact@v8
4848
with:
4949
name: Packages
5050
path: dist

.github/workflows/pip.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,13 @@ jobs:
7272
run: twine check dist/*
7373

7474
- name: Save standard package
75-
uses: actions/upload-artifact@v6
75+
uses: actions/upload-artifact@v7
7676
with:
7777
name: standard
7878
path: dist/pybind11-*
7979

8080
- name: Save global package
81-
uses: actions/upload-artifact@v6
81+
uses: actions/upload-artifact@v7
8282
with:
8383
name: global
8484
path: dist/*global-*
@@ -100,10 +100,10 @@ jobs:
100100

101101
steps:
102102
# Downloads all to directories matching the artifact names
103-
- uses: actions/download-artifact@v7
103+
- uses: actions/download-artifact@v8
104104

105105
- name: Generate artifact attestation for sdist and wheel
106-
uses: actions/attest-build-provenance@v3
106+
uses: actions/attest-build-provenance@v4
107107
with:
108108
subject-path: "*/pybind11*"
109109

.github/workflows/tests-cibw.yml

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -70,24 +70,6 @@ jobs:
7070
if: contains(matrix.runs-on, 'macos')
7171
run: echo "CIBW_TEST_COMMAND=" >> "$GITHUB_ENV"
7272

73-
# Temporarily disable Android tests on ubuntu-latest due to emulator issues.
74-
# See https://github.com/pybind/pybind11/pull/5914.
75-
- name: "NOTE: Android tests are disabled on ubuntu-latest"
76-
if: contains(matrix.runs-on, 'ubuntu')
77-
run: |
78-
echo "CIBW_TEST_COMMAND=" >> "$GITHUB_ENV"
79-
echo '::warning::Android cibuildwheel tests are disabled on ubuntu-latest (CIBW_TEST_COMMAND is empty). See PR 5914.'
80-
81-
# https://github.blog/changelog/2024-04-02-github-actions-hardware-accelerated-android-virtualization-now-available/
82-
- name: Enable KVM for Android emulator
83-
if: contains(matrix.runs-on, 'ubuntu')
84-
run: |
85-
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
86-
sudo udevadm control --reload-rules
87-
sudo udevadm trigger --name-match=kvm
88-
89-
- run: pipx install patchelf
90-
9173
- uses: pypa/cibuildwheel@v3.3
9274
env:
9375
CIBW_PLATFORM: android

.pre-commit-config.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ repos:
2525

2626
# Clang format the codebase automatically
2727
- repo: https://github.com/pre-commit/mirrors-clang-format
28-
rev: "v21.1.8"
28+
rev: "v22.1.0"
2929
hooks:
3030
- id: clang-format
3131
types_or: [c++, c, cuda]
3232

3333
# Ruff, the Python auto-correcting linter/formatter written in Rust
3434
- repo: https://github.com/astral-sh/ruff-pre-commit
35-
rev: v0.14.14
35+
rev: v0.15.4
3636
hooks:
3737
- id: ruff-check
3838
args: ["--fix", "--show-fixes"]
@@ -122,7 +122,7 @@ repos:
122122
# Use mirror because pre-commit autoupdate confuses tags in the upstream repo.
123123
# See https://github.com/crate-ci/typos/issues/390
124124
- repo: https://github.com/adhtruong/mirrors-typos
125-
rev: "v1.42.3"
125+
rev: "v1.44.0"
126126
hooks:
127127
- id: typos
128128
args: []
@@ -144,14 +144,14 @@ repos:
144144

145145
# PyLint has native support - not always usable, but works for us
146146
- repo: https://github.com/PyCQA/pylint
147-
rev: "v4.0.4"
147+
rev: "v4.0.5"
148148
hooks:
149149
- id: pylint
150150
files: ^pybind11
151151

152152
# Check schemas on some of our YAML files
153153
- repo: https://github.com/python-jsonschema/check-jsonschema
154-
rev: 0.36.1
154+
rev: 0.37.0
155155
hooks:
156156
- id: check-readthedocs
157157
- id: check-github-workflows

docs/changelog.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,62 @@ Changes will be added here periodically from the "Suggested changelog
1313
entry" block in pull request descriptions.
1414

1515

16+
## Version 3.0.3 (March 31, 2026)
17+
18+
Bug fixes:
19+
20+
- Fixed TSS key exhaustion in `implicitly_convertible()` when many implicit conversions are registered across large module sets.
21+
[#6020](https://github.com/pybind/pybind11/pull/6020)
22+
23+
- Fixed heap-buffer-overflow in `pythonbuf` with undersized buffers by enforcing a minimum buffer size.
24+
[#6019](https://github.com/pybind/pybind11/pull/6019)
25+
26+
- Fixed virtual-inheritance pointer offset crashes when dispatching inherited methods through virtual bases.
27+
[#6017](https://github.com/pybind/pybind11/pull/6017)
28+
29+
- Fixed `free(): invalid pointer` crashes during interpreter shutdown with `py::enum_<>` by duplicating late-added `def_property_static` argument strings.
30+
[#6015](https://github.com/pybind/pybind11/pull/6015)
31+
32+
- Fixed `function_record` heap-type deallocation to call `PyObject_Free()` and decref the type.
33+
[#6010](https://github.com/pybind/pybind11/pull/6010)
34+
35+
- Hardened `PYBIND11_MODULE_PYINIT` and `get_internals()` against module-initialization crashes.
36+
[#6018](https://github.com/pybind/pybind11/pull/6018)
37+
38+
- Fixed `static_pointer_cast` build failure with virtual inheritance in `holder_caster_foreign_helpers.h`.
39+
[#6014](https://github.com/pybind/pybind11/pull/6014)
40+
41+
- Fixed ambiguous `factory` template specialization that caused compilation failures with nvcc + GCC 14.
42+
[#6011](https://github.com/pybind/pybind11/pull/6011)
43+
44+
- Fixed crash in `def_readwrite` for non-smart-holder properties of smart-holder classes.
45+
[#6008](https://github.com/pybind/pybind11/pull/6008)
46+
47+
- Fixed memory leak for `py::dynamic_attr()` objects on Python 3.13+ by clearing managed `__dict__` contents during deallocation.
48+
[#5999](https://github.com/pybind/pybind11/pull/5999)
49+
50+
- Fixed binding of `noexcept` and ref-qualified (`&`, `&&`) methods inherited from unregistered base classes.
51+
[#5992](https://github.com/pybind/pybind11/pull/5992)
52+
53+
Internal:
54+
55+
- Moved `tomlkit` dependency to the dev dependency group.
56+
[#5990](https://github.com/pybind/pybind11/pull/5990)
57+
58+
- Switched to newer public CPython APIs (`PyType_GetFlags` and public vectorcall APIs where available).
59+
[#6005](https://github.com/pybind/pybind11/pull/6005)
60+
61+
Tests:
62+
63+
- Made an async callback test deterministic by replacing fixed sleep with bounded waiting.
64+
[#5986](https://github.com/pybind/pybind11/pull/5986)
65+
66+
CI:
67+
68+
- Re-enabled Android tests in the cibuildwheel workflow.
69+
[#6001](https://github.com/pybind/pybind11/pull/6001)
70+
71+
1672
## Version 3.0.2 (February 16, 2026)
1773

1874
New Features:

docs/requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ myst-parser==3.0.1
4141
# via -r requirements.in
4242
packaging==24.0
4343
# via sphinx
44-
pygments==2.17.2
44+
pygments==2.20.0
4545
# via
4646
# furo
4747
# sphinx
4848
pyyaml==6.0.2
4949
# via myst-parser
50-
requests==2.32.4
50+
requests==2.33.0
5151
# via sphinx
5252
snowballstemmer==2.2.0
5353
# via sphinx

include/pybind11/attr.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ struct type_record {
378378
#ifdef PYBIND11_BACKWARD_COMPATIBILITY_TP_DICTOFFSET
379379
dynamic_attr |= base_info->type->tp_dictoffset != 0;
380380
#else
381-
dynamic_attr |= (base_info->type->tp_flags & Py_TPFLAGS_MANAGED_DICT) != 0;
381+
dynamic_attr |= (PyType_GetFlags(base_info->type) & Py_TPFLAGS_MANAGED_DICT) != 0;
382382
#endif
383383

384384
if (caster) {

include/pybind11/cast.h

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,7 @@ public:
199199
template <typename T_, \
200200
::pybind11::detail::enable_if_t< \
201201
std::is_same<type, ::pybind11::detail::remove_cv_t<T_>>::value, \
202-
int> \
203-
= 0> \
202+
int> = 0> \
204203
static ::pybind11::handle cast( \
205204
T_ *src, ::pybind11::return_value_policy policy, ::pybind11::handle parent) { \
206205
if (!src) \
@@ -1020,7 +1019,19 @@ struct copyable_holder_caster<
10201019
return smart_holder_type_caster_support::smart_holder_from_shared_ptr(
10211020
src, policy, parent, srcs.result);
10221021
}
1023-
return type_caster_base<type>::cast_holder(srcs, &src);
1022+
1023+
auto *tinfo = srcs.result.tinfo;
1024+
if (tinfo != nullptr && tinfo->holder_enum_v == holder_enum_t::std_shared_ptr) {
1025+
return type_caster_base<type>::cast_holder(srcs, &src);
1026+
}
1027+
1028+
if (parent) {
1029+
return type_caster_base<type>::cast(
1030+
srcs, return_value_policy::reference_internal, parent);
1031+
}
1032+
1033+
throw cast_error("Unable to convert std::shared_ptr<T> to Python when the bound type "
1034+
"does not use std::shared_ptr or py::smart_holder as its holder type");
10241035
}
10251036

10261037
// This function will succeed even if the `responsible_parent` does not own the
@@ -1662,8 +1673,7 @@ PYBIND11_NAMESPACE_END(detail)
16621673
template <typename T,
16631674
detail::enable_if_t<!detail::is_pyobject<T>::value
16641675
&& !detail::is_same_ignoring_cvref<T, PyObject *>::value,
1665-
int>
1666-
= 0>
1676+
int> = 0>
16671677
T cast(const handle &handle) {
16681678
using namespace detail;
16691679
constexpr bool is_enum_cast = type_uses_type_caster_enum_type<intrinsic_t<T>>::value;
@@ -1698,8 +1708,7 @@ template <typename T,
16981708
typename Handle,
16991709
detail::enable_if_t<detail::is_same_ignoring_cvref<T, PyObject *>::value
17001710
&& detail::is_same_ignoring_cvref<Handle, handle>::value,
1701-
int>
1702-
= 0>
1711+
int> = 0>
17031712
T cast(Handle &&handle) {
17041713
return handle.inc_ref().ptr();
17051714
}
@@ -1708,8 +1717,7 @@ template <typename T,
17081717
typename Object,
17091718
detail::enable_if_t<detail::is_same_ignoring_cvref<T, PyObject *>::value
17101719
&& detail::is_same_ignoring_cvref<Object, object>::value,
1711-
int>
1712-
= 0>
1720+
int> = 0>
17131721
T cast(Object &&obj) {
17141722
return obj.release().ptr();
17151723
}
@@ -2243,8 +2251,13 @@ class unpacking_collector {
22432251
if (m_names) {
22442252
nargs -= m_names.size();
22452253
}
2246-
PyObject *result = _PyObject_Vectorcall(
2247-
ptr, m_args.data() + 1, nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, m_names.ptr());
2254+
PyObject *result =
2255+
#if PY_VERSION_HEX >= 0x03090000
2256+
PyObject_Vectorcall(
2257+
#else
2258+
_PyObject_Vectorcall(
2259+
#endif
2260+
ptr, m_args.data() + 1, nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, m_names.ptr());
22482261
if (!result) {
22492262
throw error_already_set();
22502263
}

include/pybind11/chrono.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,7 @@ class duration_caster {
6464
return src;
6565
}
6666
static const std::chrono::duration<rep, period> &
67-
get_duration(const std::chrono::duration<rep, period> &&)
68-
= delete;
67+
get_duration(const std::chrono::duration<rep, period> &&) = delete;
6968

7069
// If this is a time_point get the time_since_epoch
7170
template <typename Clock>

include/pybind11/detail/class.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,17 @@ extern "C" inline void pybind11_object_dealloc(PyObject *self) {
503503
PyObject_GC_UnTrack(self);
504504
}
505505

506+
#if PY_VERSION_HEX >= 0x030D0000
507+
// PyObject_ClearManagedDict() is available from Python 3.13+. It must be
508+
// called before tp_free() because on Python 3.14+ tp_free no longer
509+
// implicitly clears the managed dict, which would abandon the refcounts of
510+
// objects stored in __dict__ of py::dynamic_attr() types, causing permanent
511+
// memory leaks.
512+
if (PyType_HasFeature(type, Py_TPFLAGS_MANAGED_DICT)) {
513+
PyObject_ClearManagedDict(self);
514+
}
515+
#endif
516+
506517
clear_instance(self);
507518

508519
type->tp_free(self);

0 commit comments

Comments
 (0)