mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 22:52:01 +00:00
Fix debugging output for nameless py::arg_v annotations (#648)
* Fix debugging output for nameless py::arg annotations This fixes a couple bugs with nameless py::arg() (introduced in #634) annotations: - the argument name was being used in debug mode without checking that it exists (which would result in the std::string construction throwing an exception for being invoked with a nullptr) - the error output says "keyword arguments", but py::arg_v() can now also be used for positional argument defaults. - the debugging output "in function named 'blah'" was overly verbose: changed it to just "in function 'blah'". * Fix missing space in debug test string * Moved tests from issues to methods_and_attributes
This commit is contained in:
parent
93cc4bd6d7
commit
1eaacd19f6
@ -303,19 +303,21 @@ template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
|
||||
|
||||
if (!a.value) {
|
||||
#if !defined(NDEBUG)
|
||||
auto descr = "'" + std::string(a.name) + ": " + a.type + "'";
|
||||
std::string descr("'");
|
||||
if (a.name) descr += std::string(a.name) + ": ";
|
||||
descr += a.type + "'";
|
||||
if (r->is_method) {
|
||||
if (r->name)
|
||||
descr += " in method '" + (std::string) str(r->scope) + "." + (std::string) r->name + "'";
|
||||
else
|
||||
descr += " in method of '" + (std::string) str(r->scope) + "'";
|
||||
} else if (r->name) {
|
||||
descr += " in function named '" + (std::string) r->name + "'";
|
||||
descr += " in function '" + (std::string) r->name + "'";
|
||||
}
|
||||
pybind11_fail("arg(): could not convert default keyword argument "
|
||||
pybind11_fail("arg(): could not convert default argument "
|
||||
+ descr + " into a Python object (type not registered yet?)");
|
||||
#else
|
||||
pybind11_fail("arg(): could not convert default keyword argument "
|
||||
pybind11_fail("arg(): could not convert default argument "
|
||||
"into a Python object (type not registered yet?). "
|
||||
"Compile in debug mode for more information.");
|
||||
#endif
|
||||
|
@ -74,7 +74,6 @@ namespace std {
|
||||
template <> struct hash<TplConstrClass> { size_t operator()(const TplConstrClass &t) const { return std::hash<std::string>()(t.str); } };
|
||||
}
|
||||
|
||||
|
||||
void init_issues(py::module &m) {
|
||||
py::module m2 = m.def_submodule("issues");
|
||||
|
||||
@ -397,5 +396,5 @@ void init_issues(py::module &m) {
|
||||
#endif
|
||||
}
|
||||
|
||||
// MSVC workaround: trying to use a lambda here crashes MSCV
|
||||
// MSVC workaround: trying to use a lambda here crashes MSVC
|
||||
test_initializer issues(&init_issues);
|
||||
|
@ -150,6 +150,9 @@ public:
|
||||
};
|
||||
}}
|
||||
|
||||
/// Issue/PR #648: bad arg default debugging output
|
||||
class NotRegistered {};
|
||||
|
||||
test_initializer methods_and_attributes([](py::module &m) {
|
||||
py::class_<ExampleMandA>(m, "ExampleMandA")
|
||||
.def(py::init<>())
|
||||
@ -270,4 +273,18 @@ test_initializer methods_and_attributes([](py::module &m) {
|
||||
m.def("floats_preferred", [](double f) { return 0.5 * f; }, py::arg("f"));
|
||||
m.def("floats_only", [](double f) { return 0.5 * f; }, py::arg("f").noconvert());
|
||||
|
||||
/// Issue/PR #648: bad arg default debugging output
|
||||
#if !defined(NDEBUG)
|
||||
m.attr("debug_enabled") = true;
|
||||
#else
|
||||
m.attr("debug_enabled") = false;
|
||||
#endif
|
||||
m.def("bad_arg_def_named", []{
|
||||
auto m = py::module::import("pybind11_tests.issues");
|
||||
m.def("should_fail", [](int, NotRegistered) {}, py::arg(), py::arg("a") = NotRegistered());
|
||||
});
|
||||
m.def("bad_arg_def_unnamed", []{
|
||||
auto m = py::module::import("pybind11_tests.issues");
|
||||
m.def("should_fail", [](int, NotRegistered) {}, py::arg(), py::arg() = NotRegistered());
|
||||
});
|
||||
});
|
||||
|
@ -255,3 +255,27 @@ def test_noconvert_args(msg):
|
||||
|
||||
Invoked with: 4
|
||||
"""
|
||||
|
||||
|
||||
def test_bad_arg_default(msg):
|
||||
from pybind11_tests import debug_enabled, bad_arg_def_named, bad_arg_def_unnamed
|
||||
|
||||
with pytest.raises(RuntimeError) as excinfo:
|
||||
bad_arg_def_named()
|
||||
assert msg(excinfo.value) == (
|
||||
"arg(): could not convert default argument 'a: NotRegistered' in function 'should_fail' "
|
||||
"into a Python object (type not registered yet?)"
|
||||
if debug_enabled else
|
||||
"arg(): could not convert default argument into a Python object (type not registered "
|
||||
"yet?). Compile in debug mode for more information."
|
||||
)
|
||||
|
||||
with pytest.raises(RuntimeError) as excinfo:
|
||||
bad_arg_def_unnamed()
|
||||
assert msg(excinfo.value) == (
|
||||
"arg(): could not convert default argument 'NotRegistered' in function 'should_fail' "
|
||||
"into a Python object (type not registered yet?)"
|
||||
if debug_enabled else
|
||||
"arg(): could not convert default argument into a Python object (type not registered "
|
||||
"yet?). Compile in debug mode for more information."
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user