mirror of https://github.com/pybind/pybind11.git
Compare commits
7 Commits
1624a0b7fe
...
84d253503c
Author | SHA1 | Date |
---|---|---|
Megh Parikh | 84d253503c | |
Hintay | 1f8b4a7f1a | |
dependabot[bot] | ad9fd39e14 | |
vfdev | 1d9483ff73 | |
pre-commit-ci[bot] | 5f815052b0 | |
Megh Parikh | b8336a8bb7 | |
Megh Parikh | 8869be19d8 |
|
@ -22,7 +22,7 @@ jobs:
|
||||||
submodules: true
|
submodules: true
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- uses: pypa/cibuildwheel@v2.20
|
- uses: pypa/cibuildwheel@v2.21
|
||||||
env:
|
env:
|
||||||
PYODIDE_BUILD_EXPORTS: whole_archive
|
PYODIDE_BUILD_EXPORTS: whole_archive
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -685,23 +685,27 @@ public:
|
||||||
protected:
|
protected:
|
||||||
template <size_t... Is>
|
template <size_t... Is>
|
||||||
type implicit_cast(index_sequence<Is...>) & {
|
type implicit_cast(index_sequence<Is...>) & {
|
||||||
return type(cast_op<Ts>(std::get<Is>(subcasters))...);
|
using std::get;
|
||||||
|
return type(cast_op<Ts>(get<Is>(subcasters))...);
|
||||||
}
|
}
|
||||||
template <size_t... Is>
|
template <size_t... Is>
|
||||||
type implicit_cast(index_sequence<Is...>) && {
|
type implicit_cast(index_sequence<Is...>) && {
|
||||||
return type(cast_op<Ts>(std::move(std::get<Is>(subcasters)))...);
|
using std::get;
|
||||||
|
return type(cast_op<Ts>(std::move(get<Is>(subcasters)))...);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr bool load_impl(const sequence &, bool, index_sequence<>) { return true; }
|
static constexpr bool load_impl(const sequence &, bool, index_sequence<>) { return true; }
|
||||||
|
|
||||||
template <size_t... Is>
|
template <size_t... Is>
|
||||||
bool load_impl(const sequence &seq, bool convert, index_sequence<Is...>) {
|
bool load_impl(const sequence &seq, bool convert, index_sequence<Is...>) {
|
||||||
|
using std::get;
|
||||||
|
|
||||||
#ifdef __cpp_fold_expressions
|
#ifdef __cpp_fold_expressions
|
||||||
if ((... || !std::get<Is>(subcasters).load(seq[Is], convert))) {
|
if ((... || !get<Is>(subcasters).load(seq[Is], convert))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
for (bool r : {std::get<Is>(subcasters).load(seq[Is], convert)...}) {
|
for (bool r : {get<Is>(subcasters).load(seq[Is], convert)...}) {
|
||||||
if (!r) {
|
if (!r) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -714,10 +718,11 @@ protected:
|
||||||
template <typename T, size_t... Is>
|
template <typename T, size_t... Is>
|
||||||
static handle
|
static handle
|
||||||
cast_impl(T &&src, return_value_policy policy, handle parent, index_sequence<Is...>) {
|
cast_impl(T &&src, return_value_policy policy, handle parent, index_sequence<Is...>) {
|
||||||
|
using std::get;
|
||||||
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(src, policy, parent);
|
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(src, policy, parent);
|
||||||
PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(policy, parent);
|
PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(policy, parent);
|
||||||
std::array<object, size> entries{{reinterpret_steal<object>(
|
std::array<object, size> entries{{reinterpret_steal<object>(
|
||||||
make_caster<Ts>::cast(std::get<Is>(std::forward<T>(src)), policy, parent))...}};
|
make_caster<Ts>::cast(get<Is>(std::forward<T>(src)), policy, parent))...}};
|
||||||
for (const auto &entry : entries) {
|
for (const auto &entry : entries) {
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
return handle();
|
return handle();
|
||||||
|
|
|
@ -50,17 +50,17 @@ inline void try_translate_exceptions() {
|
||||||
- delegate translation to the next translator by throwing a new type of exception.
|
- delegate translation to the next translator by throwing a new type of exception.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool handled = with_internals([&](internals &internals) {
|
bool handled = with_exception_translators(
|
||||||
auto &local_exception_translators = get_local_internals().registered_exception_translators;
|
[&](std::forward_list<ExceptionTranslator> &exception_translators,
|
||||||
if (detail::apply_exception_translators(local_exception_translators)) {
|
std::forward_list<ExceptionTranslator> &local_exception_translators) {
|
||||||
return true;
|
if (detail::apply_exception_translators(local_exception_translators)) {
|
||||||
}
|
return true;
|
||||||
auto &exception_translators = internals.registered_exception_translators;
|
}
|
||||||
if (detail::apply_exception_translators(exception_translators)) {
|
if (detail::apply_exception_translators(exception_translators)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!handled) {
|
if (!handled) {
|
||||||
set_error(PyExc_SystemError, "Exception escaped from default exception translator!");
|
set_error(PyExc_SystemError, "Exception escaped from default exception translator!");
|
||||||
|
|
|
@ -39,7 +39,11 @@
|
||||||
# if PY_VERSION_HEX >= 0x030C0000 || defined(_MSC_VER)
|
# if PY_VERSION_HEX >= 0x030C0000 || defined(_MSC_VER)
|
||||||
// Version bump for Python 3.12+, before first 3.12 beta release.
|
// Version bump for Python 3.12+, before first 3.12 beta release.
|
||||||
// Version bump for MSVC piggy-backed on PR #4779. See comments there.
|
// Version bump for MSVC piggy-backed on PR #4779. See comments there.
|
||||||
# define PYBIND11_INTERNALS_VERSION 5
|
# ifdef Py_GIL_DISABLED
|
||||||
|
# define PYBIND11_INTERNALS_VERSION 6
|
||||||
|
# else
|
||||||
|
# define PYBIND11_INTERNALS_VERSION 5
|
||||||
|
# endif
|
||||||
# else
|
# else
|
||||||
# define PYBIND11_INTERNALS_VERSION 4
|
# define PYBIND11_INTERNALS_VERSION 4
|
||||||
# endif
|
# endif
|
||||||
|
@ -177,6 +181,7 @@ static_assert(sizeof(instance_map_shard) % 64 == 0,
|
||||||
struct internals {
|
struct internals {
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
pymutex mutex;
|
pymutex mutex;
|
||||||
|
pymutex exception_translator_mutex;
|
||||||
#endif
|
#endif
|
||||||
// std::type_index -> pybind11's type information
|
// std::type_index -> pybind11's type information
|
||||||
type_map<type_info *> registered_types_cpp;
|
type_map<type_info *> registered_types_cpp;
|
||||||
|
@ -643,6 +648,19 @@ inline auto with_internals(const F &cb) -> decltype(cb(get_internals())) {
|
||||||
return cb(internals);
|
return cb(internals);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
inline auto with_exception_translators(const F &cb)
|
||||||
|
-> decltype(cb(get_internals().registered_exception_translators,
|
||||||
|
get_local_internals().registered_exception_translators)) {
|
||||||
|
auto &internals = get_internals();
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
std::unique_lock<pymutex> lock((internals).exception_translator_mutex);
|
||||||
|
#endif
|
||||||
|
auto &local_internals = get_local_internals();
|
||||||
|
return cb(internals.registered_exception_translators,
|
||||||
|
local_internals.registered_exception_translators);
|
||||||
|
}
|
||||||
|
|
||||||
inline std::uint64_t mix64(std::uint64_t z) {
|
inline std::uint64_t mix64(std::uint64_t z) {
|
||||||
// David Stafford's variant 13 of the MurmurHash3 finalizer popularized
|
// David Stafford's variant 13 of the MurmurHash3 finalizer popularized
|
||||||
// by the SplitMix PRNG.
|
// by the SplitMix PRNG.
|
||||||
|
|
|
@ -2586,10 +2586,12 @@ void implicitly_convertible() {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void register_exception_translator(ExceptionTranslator &&translator) {
|
inline void register_exception_translator(ExceptionTranslator &&translator) {
|
||||||
detail::with_internals([&](detail::internals &internals) {
|
detail::with_exception_translators(
|
||||||
internals.registered_exception_translators.push_front(
|
[&](std::forward_list<ExceptionTranslator> &exception_translators,
|
||||||
std::forward<ExceptionTranslator>(translator));
|
std::forward_list<ExceptionTranslator> &local_exception_translators) {
|
||||||
});
|
(void) local_exception_translators;
|
||||||
|
exception_translators.push_front(std::forward<ExceptionTranslator>(translator));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2599,11 +2601,12 @@ inline void register_exception_translator(ExceptionTranslator &&translator) {
|
||||||
* the exception.
|
* the exception.
|
||||||
*/
|
*/
|
||||||
inline void register_local_exception_translator(ExceptionTranslator &&translator) {
|
inline void register_local_exception_translator(ExceptionTranslator &&translator) {
|
||||||
detail::with_internals([&](detail::internals &internals) {
|
detail::with_exception_translators(
|
||||||
(void) internals;
|
[&](std::forward_list<ExceptionTranslator> &exception_translators,
|
||||||
detail::get_local_internals().registered_exception_translators.push_front(
|
std::forward_list<ExceptionTranslator> &local_exception_translators) {
|
||||||
std::forward<ExceptionTranslator>(translator));
|
(void) exception_translators;
|
||||||
});
|
local_exception_translators.push_front(std::forward<ExceptionTranslator>(translator));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|
||||||
|
class PythonMyException7(Exception):
|
||||||
|
def __init__(self, message):
|
||||||
|
self.message = message
|
||||||
|
super().__init__(message)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "[PythonMyException7]: " + self.message.a
|
|
@ -111,6 +111,16 @@ struct PythonAlreadySetInDestructor {
|
||||||
py::str s;
|
py::str s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CustomData {
|
||||||
|
explicit CustomData(const std::string &a) : a(a) {}
|
||||||
|
std::string a;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MyException7 {
|
||||||
|
explicit MyException7(const CustomData &message) : message(message) {}
|
||||||
|
CustomData message;
|
||||||
|
};
|
||||||
|
|
||||||
TEST_SUBMODULE(exceptions, m) {
|
TEST_SUBMODULE(exceptions, m) {
|
||||||
m.def("throw_std_exception",
|
m.def("throw_std_exception",
|
||||||
[]() { throw std::runtime_error("This exception was intentionally thrown."); });
|
[]() { throw std::runtime_error("This exception was intentionally thrown."); });
|
||||||
|
@ -385,4 +395,33 @@ TEST_SUBMODULE(exceptions, m) {
|
||||||
|
|
||||||
// m.def("pass_exception_void", [](const py::exception<void>&) {}); // Does not compile.
|
// m.def("pass_exception_void", [](const py::exception<void>&) {}); // Does not compile.
|
||||||
m.def("return_exception_void", []() { return py::exception<void>(); });
|
m.def("return_exception_void", []() { return py::exception<void>(); });
|
||||||
|
|
||||||
|
m.def("throws7", []() {
|
||||||
|
auto data = CustomData("abc");
|
||||||
|
throw MyException7(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
py::class_<CustomData>(m, "CustomData", py::module_local())
|
||||||
|
.def(py::init<const std::string &>())
|
||||||
|
.def_readwrite("a", &CustomData::a);
|
||||||
|
|
||||||
|
PYBIND11_CONSTINIT static py::gil_safe_call_once_and_store<py::object>
|
||||||
|
PythonMyException7_storage;
|
||||||
|
PythonMyException7_storage.call_once_and_store_result([&]() {
|
||||||
|
auto mod = py::module_::import("custom_exceptions");
|
||||||
|
py::object obj = mod.attr("PythonMyException7");
|
||||||
|
return obj;
|
||||||
|
});
|
||||||
|
|
||||||
|
py::register_local_exception_translator([](std::exception_ptr p) {
|
||||||
|
try {
|
||||||
|
if (p) {
|
||||||
|
std::rethrow_exception(p);
|
||||||
|
}
|
||||||
|
} catch (const MyException7 &e) {
|
||||||
|
auto exc_type = PythonMyException7_storage.get_stored();
|
||||||
|
py::object exc_inst = exc_type(e.message);
|
||||||
|
PyErr_SetObject(PyExc_Exception, exc_inst.ptr());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ from __future__ import annotations
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from custom_exceptions import PythonMyException7
|
||||||
|
|
||||||
import env
|
import env
|
||||||
import pybind11_cross_module_tests as cm
|
import pybind11_cross_module_tests as cm
|
||||||
|
@ -195,6 +196,10 @@ def test_custom(msg):
|
||||||
raise RuntimeError("Exception error: caught child from parent") from err
|
raise RuntimeError("Exception error: caught child from parent") from err
|
||||||
assert msg(excinfo.value) == "this is a helper-defined translated exception"
|
assert msg(excinfo.value) == "this is a helper-defined translated exception"
|
||||||
|
|
||||||
|
with pytest.raises(PythonMyException7) as excinfo:
|
||||||
|
m.throws7()
|
||||||
|
assert msg(excinfo.value) == "[PythonMyException7]: abc"
|
||||||
|
|
||||||
|
|
||||||
def test_nested_throws(capture):
|
def test_nested_throws(capture):
|
||||||
"""Tests nested (e.g. C++ -> Python -> C++) exception handling"""
|
"""Tests nested (e.g. C++ -> Python -> C++) exception handling"""
|
||||||
|
|
|
@ -274,10 +274,6 @@ function(pybind11_add_module target_name)
|
||||||
target_link_libraries(${target_name} PRIVATE pybind11::embed)
|
target_link_libraries(${target_name} PRIVATE pybind11::embed)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(MSVC)
|
|
||||||
target_link_libraries(${target_name} PRIVATE pybind11::windows_extras)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# -fvisibility=hidden is required to allow multiple modules compiled against
|
# -fvisibility=hidden is required to allow multiple modules compiled against
|
||||||
# different pybind versions to work properly, and for some features (e.g.
|
# different pybind versions to work properly, and for some features (e.g.
|
||||||
# py::module_local). We force it on everything inside the `pybind11`
|
# py::module_local). We force it on everything inside the `pybind11`
|
||||||
|
|
Loading…
Reference in New Issue