Unify cast_error message thrown by [simple|unpacking]_collector (#3013)

* Unify cast_error message thrown by [simple|unpacking]_collector

simple_collector and unpacking_collector throw different error messages
when the casting of an argument failed: While the former mentions make_tuple(),
the latter emphasises the call argument (and its name/position).

* Consolidating "Unable to convert call argument" error reporting code to guarantee uniformity.

Co-authored-by: Ralf W. Grosse-Kunstleve <rwgk@google.com>
This commit is contained in:
Robert Haschke 2021-07-07 00:13:13 +02:00 committed by GitHub
parent 0ad116d371
commit c090c8c409
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 21 deletions

View File

@ -958,6 +958,21 @@ template <> inline void cast_safe<void>(object &&) {}
PYBIND11_NAMESPACE_END(detail) PYBIND11_NAMESPACE_END(detail)
// The overloads could coexist, i.e. the #if is not strictly speaking needed,
// but it is an easy minor optimization.
#if defined(NDEBUG)
inline cast_error cast_error_unable_to_convert_call_arg() {
return cast_error(
"Unable to convert call argument to Python object (compile in debug mode for details)");
}
#else
inline cast_error cast_error_unable_to_convert_call_arg(const std::string &name,
const std::string &type) {
return cast_error("Unable to convert call argument '" + name + "' of type '" + type
+ "' to Python object");
}
#endif
template <return_value_policy policy = return_value_policy::automatic_reference> template <return_value_policy policy = return_value_policy::automatic_reference>
tuple make_tuple() { return tuple(0); } tuple make_tuple() { return tuple(0); }
@ -971,11 +986,10 @@ template <return_value_policy policy = return_value_policy::automatic_reference,
for (size_t i = 0; i < args.size(); i++) { for (size_t i = 0; i < args.size(); i++) {
if (!args[i]) { 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_unable_to_convert_call_arg();
#else #else
std::array<std::string, size> argtypes { {type_id<Args>()...} }; std::array<std::string, size> argtypes { {type_id<Args>()...} };
throw cast_error("make_tuple(): unable to convert argument of type '" + throw cast_error_unable_to_convert_call_arg(std::to_string(i), argtypes[i]);
argtypes[i] + "' to Python object");
#endif #endif
} }
} }
@ -1230,9 +1244,10 @@ private:
auto o = reinterpret_steal<object>(detail::make_caster<T>::cast(std::forward<T>(x), policy, {})); auto o = reinterpret_steal<object>(detail::make_caster<T>::cast(std::forward<T>(x), policy, {}));
if (!o) { if (!o) {
#if defined(NDEBUG) #if defined(NDEBUG)
argument_cast_error(); throw cast_error_unable_to_convert_call_arg();
#else #else
argument_cast_error(std::to_string(args_list.size()), type_id<T>()); throw cast_error_unable_to_convert_call_arg(
std::to_string(args_list.size()), type_id<T>());
#endif #endif
} }
args_list.append(o); args_list.append(o);
@ -1260,9 +1275,9 @@ private:
} }
if (!a.value) { if (!a.value) {
#if defined(NDEBUG) #if defined(NDEBUG)
argument_cast_error(); throw cast_error_unable_to_convert_call_arg();
#else #else
argument_cast_error(a.name, a.type); throw cast_error_unable_to_convert_call_arg(a.name, a.type);
#endif #endif
} }
m_kwargs[a.name] = a.value; m_kwargs[a.name] = a.value;
@ -1301,17 +1316,6 @@ private:
throw type_error("Got multiple values for keyword argument '" + name + "'"); throw type_error("Got multiple values for keyword argument '" + name + "'");
} }
[[noreturn]] static void argument_cast_error() {
throw cast_error("Unable to convert call argument to Python object "
"(compile in debug mode for details)");
}
[[noreturn]] static void argument_cast_error(const std::string &name,
const std::string &type) {
throw cast_error("Unable to convert call argument '" + name
+ "' of type '" + type + "' to Python object");
}
private: private:
tuple m_args; tuple m_args;
dict m_kwargs; dict m_kwargs;

View File

@ -372,10 +372,10 @@ def test_print(capture):
with pytest.raises(RuntimeError) as excinfo: with pytest.raises(RuntimeError) as excinfo:
m.print_failure() m.print_failure()
assert str(excinfo.value) == "make_tuple(): unable to convert " + ( assert str(excinfo.value) == "Unable to convert call argument " + (
"argument of type 'UnregisteredType' to Python object" "'1' of type 'UnregisteredType' to Python object"
if debug_enabled if debug_enabled
else "arguments to Python object (compile in debug mode for details)" else "to Python object (compile in debug mode for details)"
) )