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"; return "Unknown internal error occurred";
} }
PyObject *type, *value, *traceback; error_scope scope; // Preserve error state
PyErr_Fetch(&type, &value, &traceback);
std::string errorString; std::string errorString;
if (type) { if (scope.type) {
errorString += handle(type).attr("__name__").cast<std::string>(); errorString += handle(scope.type).attr("__name__").cast<std::string>();
errorString += ": "; errorString += ": ";
} }
if (value) if (scope.value)
errorString += (std::string) handle(value).str(); errorString += (std::string) handle(scope.value).str();
PyErr_Restore(type, value, traceback);
return errorString; 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< template <typename T> constexpr const char format_descriptor<
T, typename std::enable_if<std::is_integral<T>::value>::type>::value[2]; 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(float, "f");
PYBIND11_DECL_FMT(double, "d"); PYBIND11_DECL_FMT(double, "d");
PYBIND11_DECL_FMT(bool, "?"); 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> template <return_value_policy policy = return_value_policy::automatic_reference, typename... Args>
void print(Args &&...args) { void print(Args &&...args) {
error_scope scope; // Preserve error state
auto c = detail::collect_arguments<policy>(std::forward<Args>(args)...); auto c = detail::collect_arguments<policy>(std::forward<Args>(args)...);
detail::print(c.args(), c.kwargs()); detail::print(c.args(), c.kwargs());
} }