Skip to content

Commit 43d6bfc

Browse files
committed
Merge branch 'master' into smart_holder
2 parents a3b300e + 7e418f4 commit 43d6bfc

13 files changed

+206
-30
lines changed

.github/workflows/emscripten.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
submodules: true
2424
fetch-depth: 0
2525

26-
- uses: pypa/cibuildwheel@v2.20
26+
- uses: pypa/cibuildwheel@v2.21
2727
env:
2828
PYODIDE_BUILD_EXPORTS: whole_archive
2929
with:

.github/workflows/pip.yml

+5-2
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,12 @@ jobs:
9292
runs-on: ubuntu-latest
9393
if: github.event_name == 'release' && github.event.action == 'published'
9494
needs: [packaging]
95-
environment: pypi
95+
environment:
96+
name: pypi
97+
url: https://pypi.org/p/pybind11
9698
permissions:
9799
id-token: write
98100
attestations: write
99-
contents: read
100101

101102
steps:
102103
# Downloads all to directories matching the artifact names
@@ -111,8 +112,10 @@ jobs:
111112
uses: pypa/gh-action-pypi-publish@release/v1
112113
with:
113114
packages-dir: standard/
115+
attestations: true
114116

115117
- name: Publish global package
116118
uses: pypa/gh-action-pypi-publish@release/v1
117119
with:
118120
packages-dir: global/
121+
attestations: true

docs/changelog.rst

+55
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,37 @@ New Features:
3131
* The ``array_caster`` in pybind11/stl.h was enhanced to support value types that are not default-constructible.
3232
`#5305 <https://github.com/pybind/pybind11/pull/5305>`_
3333

34+
* Added ``py::warnings`` namespace with ``py::warnings::warn`` and ``py::warnings::new_warning_type`` that provides the interface for Python warnings.
35+
`#5291 <https://github.com/pybind/pybind11/pull/5291>`_
36+
37+
Version 2.13.6 (September 13, 2024)
38+
-----------------------------------
39+
40+
New Features:
41+
42+
* A new ``self._pybind11_conduit_v1_()`` method is automatically added to all
43+
``py::class_``-wrapped types, to enable type-safe interoperability between
44+
different independent Python/C++ bindings systems, including pybind11
45+
versions with different ``PYBIND11_INTERNALS_VERSION``'s. Supported on
46+
pybind11 2.11.2, 2.12.1, and 2.13.6+.
47+
`#5296 <https://github.com/pybind/pybind11/pull/5296>`_
48+
49+
50+
Bug fixes:
51+
52+
* Using ``__cpp_nontype_template_args`` instead of ``__cpp_nontype_template_parameter_class``.
53+
`#5330 <https://github.com/pybind/pybind11/pull/5330>`_
54+
55+
* Properly translate C++ exception to Python exception when creating Python buffer from wrapped object.
56+
`#5324 <https://github.com/pybind/pybind11/pull/5324>`_
57+
58+
59+
Documentation:
60+
61+
* Adds an answer (FAQ) for "What is a highly conclusive and simple way to find memory leaks?".
62+
`#5340 <https://github.com/pybind/pybind11/pull/5340>`_
63+
64+
3465
Version 2.13.5 (August 22, 2024)
3566
--------------------------------
3667

@@ -238,6 +269,18 @@ Other:
238269
* Update docs and noxfile.
239270
`#5071 <https://github.com/pybind/pybind11/pull/5071>`_
240271

272+
Version 2.12.1 (September 13, 2024)
273+
-----------------------------------
274+
275+
New Features:
276+
277+
* A new ``self._pybind11_conduit_v1_()`` method is automatically added to all
278+
``py::class_``-wrapped types, to enable type-safe interoperability between
279+
different independent Python/C++ bindings systems, including pybind11
280+
versions with different ``PYBIND11_INTERNALS_VERSION``'s. Supported on
281+
pybind11 2.11.2, 2.12.1, and 2.13.6+.
282+
`#5296 <https://github.com/pybind/pybind11/pull/5296>`_
283+
241284

242285
Version 2.12.0 (March 27, 2024)
243286
-------------------------------
@@ -413,6 +456,18 @@ Other:
413456
* An ``assert()`` was added to help Coverty avoid generating a false positive.
414457
`#4817 <https://github.com/pybind/pybind11/pull/4817>`_
415458

