Restore logging of historically-logged Python exceptions.

This commit is contained in:
AnyOldName3
2019-07-22 00:08:35 +01:00
parent 19dcdd95c0
commit 63a6c504b0
3 changed files with 77 additions and 26 deletions
+47 -8
View File
@@ -1,8 +1,9 @@
#ifndef Q_MOC_RUN
#include <boost/python.hpp>
#endif
#include <QString>
#include <utility.h>
#include <QDebug>
#include "error.h"
using namespace MOBase;
namespace bpy = boost::python;
@@ -10,17 +11,55 @@ namespace bpy = boost::python;
void reportPythonError()
{
if (PyErr_Occurred()) {
// prints to s_ErrIO buffer
ErrWrapper &errWrapper = ErrWrapper::instance();
errWrapper.startRecordingExceptionMessage();
PyErr_Print();
// extract data from python buffer
bpy::object mainModule = bpy::import("__main__");
bpy::object mainNamespace = mainModule.attr("__dict__");
bpy::object errMsgObj = bpy::eval("s_ErrIO.getvalue()", mainNamespace);
QString errMsg = bpy::extract<QString>(errMsgObj.ptr());
bpy::eval("s_ErrIO.truncate(0)", mainNamespace);
errWrapper.stopRecordingExceptionMessage();
QString errMsg = errWrapper.getLastExceptionMessage();
throw MyException(errMsg);
} else {
throw MyException("An unexpected C++ exception was thrown in python code");
}
}
ErrWrapper & ErrWrapper::instance()
{
static ErrWrapper err;
return err;
}
void ErrWrapper::write(const char * message)
{
buffer << message;
if (buffer.tellp() != 0 && buffer.str().back() == '\n')
{
// actually put the string in a variable so it doesn't get destroyed as soon as we get a pointer to its data
std::string string = buffer.str().substr(0, buffer.str().length() - 1);
qCritical().nospace().noquote() << string.c_str();
buffer = std::stringstream();
}
if (recordingExceptionMessage)
{
lastException << message;
}
}
void ErrWrapper::startRecordingExceptionMessage()
{
recordingExceptionMessage = true;
lastException = std::stringstream();
}
void ErrWrapper::stopRecordingExceptionMessage()
{
recordingExceptionMessage = false;
}
QString ErrWrapper::getLastExceptionMessage()
{
return QString::fromStdString(lastException.str());
}
+19
View File
@@ -1,7 +1,26 @@
#ifndef ERROR_H
#define ERROR_H
#include <QString>
#include <sstream>
// turn an error from the python interpreter into an exception
void reportPythonError();
struct ErrWrapper
{
static ErrWrapper & instance();
void write(const char * message);
void startRecordingExceptionMessage();
void stopRecordingExceptionMessage();
QString getLastExceptionMessage();
std::stringstream buffer;
bool recordingExceptionMessage;
std::stringstream lastException;
};
#endif // ERROR_H
+11 -18
View File
@@ -1306,7 +1306,9 @@ struct PrintWrapper
buffer << message;
if (buffer.tellp() != 0 && buffer.str().back() == '\n')
{
qDebug().nospace().noquote() << buffer.str().substr(0, buffer.str().length() - 1).c_str();
// actually put the string in a variable so it doesn't get destroyed as soon as we get a pointer to its data
std::string string = buffer.str().substr(0, buffer.str().length() - 1);
qDebug().nospace().noquote() << string.c_str();
buffer = std::stringstream();
}
}
@@ -1314,27 +1316,18 @@ struct PrintWrapper
std::stringstream buffer;
};
struct ErrWrapper
{
void write(const char * message)
{
buffer << message;
if (buffer.tellp() != 0 && buffer.str().back() == '\n')
{
qCritical().nospace().noquote() << buffer.str().substr(0, buffer.str().length() - 1).c_str();
buffer = std::stringstream();
}
}
std::stringstream buffer;
};
// ErrWrapper is in error.h
BOOST_PYTHON_MODULE(moprivate)
{
bpy::class_<PrintWrapper, boost::noncopyable>("PrintWrapper", bpy::init<>())
.def("write", &PrintWrapper::write);
bpy::class_<ErrWrapper, boost::noncopyable>("ErrWrapper", bpy::init<>())
.def("write", &ErrWrapper::write);
.def("instance", &ErrWrapper::instance, bpy::return_value_policy<bpy::reference_existing_object>()).staticmethod("instance")
.def("write", &ErrWrapper::write)
.def("startRecordingExceptionMessage", &ErrWrapper::startRecordingExceptionMessage)
.def("stopRecordingExceptionMessage", &ErrWrapper::stopRecordingExceptionMessage)
.def("getLastExceptionMessage", &ErrWrapper::getLastExceptionMessage);
}
bool PythonRunner::initPython(const QString &pythonPath)
@@ -1372,8 +1365,8 @@ bool PythonRunner::initPython(const QString &pythonPath)
mainNamespace["moprivate"] = bpy::import("moprivate");
bpy::import("site");
bpy::exec("sys.stdout = moprivate.PrintWrapper()\n"
"sys.stderr = moprivate.ErrWrapper()\n"
"sys.excepthook = lambda x, y, z: sys.__excepthook__(x, y, z)",
"sys.stderr = moprivate.ErrWrapper.instance()\n"
"sys.excepthook = lambda x, y, z: sys.__excepthook__(x, y, z)\n",
mainNamespace);
return true;