decode a Python exception into a string
| 65 | |
| 66 | // decode a Python exception into a string |
| 67 | std::string handle_pyerror( |
| 68 | bool crash_dump, |
| 69 | std::string module, |
| 70 | std::string caller) |
| 71 | { |
| 72 | using namespace boost::python; |
| 73 | using namespace boost; |
| 74 | |
| 75 | PyObject *exc, *val, *tb; |
| 76 | object formatted_list, formatted; |
| 77 | PyErr_Fetch(&exc, &val, &tb); |
| 78 | PyErr_NormalizeException(&exc, &val, &tb); |
| 79 | handle<> hexc(exc), hval(allow_null(val)), htb(allow_null(tb)); |
| 80 | |
| 81 | object traceback(import("traceback")); |
| 82 | if (!tb) { |
| 83 | object format_exception_only(traceback.attr("format_exception_only")); |
| 84 | try { |
| 85 | formatted_list = format_exception_only(hexc, hval); |
| 86 | } catch (error_already_set const &) { |
| 87 | // error while processing exception object |
| 88 | // returning only the exception string value |
| 89 | PyObject *name_attr = PyObject_GetAttrString(exc, "__name__"); |
| 90 | std::stringstream ss; |
| 91 | ss << PyUnicode_AsUTF8(name_attr) << ": " << PyUnicode_AsUTF8(val); |
| 92 | Py_XDECREF(name_attr); |
| 93 | ss << "\nError processing exception object: " << peek_pyerror(); |
| 94 | return ss.str(); |
| 95 | } |
| 96 | } else { |
| 97 | object format_exception(traceback.attr("format_exception")); |
| 98 | try { |
| 99 | formatted_list = format_exception(hexc, hval, htb); |
| 100 | } catch (error_already_set const &) { |
| 101 | // error while processing exception object |
| 102 | // returning only the exception string value |
| 103 | PyObject *name_attr = PyObject_GetAttrString(exc, "__name__"); |
| 104 | std::stringstream ss; |
| 105 | ss << PyUnicode_AsUTF8(name_attr) << ": " << PyUnicode_AsUTF8(val); |
| 106 | Py_XDECREF(name_attr); |
| 107 | ss << "\nError processing exception object: " << peek_pyerror(); |
| 108 | return ss.str(); |
| 109 | } |
| 110 | } |
| 111 | formatted = str("").join(formatted_list); |
| 112 | |
| 113 | if (!module.empty()) { |
| 114 | std::list<std::string> bt_strings; |
| 115 | std::map<std::string, std::string> extra; |
| 116 | |
| 117 | extra["mgr_module"] = module; |
| 118 | extra["mgr_module_caller"] = caller; |
| 119 | PyObject *name_attr = PyObject_GetAttrString(exc, "__name__"); |
| 120 | extra["mgr_python_exception"] = stringify(PyUnicode_AsUTF8(name_attr)); |
| 121 | Py_XDECREF(name_attr); |
| 122 | |
| 123 | PyObject *l = get_managed_object(formatted_list, boost::python::tag); |
| 124 | if (PyList_Check(l)) { |
no test coverage detected