emit a more useful error message when a return value can't be converted to a Python type

This commit is contained in:
Wenzel Jakob 2015-10-04 15:17:34 +02:00
parent 2cf192f578
commit b3ee3eaf81

View File

@ -190,7 +190,7 @@ public:
process_extras(data->extras, pyArgs, kwargs, entry->is_method); process_extras(data->extras, pyArgs, kwargs, entry->is_method);
cast_in args; cast_in args;
if (!args.load(pyArgs, true)) if (!args.load(pyArgs, true))
return nullptr; return (PyObject *) 1; /* Special return code: try next overload */
return cast_out::cast(args.template call<Return>(data->f), entry->policy, parent); return cast_out::cast(args.template call<Return>(data->f), entry->policy, parent);
}; };
@ -250,7 +250,7 @@ private:
process_extras(data->extras, pyArgs, kwargs, entry->is_method); process_extras(data->extras, pyArgs, kwargs, entry->is_method);
cast_in args; cast_in args;
if (!args.load(pyArgs, true)) if (!args.load(pyArgs, true))
return nullptr; return (PyObject *) 1; /* Special return code: try next overload */
return cast_out::cast(args.template call<Return>(data->f), entry->policy, parent); return cast_out::cast(args.template call<Return>(data->f), entry->policy, parent);
}; };
@ -270,8 +270,9 @@ private:
int nargs = (int) PyTuple_Size(args); int nargs = (int) PyTuple_Size(args);
PyObject *result = nullptr; PyObject *result = nullptr;
PyObject *parent = nargs > 0 ? PyTuple_GetItem(args, 0) : nullptr; PyObject *parent = nargs > 0 ? PyTuple_GetItem(args, 0) : nullptr;
function_entry *it = overloads;
try { try {
for (function_entry *it = overloads; it != nullptr; it = it->next) { for (; it != nullptr; it = it->next) {
PyObject *args_ = args; PyObject *args_ = args;
if (it->keywords != 0 && nargs < it->keywords) { if (it->keywords != 0 && nargs < it->keywords) {
@ -289,7 +290,7 @@ private:
Py_DECREF(args_); Py_DECREF(args_);
} }
if (result != nullptr) if (result != (PyObject *) 1)
break; break;
} }
} catch (const error_already_set &) { return nullptr; } catch (const error_already_set &) { return nullptr;
@ -300,7 +301,24 @@ private:
PyErr_SetString(PyExc_RuntimeError, "Caught an unknown exception!"); PyErr_SetString(PyExc_RuntimeError, "Caught an unknown exception!");
return nullptr; return nullptr;
} }
if (result) { if (result == (PyObject *) 1) {
std::string msg = "Incompatible function arguments. The "
"following argument types are supported:\n";
int ctr = 0;
for (function_entry *it = overloads; it != nullptr; it = it->next) {
msg += " "+ std::to_string(++ctr) + ". ";
msg += it->signature;
msg += "\n";
}
PyErr_SetString(PyExc_TypeError, msg.c_str());
return nullptr;
} else if (result == nullptr) {
std::string msg = "Unable to convert function return value to a "
"Python type! The signature was\n\t";
msg += it->signature;
PyErr_SetString(PyExc_TypeError, msg.c_str());
return nullptr;
} else {
if (overloads->is_constructor) { if (overloads->is_constructor) {
PyObject *inst = PyTuple_GetItem(args, 0); PyObject *inst = PyTuple_GetItem(args, 0);
const detail::type_info *type_info = const detail::type_info *type_info =
@ -309,17 +327,6 @@ private:
type_info->init_holder(inst); type_info->init_holder(inst);
} }
return result; return result;
} else {
std::string signatures = "Incompatible function arguments. The "
"following argument types are supported:\n";
int ctr = 0;
for (function_entry *it = overloads; it != nullptr; it = it->next) {
signatures += " "+ std::to_string(++ctr) + ". ";
signatures += it->signature;
signatures += "\n";
}
PyErr_SetString(PyExc_TypeError, signatures.c_str());
return nullptr;
} }
} }