RAII wrapper for error state

This commit is contained in:
Wenzel Jakob 2016-09-10 16:32:17 +09:00
parent 1f2e417d8c
commit 720136bfa7
3 changed files with 13 additions and 7 deletions

View File

@ -111,18 +111,16 @@ PYBIND11_NOINLINE inline std::string error_string() {
return "Unknown internal error occurred";
}
PyObject *type, *value, *traceback;
PyErr_Fetch(&type, &value, &traceback);
error_scope scope; // Preserve error state
std::string errorString;
if (type) {
errorString += handle(type).attr("__name__").cast<std::string>();
if (scope.type) {
errorString += handle(scope.type).attr("__name__").cast<std::string>();
errorString += ": ";
}
if (value)
errorString += (std::string) handle(value).str();
if (scope.value)
errorString += (std::string) handle(scope.value).str();
PyErr_Restore(type, value, traceback);
return errorString;
}

View File

@ -420,6 +420,13 @@ template <typename T> struct format_descriptor<T, typename std::enable_if<std::i
template <typename T> constexpr const char format_descriptor<
T, typename std::enable_if<std::is_integral<T>::value>::type>::value[2];
/// RAII wrapper that temporarily clears any Python error state
struct error_scope {
PyObject *type, *value, *trace;
error_scope() { PyErr_Fetch(&type, &value, &trace); }
~error_scope() { PyErr_Restore(type, value, trace); }
};
PYBIND11_DECL_FMT(float, "f");
PYBIND11_DECL_FMT(double, "d");
PYBIND11_DECL_FMT(bool, "?");

View File

@ -1309,6 +1309,7 @@ NAMESPACE_END(detail)
template <return_value_policy policy = return_value_policy::automatic_reference, typename... Args>
void print(Args &&...args) {
error_scope scope; // Preserve error state
auto c = detail::collect_arguments<policy>(std::forward<Args>(args)...);
detail::print(c.args(), c.kwargs());
}