459+
Version 2.11.2 (September 13, 2024)
460+
-----------------------------------
461+
462+
New Features:
463+
464+
* A new ``self._pybind11_conduit_v1_()`` method is automatically added to all
465+
``py::class_``-wrapped types, to enable type-safe interoperability between
466+
different independent Python/C++ bindings systems, including pybind11
467+
versions with different ``PYBIND11_INTERNALS_VERSION``'s. Supported on
468+
pybind11 2.11.2, 2.12.1, and 2.13.6+.
469+
`#5296 <https://github.com/pybind/pybind11/pull/5296>`_
470+
416471

417472
Version 2.11.1 (July 17, 2023)
418473
------------------------------

include/pybind11/cast.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -1853,9 +1853,9 @@ class argument_loader {
18531853
using indices = make_index_sequence<sizeof...(Args)>;
18541854

18551855
template <typename Arg>
1856-
using argument_is_args = std::is_same<intrinsic_t<Arg>, args>;
1856+
using argument_is_args = std::is_base_of<args, intrinsic_t<Arg>>;
18571857
template <typename Arg>
1858-
using argument_is_kwargs = std::is_same<intrinsic_t<Arg>, kwargs>;
1858+
using argument_is_kwargs = std::is_base_of<kwargs, intrinsic_t<Arg>>;
18591859
// Get kwargs argument position, or -1 if not present:
18601860
static constexpr auto kwargs_pos = constexpr_last<argument_is_kwargs, Args...>();
18611861

include/pybind11/detail/exception_translation.h

+11-11
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,17 @@ inline void try_translate_exceptions() {
5050
- delegate translation to the next translator by throwing a new type of exception.
5151
*/
5252

53-
bool handled = with_internals([&](internals &internals) {
54-
auto &local_exception_translators = get_local_internals().registered_exception_translators;
55-
if (detail::apply_exception_translators(local_exception_translators)) {
56-
return true;
57-
}
58-
auto &exception_translators = internals.registered_exception_translators;
59-
if (detail::apply_exception_translators(exception_translators)) {
60-
return true;
61-
}
62-
return false;
63-
});
53+
bool handled = with_exception_translators(
54+
[&](std::forward_list<ExceptionTranslator> &exception_translators,
55+
std::forward_list<ExceptionTranslator> &local_exception_translators) {
56+
if (detail::apply_exception_translators(local_exception_translators)) {
57+
return true;
58+
}
59+
if (detail::apply_exception_translators(exception_translators)) {
60+
return true;
61+
}
62+
return false;
63+
});
6464

6565
if (!handled) {
6666
set_error(PyExc_SystemError, "Exception escaped from default exception translator!");

include/pybind11/detail/internals.h

+19-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@
4141
# elif PY_VERSION_HEX >= 0x030C0000 || defined(_MSC_VER)
4242
// Version bump for Python 3.12+, before first 3.12 beta release.
4343
// Version bump for MSVC piggy-backed on PR #4779. See comments there.
44-
# define PYBIND11_INTERNALS_VERSION 5
44+
# ifdef Py_GIL_DISABLED
45+
# define PYBIND11_INTERNALS_VERSION 6
46+
# else
47+
# define PYBIND11_INTERNALS_VERSION 5
48+
# endif
4549
# else
4650
# define PYBIND11_INTERNALS_VERSION 4
4751
# endif
@@ -179,6 +183,7 @@ static_assert(sizeof(instance_map_shard) % 64 == 0,
179183
struct internals {
180184
#ifdef Py_GIL_DISABLED
181185
pymutex mutex;
186+
pymutex exception_translator_mutex;
182187
#endif
183188
// std::type_index -> pybind11's type information
184189
type_map<type_info *> registered_types_cpp;
@@ -669,6 +674,19 @@ inline auto with_internals(const F &cb) -> decltype(cb(get_internals())) {
669674
return cb(internals);
670675
}
671676

677+
template <typename F>
678+
inline auto with_exception_translators(const F &cb)
679+
-> decltype(cb(get_internals().registered_exception_translators,
680+
get_local_internals().registered_exception_translators)) {
681+
auto &internals = get_internals();
682+
#ifdef Py_GIL_DISABLED
683+
std::unique_lock<pymutex> lock((internals).exception_translator_mutex);
684+
#endif
685+
auto &local_internals = get_local_internals();
686+
return cb(internals.registered_exception_translators,
687+
local_internals.registered_exception_translators);
688+
}
689+
672690
inline std::uint64_t mix64(std::uint64_t z) {
673691
// David Stafford's variant 13 of the MurmurHash3 finalizer popularized
674692
// by the SplitMix PRNG.

include/pybind11/pybind11.h

+22-9
Original file line numberDiff line numberDiff line change
@@ -1387,7 +1387,17 @@ class generic_type : public object {
13871387
} else {
13881388
internals.registered_types_cpp[tindex] = tinfo;
13891389
}
1390+
1391+
PYBIND11_WARNING_PUSH
1392+
#if defined(__GNUC__) && __GNUC__ == 12
1393+
// When using GCC 12 these warnings are disabled as they trigger
1394+
// false positive warnings. Discussed here:
1395+
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115824.
1396+
PYBIND11_WARNING_DISABLE_GCC("-Warray-bounds")
1397+
PYBIND11_WARNING_DISABLE_GCC("-Wstringop-overread")
1398+
#endif
13901399
internals.registered_types_py[(PyTypeObject *) m_ptr] = {tinfo};
1400+
PYBIND11_WARNING_POP
13911401
});
13921402

13931403
if (rec.bases.size() > 1 || rec.multiple_inheritance) {
@@ -2915,10 +2925,12 @@ void implicitly_convertible() {
29152925
}
29162926

29172927
inline void register_exception_translator(ExceptionTranslator &&translator) {
2918-
detail::with_internals([&](detail::internals &internals) {
2919-
internals.registered_exception_translators.push_front(
2920-
std::forward<ExceptionTranslator>(translator));
2921-
});
2928+
detail::with_exception_translators(
2929+
[&](std::forward_list<ExceptionTranslator> &exception_translators,
2930+
std::forward_list<ExceptionTranslator> &local_exception_translators) {
2931+
(void) local_exception_translators;
2932+
exception_translators.push_front(std::forward<ExceptionTranslator>(translator));
2933+
});
29222934
}
29232935

29242936
/**
@@ -2928,11 +2940,12 @@ inline void register_exception_translator(ExceptionTranslator &&translator) {
29282940
* the exception.
29292941
*/
29302942
inline void register_local_exception_translator(ExceptionTranslator &&translator) {
2931-
detail::with_internals([&](detail::internals &internals) {
2932-
(void) internals;
2933-
detail::get_local_internals().registered_exception_translators.push_front(
2934-
std::forward<ExceptionTranslator>(translator));
2935-
});
2943+
detail::with_exception_translators(
2944+
[&](std::forward_list<ExceptionTranslator> &exception_translators,
2945+
std::forward_list<ExceptionTranslator> &local_exception_translators) {
2946+
(void) exception_translators;
2947+
local_exception_translators.push_front(std::forward<ExceptionTranslator>(translator));
2948+
});
29362949
}
29372950

29382951
/**

tests/custom_exceptions.py

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from __future__ import annotations
2+
3+
4+
class PythonMyException7(Exception):
5+
def __init__(self, message):
6+
self.message = message
7+
super().__init__(message)
8+
9+
def __str__(self):
10+
return "[PythonMyException7]: " + self.message.a

tests/test_exceptions.cpp

+39
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,16 @@ struct PythonAlreadySetInDestructor {
111111
py::str s;
112112
};
113113

114+
struct CustomData {
115+
explicit CustomData(const std::string &a) : a(a) {}
116+
std::string a;
117+
};
118+
119+
struct MyException7 {
120+
explicit MyException7(const CustomData &message) : message(message) {}
121+
CustomData message;
122+
};
123+
114124
TEST_SUBMODULE(exceptions, m) {
115125
m.def("throw_std_exception",
116126
[]() { throw std::runtime_error("This exception was intentionally thrown."); });
@@ -385,4 +395,33 @@ TEST_SUBMODULE(exceptions, m) {
385395

386396
// m.def("pass_exception_void", [](const py::exception<void>&) {}); // Does not compile.
387397
m.def("return_exception_void", []() { return py::exception<void>(); });
398+
399+
m.def("throws7", []() {
400+
auto data = CustomData("abc");
401+
throw MyException7(data);
402+
});
403+
404+
py::class_<CustomData>(m, "CustomData", py::module_local())
405+
.def(py::init<const std::string &>())
406+
.def_readwrite("a", &CustomData::a);
407+
408+
PYBIND11_CONSTINIT static py::gil_safe_call_once_and_store<py::object>
409+
PythonMyException7_storage;
410+
PythonMyException7_storage.call_once_and_store_result([&]() {
411+
auto mod = py::module_::import("custom_exceptions");
412+
py::object obj = mod.attr("PythonMyException7");
413+
return obj;
414+
});
415+
416+
py::register_local_exception_translator([](std::exception_ptr p) {
417+
try {
418+
if (p) {
419+
std::rethrow_exception(p);
420+
}
421+
} catch (const MyException7 &e) {
422+
auto exc_type = PythonMyException7_storage.get_stored();
423+
py::object exc_inst = exc_type(e.message);
424+
PyErr_SetObject(PyExc_Exception, exc_inst.ptr());
425+
}
426+
});
388427
}

tests/test_exceptions.py

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import sys
44

55
import pytest
6+
from custom_exceptions import PythonMyException7
67

78
import env
89
import pybind11_cross_module_tests as cm
@@ -195,6 +196,10 @@ def test_custom(msg):
195196
raise RuntimeError("Exception error: caught child from parent") from err
196197
assert msg(excinfo.value) == "this is a helper-defined translated exception"
197198

199+
with pytest.raises(PythonMyException7) as excinfo:
200+
m.throws7()
201+
assert msg(excinfo.value) == "[PythonMyException7]: abc"
202+
198203

199204
def test_nested_throws(capture):
200205
"""Tests nested (e.g. C++ -> Python -> C++) exception handling"""

tests/test_kwargs_and_defaults.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,26 @@
1414

1515
#include <utility>
1616

17+
// Classes needed for subclass test.
18+
class ArgsSubclass : public py::args {
19+
using py::args::args;
20+
};
21+
class KWArgsSubclass : public py::kwargs {
22+
using py::kwargs::kwargs;
23+
};
24+
namespace pybind11 {
25+
namespace detail {
26+
template <>
27+
struct handle_type_name<ArgsSubclass> {
28+
static constexpr auto name = const_name("*Args");
29+
};
30+
template <>
31+
struct handle_type_name<KWArgsSubclass> {
32+
static constexpr auto name = const_name("**KWArgs");
33+
};
34+
} // namespace detail
35+
} // namespace pybind11
36+
1737
TEST_SUBMODULE(kwargs_and_defaults, m) {
1838
auto kw_func
1939
= [](int x, int y) { return "x=" + std::to_string(x) + ", y=" + std::to_string(y); };
@@ -322,4 +342,10 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
322342
py::pos_only{},
323343
py::arg("i"),
324344
py::arg("j"));
345+
346+
// Test support for args and kwargs subclasses
347+
m.def("args_kwargs_subclass_function",
348+
[](const ArgsSubclass &args, const KWArgsSubclass &kwargs) {
349+
return py::make_tuple(args, kwargs);
350+
});
325351
}

tests/test_kwargs_and_defaults.py

+11
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ def test_function_signatures(doc):
1717
assert (
1818
doc(m.args_kwargs_function) == "args_kwargs_function(*args, **kwargs) -> tuple"
1919
)
20+
assert (
21+
doc(m.args_kwargs_subclass_function)
22+
== "args_kwargs_subclass_function(*Args, **KWArgs) -> tuple"
23+
)
2024
assert (
2125
doc(m.KWClass.foo0)
2226
== "foo0(self: m.kwargs_and_defaults.KWClass, arg0: int, arg1: float) -> None"
@@ -98,6 +102,7 @@ def test_arg_and_kwargs():
98102
args = "a1", "a2"
99103
kwargs = {"arg3": "a3", "arg4": 4}
100104
assert m.args_kwargs_function(*args, **kwargs) == (args, kwargs)
105+
assert m.args_kwargs_subclass_function(*args, **kwargs) == (args, kwargs)
101106

102107

103108
def test_mixed_args_and_kwargs(msg):
@@ -413,6 +418,12 @@ def test_args_refcount():
413418
)
414419
assert refcount(myval) == expected
415420

421+
assert m.args_kwargs_subclass_function(7, 8, myval, a=1, b=myval) == (
422+
(7, 8, myval),
423+
{"a": 1, "b": myval},
424+
)
425+
assert refcount(myval) == expected
426+
416427
exp3 = refcount(myval, myval, myval)
417428
assert m.args_refcount(myval, myval, myval) == (exp3, exp3, exp3)
418429
assert refcount(myval) == expected

0 commit comments

Comments
 (0)