mirror of
https://github.com/pybind/pybind11.git
synced 2026-05-26 08:01:48 +00:00
Merge branch 'master' into smart_holder
This commit is contained in:
@@ -35,6 +35,25 @@ using NonLocalVec2 = std::vector<NonLocal2>;
|
||||
using NonLocalMap = std::unordered_map<std::string, NonLocalType>;
|
||||
using NonLocalMap2 = std::unordered_map<std::string, uint8_t>;
|
||||
|
||||
|
||||
// Exception that will be caught via the module local translator.
|
||||
class LocalException : public std::exception {
|
||||
public:
|
||||
explicit LocalException(const char * m) : message{m} {}
|
||||
const char * what() const noexcept override {return message.c_str();}
|
||||
private:
|
||||
std::string message = "";
|
||||
};
|
||||
|
||||
// Exception that will be registered with register_local_exception_translator
|
||||
class LocalSimpleException : public std::exception {
|
||||
public:
|
||||
explicit LocalSimpleException(const char * m) : message{m} {}
|
||||
const char * what() const noexcept override {return message.c_str();}
|
||||
private:
|
||||
std::string message = "";
|
||||
};
|
||||
|
||||
PYBIND11_MAKE_OPAQUE(LocalVec);
|
||||
PYBIND11_MAKE_OPAQUE(LocalVec2);
|
||||
PYBIND11_MAKE_OPAQUE(LocalMap);
|
||||
|
||||
@@ -29,11 +29,14 @@ PYBIND11_MODULE(pybind11_cross_module_tests, m) {
|
||||
bind_local<ExternalType2>(m, "ExternalType2", py::module_local());
|
||||
|
||||
// test_exceptions.py
|
||||
py::register_local_exception<LocalSimpleException>(m, "LocalSimpleException");
|
||||
m.def("raise_runtime_error", []() { PyErr_SetString(PyExc_RuntimeError, "My runtime error"); throw py::error_already_set(); });
|
||||
m.def("raise_value_error", []() { PyErr_SetString(PyExc_ValueError, "My value error"); throw py::error_already_set(); });
|
||||
m.def("throw_pybind_value_error", []() { throw py::value_error("pybind11 value error"); });
|
||||
m.def("throw_pybind_type_error", []() { throw py::type_error("pybind11 type error"); });
|
||||
m.def("throw_stop_iteration", []() { throw py::stop_iteration(); });
|
||||
m.def("throw_local_error", []() { throw LocalException("just local"); });
|
||||
m.def("throw_local_simple_error", []() { throw LocalSimpleException("external mod"); });
|
||||
py::register_exception_translator([](std::exception_ptr p) {
|
||||
try {
|
||||
if (p) std::rethrow_exception(p);
|
||||
@@ -42,6 +45,17 @@ PYBIND11_MODULE(pybind11_cross_module_tests, m) {
|
||||
}
|
||||
});
|
||||
|
||||
// translate the local exception into a key error but only in this module
|
||||
py::register_local_exception_translator([](std::exception_ptr p) {
|
||||
try {
|
||||
if (p) {
|
||||
std::rethrow_exception(p);
|
||||
}
|
||||
} catch (const LocalException &e) {
|
||||
PyErr_SetString(PyExc_KeyError, e.what());
|
||||
}
|
||||
});
|
||||
|
||||
// test_local_bindings.py
|
||||
// Local to both:
|
||||
bind_local<LocalType, 1>(m, "LocalType", py::module_local())
|
||||
@@ -94,7 +108,7 @@ PYBIND11_MODULE(pybind11_cross_module_tests, m) {
|
||||
m.def("get_mixed_lg", [](int i) { return MixedLocalGlobal(i); });
|
||||
|
||||
// test_internal_locals_differ
|
||||
m.def("local_cpp_types_addr", []() { return (uintptr_t) &py::detail::registered_local_types_cpp(); });
|
||||
m.def("local_cpp_types_addr", []() { return (uintptr_t) &py::detail::get_local_internals().registered_types_cpp; });
|
||||
|
||||
// test_stl_caster_vs_stl_bind
|
||||
py::bind_vector<std::vector<int>>(m, "VectorInt");
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
All rights reserved. Use of this source code is governed by a
|
||||
BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "test_exceptions.h"
|
||||
|
||||
#include "local_bindings.h"
|
||||
|
||||
#include "pybind11_tests.h"
|
||||
#include <utility>
|
||||
|
||||
@@ -68,6 +69,17 @@ class MyException5_1 : public MyException5 {
|
||||
using MyException5::MyException5;
|
||||
};
|
||||
|
||||
|
||||
// Exception that will be caught via the module local translator.
|
||||
class MyException6 : public std::exception {
|
||||
public:
|
||||
explicit MyException6(const char * m) : message{m} {}
|
||||
const char * what() const noexcept override {return message.c_str();}
|
||||
private:
|
||||
std::string message = "";
|
||||
};
|
||||
|
||||
|
||||
struct PythonCallInDestructor {
|
||||
PythonCallInDestructor(const py::dict &d) : d(d) {}
|
||||
~PythonCallInDestructor() { d["good"] = true; }
|
||||
@@ -138,14 +150,29 @@ TEST_SUBMODULE(exceptions, m) {
|
||||
// A slightly more complicated one that declares MyException5_1 as a subclass of MyException5
|
||||
py::register_exception<MyException5_1>(m, "MyException5_1", ex5.ptr());
|
||||
|
||||
//py::register_local_exception<LocalSimpleException>(m, "LocalSimpleException")
|
||||
|
||||
py::register_local_exception_translator([](std::exception_ptr p) {
|
||||
try {
|
||||
if (p) {
|
||||
std::rethrow_exception(p);
|
||||
}
|
||||
} catch (const MyException6 &e) {
|
||||
PyErr_SetString(PyExc_RuntimeError, e.what());
|
||||
}
|
||||
});
|
||||
|
||||
m.def("throws1", []() { throw MyException("this error should go to a custom type"); });
|
||||
m.def("throws2", []() { throw MyException2("this error should go to a standard Python exception"); });
|
||||
m.def("throws3", []() { throw MyException3("this error cannot be translated"); });
|
||||
m.def("throws4", []() { throw MyException4("this error is rethrown"); });
|
||||
m.def("throws5", []() { throw MyException5("this is a helper-defined translated exception"); });
|
||||
m.def("throws5_1", []() { throw MyException5_1("MyException5 subclass"); });
|
||||
m.def("throws6", []() { throw MyException6("MyException6 only handled in this module"); });
|
||||
m.def("throws_logic_error", []() { throw std::logic_error("this error should fall through to the standard handler"); });
|
||||
m.def("throws_overflow_error", []() {throw std::overflow_error(""); });
|
||||
m.def("throws_overflow_error", []() { throw std::overflow_error(""); });
|
||||
m.def("throws_local_error", []() { throw LocalException("never caught"); });
|
||||
m.def("throws_local_simple_error", []() { throw LocalSimpleException("this mod"); });
|
||||
m.def("exception_matches", []() {
|
||||
py::dict foo;
|
||||
try {
|
||||
|
||||
@@ -25,7 +25,7 @@ def test_error_already_set(msg):
|
||||
assert msg(excinfo.value) == "foo"
|
||||
|
||||
|
||||
def test_cross_module_exceptions():
|
||||
def test_cross_module_exceptions(msg):
|
||||
with pytest.raises(RuntimeError) as excinfo:
|
||||
cm.raise_runtime_error()
|
||||
assert str(excinfo.value) == "My runtime error"
|
||||
@@ -45,6 +45,15 @@ def test_cross_module_exceptions():
|
||||
with pytest.raises(StopIteration) as excinfo:
|
||||
cm.throw_stop_iteration()
|
||||
|
||||
with pytest.raises(cm.LocalSimpleException) as excinfo:
|
||||
cm.throw_local_simple_error()
|
||||
assert msg(excinfo.value) == "external mod"
|
||||
|
||||
with pytest.raises(KeyError) as excinfo:
|
||||
cm.throw_local_error()
|
||||
# KeyError is a repr of the key, so it has an extra set of quotes
|
||||
assert str(excinfo.value) == "'just local'"
|
||||
|
||||
|
||||
# TODO: FIXME
|
||||
@pytest.mark.xfail(
|
||||
@@ -221,3 +230,21 @@ def test_invalid_repr():
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
m.simple_bool_passthrough(MyRepr())
|
||||
|
||||
|
||||
def test_local_translator(msg):
|
||||
"""Tests that a local translator works and that the local translator from
|
||||
the cross module is not applied"""
|
||||
with pytest.raises(RuntimeError) as excinfo:
|
||||
m.throws6()
|
||||
assert msg(excinfo.value) == "MyException6 only handled in this module"
|
||||
|
||||
with pytest.raises(RuntimeError) as excinfo:
|
||||
m.throws_local_error()
|
||||
assert not isinstance(excinfo.value, KeyError)
|
||||
assert msg(excinfo.value) == "never caught"
|
||||
|
||||
with pytest.raises(Exception) as excinfo:
|
||||
m.throws_local_simple_error()
|
||||
assert not isinstance(excinfo.value, cm.LocalSimpleException)
|
||||
assert msg(excinfo.value) == "this mod"
|
||||
|
||||
@@ -78,7 +78,7 @@ TEST_SUBMODULE(local_bindings, m) {
|
||||
m.def("get_mixed_lg", [](int i) { return MixedLocalGlobal(i); });
|
||||
|
||||
// test_internal_locals_differ
|
||||
m.def("local_cpp_types_addr", []() { return (uintptr_t) &py::detail::registered_local_types_cpp(); });
|
||||
m.def("local_cpp_types_addr", []() { return (uintptr_t) &py::detail::get_local_internals().registered_types_cpp; });
|
||||
|
||||
// test_stl_caster_vs_stl_bind
|
||||
m.def("load_vector_via_caster", [](std::vector<int> v) {
|
||||
|
||||
Reference in New Issue
Block a user