Skip to content

Fix debugging output for nameless py::arg_v annotations #648

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 8, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions include/pybind11/attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions tests/test_issues.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down Expand Up @@ -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);
17 changes: 17 additions & 0 deletions tests/test_methods_and_attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ template <> struct type_caster<ArgAlwaysConverts> {
};
}}

/// 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<>())
Expand Down Expand Up @@ -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());
});
});
24 changes: 24 additions & 0 deletions tests/test_methods_and_attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."
)