mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 13:15:12 +00:00
Improve make_tuple error message under debugging
When make_tuple fails (for example, when print() is called with a non-convertible argument, as in #778) the error message a less helpful than it could be: make_tuple(): unable to convert arguments of types 'std::tuple<type1, type2>' to Python object There is no actual std::tuple involved (only a parameter pack and a Python tuple), but it also doesn't immediately reveal which type caused the problem. This commit changes the debugging mode output to show just the problematic type: make_tuple(): unable to convert argument of type 'type2' to Python object
This commit is contained in:
parent
8f010cce8e
commit
6906b270d6
@ -1246,18 +1246,19 @@ NAMESPACE_END(detail)
|
|||||||
|
|
||||||
template <return_value_policy policy = return_value_policy::automatic_reference,
|
template <return_value_policy policy = return_value_policy::automatic_reference,
|
||||||
typename... Args> tuple make_tuple(Args&&... args_) {
|
typename... Args> tuple make_tuple(Args&&... args_) {
|
||||||
const size_t size = sizeof...(Args);
|
constexpr size_t size = sizeof...(Args);
|
||||||
std::array<object, size> args {
|
std::array<object, size> args {
|
||||||
{ reinterpret_steal<object>(detail::make_caster<Args>::cast(
|
{ reinterpret_steal<object>(detail::make_caster<Args>::cast(
|
||||||
std::forward<Args>(args_), policy, nullptr))... }
|
std::forward<Args>(args_), policy, nullptr))... }
|
||||||
};
|
};
|
||||||
for (auto &arg_value : args) {
|
for (size_t i = 0; i < args.size(); i++) {
|
||||||
if (!arg_value) {
|
if (!args[i]) {
|
||||||
#if defined(NDEBUG)
|
#if defined(NDEBUG)
|
||||||
throw cast_error("make_tuple(): unable to convert arguments to Python object (compile in debug mode for details)");
|
throw cast_error("make_tuple(): unable to convert arguments to Python object (compile in debug mode for details)");
|
||||||
#else
|
#else
|
||||||
throw cast_error("make_tuple(): unable to convert arguments of types '" +
|
std::array<std::string, size> argtypes { type_id<Args>()... };
|
||||||
(std::string) type_id<std::tuple<Args...>>() + "' to Python object");
|
throw cast_error("make_tuple(): unable to convert argument of type '" +
|
||||||
|
argtypes[i] + "' to Python object");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,6 +186,7 @@ struct MoveOutContainer {
|
|||||||
std::list<Value> move_list() const { return {{0}, {1}, {2}}; }
|
std::list<Value> move_list() const { return {{0}, {1}, {2}}; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UnregisteredType { };
|
||||||
|
|
||||||
test_initializer python_types([](py::module &m) {
|
test_initializer python_types([](py::module &m) {
|
||||||
/* No constructor is explicitly defined below. An exception is raised when
|
/* No constructor is explicitly defined below. An exception is raised when
|
||||||
@ -235,6 +236,13 @@ test_initializer python_types([](py::module &m) {
|
|||||||
py::print("{a} + {b} = {c}"_s.format("a"_a="py::print", "b"_a="str.format", "c"_a="this"));
|
py::print("{a} + {b} = {c}"_s.format("a"_a="py::print", "b"_a="str.format", "c"_a="this"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
m.def("test_print_failure", []() { py::print(42, UnregisteredType()); });
|
||||||
|
#if !defined(NDEBUG)
|
||||||
|
m.attr("debug_enabled") = true;
|
||||||
|
#else
|
||||||
|
m.attr("debug_enabled") = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
m.def("test_str_format", []() {
|
m.def("test_str_format", []() {
|
||||||
auto s1 = "{} + {} = {}"_s.format(1, 2, 3);
|
auto s1 = "{} + {} = {}"_s.format(1, 2, 3);
|
||||||
auto s2 = "{a} + {b} = {c}"_s.format("a"_a=1, "b"_a=2, "c"_a=3);
|
auto s2 = "{a} + {b} = {c}"_s.format("a"_a=1, "b"_a=2, "c"_a=3);
|
||||||
|
@ -258,7 +258,7 @@ def test_module():
|
|||||||
|
|
||||||
|
|
||||||
def test_print(capture):
|
def test_print(capture):
|
||||||
from pybind11_tests import test_print_function
|
from pybind11_tests import test_print_function, test_print_failure, debug_enabled
|
||||||
|
|
||||||
with capture:
|
with capture:
|
||||||
test_print_function()
|
test_print_function()
|
||||||
@ -272,6 +272,14 @@ def test_print(capture):
|
|||||||
"""
|
"""
|
||||||
assert capture.stderr == "this goes to stderr"
|
assert capture.stderr == "this goes to stderr"
|
||||||
|
|
||||||
|
with pytest.raises(RuntimeError) as excinfo:
|
||||||
|
test_print_failure()
|
||||||
|
assert str(excinfo.value) == "make_tuple(): unable to convert " + (
|
||||||
|
"argument of type 'UnregisteredType' to Python object"
|
||||||
|
if debug_enabled else
|
||||||
|
"arguments to Python object (compile in debug mode for details)"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_str_api():
|
def test_str_api():
|
||||||
from pybind11_tests import test_str_format
|
from pybind11_tests import test_str_format
|
||||||
|
Loading…
Reference in New Issue
Block a user