Fix #283: don't print first arg of constructor

This changes the exception error message of a bad-arguments error to
suppress the constructor argument when the failure is a constructor.

This changes both the "Invoked with: " output to omit the object
instances, and rewrites the constructor signature to make it look
like a constructor (changing the first argument to the object name, and
removing the ' -> NoneType' return type.
This commit is contained in:
Jason Rhinelander
2016-07-17 17:43:00 -04:00
parent fbdd30e5c5
commit 4e45e1805b
4 changed files with 56 additions and 4 deletions

View File

@@ -445,17 +445,38 @@ protected:
}
if (result.ptr() == PYBIND11_TRY_NEXT_OVERLOAD) {
std::string msg = "Incompatible function arguments. The "
"following argument types are supported:\n";
std::string msg = "Incompatible " + std::string(overloads->is_constructor ? "constructor" : "function") +
" arguments. The following argument types are supported:\n";
int ctr = 0;
for (detail::function_record *it2 = overloads; it2 != nullptr; it2 = it2->next) {
msg += " "+ std::to_string(++ctr) + ". ";
msg += it2->signature;
bool wrote_sig = false;
if (overloads->is_constructor) {
// For a constructor, rewrite `(Object, arg0, ...) -> NoneType` as `Object(arg0, ...)`
std::string sig = it2->signature;
size_t start = sig.find('(') + 1;
if (start < sig.size()) {
// End at the , for the next argument
size_t end = sig.find(", "), next = end + 2;
size_t ret = sig.rfind(" -> ");
// Or the ), if there is no comma:
if (end >= sig.size()) next = end = sig.find(')');
if (start < end && next < sig.size()) {
msg.append(sig, start, end - start);
msg += '(';
msg.append(sig, next, ret - next);
wrote_sig = true;
}
}
}
if (!wrote_sig) msg += it2->signature;
msg += "\n";
}
msg += " Invoked with: ";
tuple args_(args, true);
for( std::size_t ti = 0; ti != args_.size(); ++ti)
for( std::size_t ti = overloads->is_constructor ? 1 : 0; ti < args_.size(); ++ti)
{
msg += static_cast<std::string>(static_cast<object>(args_[ti]).str());
if ((ti + 1) != args_.size() )