| 139 | |
| 140 | protected: |
| 141 | Result<std::string> FormatImpl() const { |
| 142 | PyAcquireGIL lock; |
| 143 | |
| 144 | // Use traceback.format_exception() |
| 145 | OwnedRef traceback_module; |
| 146 | RETURN_NOT_OK(internal::ImportModule("traceback", &traceback_module)); |
| 147 | |
| 148 | OwnedRef fmt_exception; |
| 149 | RETURN_NOT_OK(internal::ImportFromModule(traceback_module.obj(), "format_exception", |
| 150 | &fmt_exception)); |
| 151 | |
| 152 | OwnedRef formatted; |
| 153 | formatted.reset(PyObject_CallFunctionObjArgs(fmt_exception.obj(), exc_type_.obj(), |
| 154 | exc_value_.obj(), exc_traceback_.obj(), |
| 155 | NULL)); |
| 156 | RETURN_IF_PYERROR(); |
| 157 | |
| 158 | std::stringstream ss; |
| 159 | ss << "Python exception: "; |
| 160 | Py_ssize_t num_lines = PySequence_Length(formatted.obj()); |
| 161 | RETURN_IF_PYERROR(); |
| 162 | |
| 163 | for (Py_ssize_t i = 0; i < num_lines; ++i) { |
| 164 | Py_ssize_t line_size; |
| 165 | |
| 166 | PyObject* line = PySequence_GetItem(formatted.obj(), i); |
| 167 | RETURN_IF_PYERROR(); |
| 168 | |
| 169 | const char* data = PyUnicode_AsUTF8AndSize(line, &line_size); |
| 170 | RETURN_IF_PYERROR(); |
| 171 | |
| 172 | ss << std::string_view(data, line_size); |
| 173 | } |
| 174 | return ss.str(); |
| 175 | } |
| 176 | |
| 177 | PythonErrorDetail() = default; |
| 178 |
nothing calls this directly
no test coverage detected