mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-23 13:45:10 +00:00
Merge branch 'pybind:master' into master
This commit is contained in:
commit
1083484cf9
2
.github/CONTRIBUTING.md
vendored
2
.github/CONTRIBUTING.md
vendored
@ -120,7 +120,7 @@ The valid options are:
|
|||||||
* `-DPYBIND11_NOPYTHON=ON`: Disable all Python searching (disables tests)
|
* `-DPYBIND11_NOPYTHON=ON`: Disable all Python searching (disables tests)
|
||||||
* `-DBUILD_TESTING=ON`: Enable the tests
|
* `-DBUILD_TESTING=ON`: Enable the tests
|
||||||
* `-DDOWNLOAD_CATCH=ON`: Download catch to build the C++ tests
|
* `-DDOWNLOAD_CATCH=ON`: Download catch to build the C++ tests
|
||||||
* `-DOWNLOAD_EIGEN=ON`: Download Eigen for the NumPy tests
|
* `-DDOWNLOAD_EIGEN=ON`: Download Eigen for the NumPy tests
|
||||||
* `-DPYBIND11_INSTALL=ON/OFF`: Enable the install target (on by default for the
|
* `-DPYBIND11_INSTALL=ON/OFF`: Enable the install target (on by default for the
|
||||||
master project)
|
master project)
|
||||||
* `-DUSE_PYTHON_INSTALL_DIR=ON`: Try to install into the python dir
|
* `-DUSE_PYTHON_INSTALL_DIR=ON`: Try to install into the python dir
|
||||||
|
@ -765,10 +765,12 @@ template <typename base, typename deleter> struct is_holder_type<base, std::uniq
|
|||||||
std::true_type {};
|
std::true_type {};
|
||||||
|
|
||||||
template <typename T> struct handle_type_name { static constexpr auto name = const_name<T>(); };
|
template <typename T> struct handle_type_name { static constexpr auto name = const_name<T>(); };
|
||||||
|
template <> struct handle_type_name<bool_> { static constexpr auto name = const_name("bool"); };
|
||||||
template <> struct handle_type_name<bytes> { static constexpr auto name = const_name(PYBIND11_BYTES_NAME); };
|
template <> struct handle_type_name<bytes> { static constexpr auto name = const_name(PYBIND11_BYTES_NAME); };
|
||||||
template <> struct handle_type_name<int_> { static constexpr auto name = const_name("int"); };
|
template <> struct handle_type_name<int_> { static constexpr auto name = const_name("int"); };
|
||||||
template <> struct handle_type_name<iterable> { static constexpr auto name = const_name("Iterable"); };
|
template <> struct handle_type_name<iterable> { static constexpr auto name = const_name("Iterable"); };
|
||||||
template <> struct handle_type_name<iterator> { static constexpr auto name = const_name("Iterator"); };
|
template <> struct handle_type_name<iterator> { static constexpr auto name = const_name("Iterator"); };
|
||||||
|
template <> struct handle_type_name<float_> { static constexpr auto name = const_name("float"); };
|
||||||
template <> struct handle_type_name<none> { static constexpr auto name = const_name("None"); };
|
template <> struct handle_type_name<none> { static constexpr auto name = const_name("None"); };
|
||||||
template <> struct handle_type_name<args> { static constexpr auto name = const_name("*args"); };
|
template <> struct handle_type_name<args> { static constexpr auto name = const_name("*args"); };
|
||||||
template <> struct handle_type_name<kwargs> { static constexpr auto name = const_name("**kwargs"); };
|
template <> struct handle_type_name<kwargs> { static constexpr auto name = const_name("**kwargs"); };
|
||||||
|
@ -36,6 +36,9 @@
|
|||||||
# define PYBIND11_CPP14
|
# define PYBIND11_CPP14
|
||||||
# if __cplusplus >= 201703L
|
# if __cplusplus >= 201703L
|
||||||
# define PYBIND11_CPP17
|
# define PYBIND11_CPP17
|
||||||
|
# if __cplusplus >= 202002L
|
||||||
|
# define PYBIND11_CPP20
|
||||||
|
# endif
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
#elif defined(_MSC_VER) && __cplusplus == 199711L
|
#elif defined(_MSC_VER) && __cplusplus == 199711L
|
||||||
@ -45,6 +48,9 @@
|
|||||||
# define PYBIND11_CPP14
|
# define PYBIND11_CPP14
|
||||||
# if _MSVC_LANG > 201402L && _MSC_VER >= 1910
|
# if _MSVC_LANG > 201402L && _MSC_VER >= 1910
|
||||||
# define PYBIND11_CPP17
|
# define PYBIND11_CPP17
|
||||||
|
# if _MSVC_LANG >= 202002L
|
||||||
|
# define PYBIND11_CPP20
|
||||||
|
# endif
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
@ -612,6 +618,18 @@ template <typename T> using remove_cv_t = typename std::remove_cv<T>::type;
|
|||||||
template <typename T> using remove_reference_t = typename std::remove_reference<T>::type;
|
template <typename T> using remove_reference_t = typename std::remove_reference<T>::type;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(PYBIND11_CPP20)
|
||||||
|
using std::remove_cvref;
|
||||||
|
using std::remove_cvref_t;
|
||||||
|
#else
|
||||||
|
template <class T>
|
||||||
|
struct remove_cvref {
|
||||||
|
using type = remove_cv_t<remove_reference_t<T>>;
|
||||||
|
};
|
||||||
|
template <class T>
|
||||||
|
using remove_cvref_t = typename remove_cvref<T>::type;
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Index sequences
|
/// Index sequences
|
||||||
#if defined(PYBIND11_CPP14)
|
#if defined(PYBIND11_CPP14)
|
||||||
using std::index_sequence;
|
using std::index_sequence;
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../pytypes.h"
|
#include "../pytypes.h"
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
/// Tracks the `internals` and `type_info` ABI version independent of the main library version.
|
/// Tracks the `internals` and `type_info` ABI version independent of the main library version.
|
||||||
///
|
///
|
||||||
@ -280,21 +281,104 @@ inline internals **&get_internals_pp() {
|
|||||||
return internals_pp;
|
return internals_pp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PY_VERSION_HEX >= 0x03030000
|
||||||
|
// forward decl
|
||||||
|
inline void translate_exception(std::exception_ptr);
|
||||||
|
|
||||||
|
template <class T,
|
||||||
|
enable_if_t<std::is_same<std::nested_exception, remove_cvref_t<T>>::value, int> = 0>
|
||||||
|
bool handle_nested_exception(const T &exc, const std::exception_ptr &p) {
|
||||||
|
std::exception_ptr nested = exc.nested_ptr();
|
||||||
|
if (nested != nullptr && nested != p) {
|
||||||
|
translate_exception(nested);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T,
|
||||||
|
enable_if_t<!std::is_same<std::nested_exception, remove_cvref_t<T>>::value, int> = 0>
|
||||||
|
bool handle_nested_exception(const T &exc, const std::exception_ptr &p) {
|
||||||
|
if (auto *nep = dynamic_cast<const std::nested_exception *>(std::addressof(exc))) {
|
||||||
|
return handle_nested_exception(*nep, p);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
bool handle_nested_exception(const T &, std::exception_ptr &) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline bool raise_err(PyObject *exc_type, const char *msg) {
|
||||||
|
#if PY_VERSION_HEX >= 0x03030000
|
||||||
|
if (PyErr_Occurred()) {
|
||||||
|
raise_from(exc_type, msg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
PyErr_SetString(exc_type, msg);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
inline void translate_exception(std::exception_ptr p) {
|
inline void translate_exception(std::exception_ptr p) {
|
||||||
|
if (!p) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
if (p) std::rethrow_exception(p);
|
std::rethrow_exception(p);
|
||||||
} catch (error_already_set &e) { e.restore(); return;
|
} catch (error_already_set &e) {
|
||||||
} catch (const builtin_exception &e) { e.set_error(); return;
|
handle_nested_exception(e, p);
|
||||||
} catch (const std::bad_alloc &e) { PyErr_SetString(PyExc_MemoryError, e.what()); return;
|
e.restore();
|
||||||
} catch (const std::domain_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return;
|
return;
|
||||||
} catch (const std::invalid_argument &e) { PyErr_SetString(PyExc_ValueError, e.what()); return;
|
} catch (const builtin_exception &e) {
|
||||||
} catch (const std::length_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return;
|
// Could not use template since it's an abstract class.
|
||||||
} catch (const std::out_of_range &e) { PyErr_SetString(PyExc_IndexError, e.what()); return;
|
if (auto *nep = dynamic_cast<const std::nested_exception *>(std::addressof(e))) {
|
||||||
} catch (const std::range_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return;
|
handle_nested_exception(*nep, p);
|
||||||
} catch (const std::overflow_error &e) { PyErr_SetString(PyExc_OverflowError, e.what()); return;
|
}
|
||||||
} catch (const std::exception &e) { PyErr_SetString(PyExc_RuntimeError, e.what()); return;
|
e.set_error();
|
||||||
|
return;
|
||||||
|
} catch (const std::bad_alloc &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
raise_err(PyExc_MemoryError, e.what());
|
||||||
|
return;
|
||||||
|
} catch (const std::domain_error &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
raise_err(PyExc_ValueError, e.what());
|
||||||
|
return;
|
||||||
|
} catch (const std::invalid_argument &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
raise_err(PyExc_ValueError, e.what());
|
||||||
|
return;
|
||||||
|
} catch (const std::length_error &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
raise_err(PyExc_ValueError, e.what());
|
||||||
|
return;
|
||||||
|
} catch (const std::out_of_range &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
raise_err(PyExc_IndexError, e.what());
|
||||||
|
return;
|
||||||
|
} catch (const std::range_error &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
raise_err(PyExc_ValueError, e.what());
|
||||||
|
return;
|
||||||
|
} catch (const std::overflow_error &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
raise_err(PyExc_OverflowError, e.what());
|
||||||
|
return;
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
raise_err(PyExc_RuntimeError, e.what());
|
||||||
|
return;
|
||||||
|
} catch (const std::nested_exception &e) {
|
||||||
|
handle_nested_exception(e, p);
|
||||||
|
raise_err(PyExc_RuntimeError, "Caught an unknown nested exception!");
|
||||||
|
return;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Caught an unknown exception!");
|
raise_err(PyExc_RuntimeError, "Caught an unknown exception!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
#include "local_bindings.h"
|
#include "local_bindings.h"
|
||||||
|
|
||||||
#include "pybind11_tests.h"
|
#include "pybind11_tests.h"
|
||||||
|
#include <exception>
|
||||||
|
#include <stdexcept>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
// A type that should be raised as an exception in Python
|
// A type that should be raised as an exception in Python
|
||||||
@ -105,7 +107,6 @@ struct PythonAlreadySetInDestructor {
|
|||||||
py::str s;
|
py::str s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
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.");
|
||||||
@ -281,5 +282,12 @@ TEST_SUBMODULE(exceptions, m) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
m.def("throw_nested_exception", []() {
|
||||||
|
try {
|
||||||
|
throw std::runtime_error("Inner Exception");
|
||||||
|
} catch (const std::runtime_error &) {
|
||||||
|
std::throw_with_nested(std::runtime_error("Outer Exception"));
|
||||||
|
}
|
||||||
|
});
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -239,6 +239,14 @@ def test_nested_throws(capture):
|
|||||||
assert str(excinfo.value) == "this is a helper-defined translated exception"
|
assert str(excinfo.value) == "this is a helper-defined translated exception"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif("env.PY2")
|
||||||
|
def test_throw_nested_exception():
|
||||||
|
with pytest.raises(RuntimeError) as excinfo:
|
||||||
|
m.throw_nested_exception()
|
||||||
|
assert str(excinfo.value) == "Outer Exception"
|
||||||
|
assert str(excinfo.value.__cause__) == "Inner Exception"
|
||||||
|
|
||||||
|
|
||||||
# This can often happen if you wrap a pybind11 class in a Python wrapper
|
# This can often happen if you wrap a pybind11 class in a Python wrapper
|
||||||
def test_invalid_repr():
|
def test_invalid_repr():
|
||||||
class MyRepr(object):
|
class MyRepr(object):
|
||||||
|
@ -13,12 +13,16 @@
|
|||||||
|
|
||||||
|
|
||||||
TEST_SUBMODULE(pytypes, m) {
|
TEST_SUBMODULE(pytypes, m) {
|
||||||
|
// test_bool
|
||||||
|
m.def("get_bool", []{return py::bool_(false);});
|
||||||
// test_int
|
// test_int
|
||||||
m.def("get_int", []{return py::int_(0);});
|
m.def("get_int", []{return py::int_(0);});
|
||||||
// test_iterator
|
// test_iterator
|
||||||
m.def("get_iterator", []{return py::iterator();});
|
m.def("get_iterator", []{return py::iterator();});
|
||||||
// test_iterable
|
// test_iterable
|
||||||
m.def("get_iterable", []{return py::iterable();});
|
m.def("get_iterable", []{return py::iterable();});
|
||||||
|
// test_float
|
||||||
|
m.def("get_float", []{return py::float_(0.0f);});
|
||||||
// test_list
|
// test_list
|
||||||
m.def("list_no_args", []() { return py::list{}; });
|
m.def("list_no_args", []() { return py::list{}; });
|
||||||
m.def("list_ssize_t", []() { return py::list{(py::ssize_t) 0}; });
|
m.def("list_ssize_t", []() { return py::list{(py::ssize_t) 0}; });
|
||||||
|
@ -10,6 +10,10 @@ from pybind11_tests import debug_enabled
|
|||||||
from pybind11_tests import pytypes as m
|
from pybind11_tests import pytypes as m
|
||||||
|
|
||||||
|
|
||||||
|
def test_bool(doc):
|
||||||
|
assert doc(m.get_bool) == "get_bool() -> bool"
|
||||||
|
|
||||||
|
|
||||||
def test_int(doc):
|
def test_int(doc):
|
||||||
assert doc(m.get_int) == "get_int() -> int"
|
assert doc(m.get_int) == "get_int() -> int"
|
||||||
|
|
||||||
@ -22,6 +26,10 @@ def test_iterable(doc):
|
|||||||
assert doc(m.get_iterable) == "get_iterable() -> Iterable"
|
assert doc(m.get_iterable) == "get_iterable() -> Iterable"
|
||||||
|
|
||||||
|
|
||||||
|
def test_float(doc):
|
||||||
|
assert doc(m.get_float) == "get_float() -> float"
|
||||||
|
|
||||||
|
|
||||||
def test_list(capture, doc):
|
def test_list(capture, doc):
|
||||||
assert m.list_no_args() == []
|
assert m.list_no_args() == []
|
||||||
assert m.list_ssize_t() == []
|
assert m.list_ssize_t() == []
|
||||||
|
Loading…
Reference in New Issue
Block a user