From 62f10c03ff867e9c7fe645b4adcdba00c3624e1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sat, 9 May 2020 21:13:45 +0200 Subject: [PATCH] Temporary commit. --- src/runner/error.cpp | 17 --- src/runner/error.h | 110 +++++++++++++++- src/runner/proxypluginwrappers.cpp | 17 ++- src/runner/proxypluginwrappers.h | 14 ++ src/runner/pythonrunner.cpp | 142 +++++++++++---------- src/runner/pythonutils.h | 7 +- src/runner/pythonwrapperutilities.h | 69 +++++++--- src/runner/uibasewrappers.h | 191 +--------------------------- 8 files changed, 271 insertions(+), 296 deletions(-) diff --git a/src/runner/error.cpp b/src/runner/error.cpp index e17cd14..7ef6700 100644 --- a/src/runner/error.cpp +++ b/src/runner/error.cpp @@ -8,23 +8,6 @@ using namespace MOBase; namespace bpy = boost::python; -void reportPythonError() -{ - if (PyErr_Occurred()) { - ErrWrapper &errWrapper = ErrWrapper::instance(); - - errWrapper.startRecordingExceptionMessage(); - PyErr_Print(); - 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; diff --git a/src/runner/error.h b/src/runner/error.h index 2cadb57..d4f8b10 100644 --- a/src/runner/error.h +++ b/src/runner/error.h @@ -1,16 +1,17 @@ #ifndef ERROR_H #define ERROR_H -#include -#include -// turn an error from the python interpreter into an exception -void reportPythonError(); +#include + +#include + +#include struct ErrWrapper { - static ErrWrapper & instance(); - - void write(const char * message); + static ErrWrapper& instance(); + + void write(const char* message); void startRecordingExceptionMessage(); @@ -23,4 +24,99 @@ struct ErrWrapper std::stringstream lastException; }; +namespace pyexcept { + + /** + * @brief Exception to throw when a python implementation does not implement + * a pure virtual function. + */ + class MissingImplementation : public MOBase::MyException { + public: + MissingImplementation(std::string const& className, std::string const& methodName) : + MyException(QString::fromStdString( + fmt::format("Python class implementing \"{}\" has no implementation of method \"{}\".", + className, methodName))) { } + + }; + + /** + * @brief Exception to throw when a python error occurs. + */ + class PythonError : public MOBase::MyException { + public: + + /** + * @brief Create a new PythonError, fetching the error message from python. If the message + * cannot be retrieved, `defaultErrorMessage()` is used instead. + */ + PythonError() : MyException(getPythonErrorMessage()) { } + + /** + * @brief Create a new PythonError with the given message. + * + * @param message Message for the exception. + */ + PythonError(QString message) : MyException(message) { } + + protected: + + /** + * + */ + static QString defaultErrorMessage() { + return QObject::tr("An unexpected C++ exception was thrown in python code."); + } + + /** + * + */ + static QString getPythonErrorMessage() { + if (PyErr_Occurred()) { + ErrWrapper& errWrapper = ErrWrapper::instance(); + + errWrapper.startRecordingExceptionMessage(); + PyErr_Print(); + errWrapper.stopRecordingExceptionMessage(); + + return errWrapper.getLastExceptionMessage(); + } + else { + return defaultErrorMessage(); + } + } + }; + + /** + * @brief Exception to throw when an unknown error occured. This is typically thrown + * from a catch(...) block. + */ + class UnknownException : public MOBase::MyException { + public: + + /** + * @brief Create a new UnknownException with the default message. + * + * @see defaultErrorMessage + */ + UnknownException() : MyException(defaultErrorMessage()) { } + + /** + * @brief Create a new UnknownException with the given message. + * + * @param message Message for the exception. + */ + UnknownException(QString message) : MyException(message) { } + + protected: + + /** + * + */ + static QString defaultErrorMessage() { + return QObject::tr("An unknown exception was thrown in python code."); + } + }; + +} + #endif // ERROR_H diff --git a/src/runner/proxypluginwrappers.cpp b/src/runner/proxypluginwrappers.cpp index bbcee99..5f7b18d 100644 --- a/src/runner/proxypluginwrappers.cpp +++ b/src/runner/proxypluginwrappers.cpp @@ -393,7 +393,7 @@ bool IPluginModPageWrapper::handlesDownload(const QUrl & pageURL, const QUrl & d void IPluginModPageWrapper::setParentWidget(QWidget * widget) { - basicWrapperFunctionImplementation(this, "setParentWidget", widget); + basicWrapperFunctionImplementationWithDefault(this, &IPluginModPageWrapper::setParentWidget_Default, "setParentWidget", widget); } /// end IPluginModPage Wrapper ///////////////////////////// @@ -414,12 +414,21 @@ QWidget *IPluginPreviewWrapper::genFilePreview(const QString &fileName, const QS GILock lock; boost::python::override implementation = this->get_override("genFilePreview"); if (!implementation) - throw MissingImplementation(this->className, "genFilePreview"); + throw pyexcept::MissingImplementation(this->className, "genFilePreview"); boost::python::object pyVersion = implementation(fileName, maxSize); // We need responsibility for deleting the QWidget to be transferred to C++ sipAPIAccess::sipAPI()->api_transfer_to(pyVersion.ptr(), Py_None); return boost::python::extract(pyVersion)(); - } PYCATCH; + } + catch (const boost::python::error_already_set&) { + throw pyexcept::PythonError(); + } + catch (pyexcept::MissingImplementation const& missingImplementation) { + throw missingImplementation; + } + catch (...) { + throw pyexcept::UnknownException(); + } } /// end IPluginPreview Wrapper ///////////////////////////// @@ -445,7 +454,7 @@ QIcon IPluginToolWrapper::icon() const void IPluginToolWrapper::setParentWidget(QWidget *parent) { - basicWrapperFunctionImplementation(this, "setParentWidget", parent); + basicWrapperFunctionImplementationWithDefault(this, &IPluginToolWrapper::setParentWidget_Default, "setParentWidget", parent); } void IPluginToolWrapper::display() const diff --git a/src/runner/proxypluginwrappers.h b/src/runner/proxypluginwrappers.h index c24d4ad..f2ca83f 100644 --- a/src/runner/proxypluginwrappers.h +++ b/src/runner/proxypluginwrappers.h @@ -186,12 +186,19 @@ public: static constexpr const char* className = "IPluginModPageWrapper"; using boost::python::wrapper::get_override; + // Bring in public scope: + using IPluginModPage::parentWidget; + virtual QString displayName() const override; virtual QIcon icon() const override; virtual QUrl pageURL() const override; virtual bool useIntegratedBrowser() const override; virtual bool handlesDownload(const QUrl &pageURL, const QUrl &downloadURL, MOBase::ModRepositoryFileInfo &fileInfo) const override; virtual void setParentWidget(QWidget *widget) override; + + void setParentWidget_Default(QWidget* parent) { + IPluginModPage::setParentWidget(parent); + } }; @@ -220,11 +227,18 @@ public: static constexpr const char* className = "IPluginToolWrapper"; using boost::python::wrapper::get_override; + // Bring in public scope: + using IPluginTool::parentWidget; + virtual QString displayName() const; virtual QString tooltip() const; virtual QIcon icon() const; virtual void setParentWidget(QWidget *parent); + void setParentWidget_Default(QWidget* parent) { + IPluginTool::setParentWidget(parent); + } + public Q_SLOTS: virtual void display() const; }; diff --git a/src/runner/pythonrunner.cpp b/src/runner/pythonrunner.cpp index 0d9b6cc..938186f 100644 --- a/src/runner/pythonrunner.cpp +++ b/src/runner/pythonrunner.cpp @@ -569,16 +569,6 @@ struct Functor_converter }; -// We must wrap IOrganizer::waitForApplication to convert the out parameter to a return value and also because bpy doesn't like coverting to void* (HANDLE) even if a converter exists. -static PyObject *waitForApplication(const bpy::object &self, size_t handle) -{ - IOrganizer& organizer = bpy::extract(self)(); - DWORD returnCode; - bool result = organizer.waitForApplication((HANDLE)handle, &returnCode); - return bpy::incref(bpy::make_tuple(result, returnCode).ptr()); -} - - /** * @brief Call policy that automatically downcast shared pointer of type FromType * to shared pointer of type ToType. @@ -671,6 +661,7 @@ BOOST_PYTHON_MODULE(mobase) utils::register_associative_container(); // Tuple: + bpy::register_tuple>(); // IOrganizer::waitForApplication bpy::register_tuple, QString, int>>(); // Variants: @@ -683,13 +674,13 @@ BOOST_PYTHON_MODULE(mobase) // Functions: Functor_converter(); // converter for the onRefreshed-callback + Functor_converter(); + Functor_converter(); Functor_converter(); // converter for the onModStateChanged-callback Functor_converter(); - Functor_converter(); Functor_converter(); - Functor_converter(); - Functor_converter(QString const&)>(); Functor_converter const&)>(); + Functor_converter(QString const&)>(); bpy::def("toPyQt", &toPyQt); @@ -765,45 +756,55 @@ BOOST_PYTHON_MODULE(mobase) .def_readwrite("origins", &IOrganizer::FileInfo::origins) ; - bpy::class_("IOrganizer") - .def("createNexusBridge", bpy::pure_virtual(&IOrganizer::createNexusBridge), bpy::return_value_policy()) - .def("profileName", bpy::pure_virtual(&IOrganizer::profileName)) - .def("profilePath", bpy::pure_virtual(&IOrganizer::profilePath)) - .def("downloadsPath", bpy::pure_virtual(&IOrganizer::downloadsPath)) - .def("overwritePath", bpy::pure_virtual(&IOrganizer::overwritePath)) - .def("basePath", bpy::pure_virtual(&IOrganizer::basePath)) - .def("modsPath", bpy::pure_virtual(&IOrganizer::modsPath)) - .def("appVersion", bpy::pure_virtual(&IOrganizer::appVersion)) - .def("getMod", bpy::pure_virtual(&IOrganizer::getMod), bpy::return_value_policy()) - .def("createMod", bpy::pure_virtual(&IOrganizer::createMod), bpy::return_value_policy()) - .def("getGame", bpy::pure_virtual(&IOrganizer::getGame), bpy::return_value_policy()) - .def("removeMod", bpy::pure_virtual(&IOrganizer::removeMod)) - .def("modDataChanged", bpy::pure_virtual(&IOrganizer::modDataChanged)) - .def("pluginSetting", bpy::pure_virtual(&IOrganizer::pluginSetting)) - .def("setPluginSetting", bpy::pure_virtual(&IOrganizer::setPluginSetting)) - .def("persistent", bpy::pure_virtual(&IOrganizer::persistent)) - .def("setPersistent", bpy::pure_virtual(&IOrganizer::setPersistent)) - .def("pluginDataPath", bpy::pure_virtual(&IOrganizer::pluginDataPath)) - .def("installMod", bpy::pure_virtual(&IOrganizer::installMod),(bpy::arg("nameSuggestion")=""), bpy::return_value_policy()) - .def("resolvePath", bpy::pure_virtual(&IOrganizer::resolvePath)) - .def("listDirectories", bpy::pure_virtual(&IOrganizer::listDirectories)) - .def("findFiles", bpy::pure_virtual(&IOrganizer::findFiles)) - .def("getFileOrigins", bpy::pure_virtual(&IOrganizer::getFileOrigins)) - .def("findFileInfos", bpy::pure_virtual(&IOrganizer::findFileInfos)) - .def("downloadManager", bpy::pure_virtual(&IOrganizer::downloadManager), bpy::return_value_policy()) - .def("pluginList", bpy::pure_virtual(&IOrganizer::pluginList), bpy::return_value_policy()) - .def("modList", bpy::pure_virtual(&IOrganizer::modList), bpy::return_value_policy()) - .def("profile", bpy::pure_virtual(&IOrganizer::profile), bpy::return_value_policy()) - .def("startApplication", bpy::pure_virtual(&IOrganizer::startApplication), ((bpy::arg("args")=QStringList()), (bpy::arg("cwd")=""), (bpy::arg("profile")=""), (bpy::arg("forcedCustomOverwrite")=""), (bpy::arg("ignoreCustomOverwrite")=false)), bpy::return_value_policy()) + bpy::class_("IOrganizer", bpy::no_init) + .def("createNexusBridge", &IOrganizer::createNexusBridge, bpy::return_value_policy()) + .def("profileName", &IOrganizer::profileName) + .def("profilePath", &IOrganizer::profilePath) + .def("downloadsPath", &IOrganizer::downloadsPath) + .def("overwritePath", &IOrganizer::overwritePath) + .def("basePath", &IOrganizer::basePath) + .def("modsPath", &IOrganizer::modsPath) + .def("appVersion", &IOrganizer::appVersion) + .def("getMod", &IOrganizer::getMod, bpy::return_value_policy()) + .def("createMod", &IOrganizer::createMod, bpy::return_value_policy()) + .def("getGame", &IOrganizer::getGame, bpy::return_value_policy()) + .def("removeMod", &IOrganizer::removeMod) + .def("modDataChanged", &IOrganizer::modDataChanged) + .def("pluginSetting", &IOrganizer::pluginSetting) + .def("setPluginSetting", &IOrganizer::setPluginSetting) + .def("persistent", &IOrganizer::persistent, bpy::arg("persistent") = QVariant()) + .def("setPersistent", &IOrganizer::setPersistent, bpy::arg("sync") = true) + .def("pluginDataPath", &IOrganizer::pluginDataPath) + .def("installMod", &IOrganizer::installMod, (bpy::arg("name_suggestion") = ""), bpy::return_value_policy()) + .def("resolvePath", &IOrganizer::resolvePath) + .def("listDirectories", &IOrganizer::listDirectories) + .def("findFiles", &IOrganizer::findFiles) + .def("getFileOrigins", &IOrganizer::getFileOrigins) + .def("findFileInfos", &IOrganizer::findFileInfos) + .def("downloadManager", &IOrganizer::downloadManager, bpy::return_value_policy()) + .def("pluginList", &IOrganizer::pluginList, bpy::return_value_policy()) + .def("modList", &IOrganizer::modList, bpy::return_value_policy()) + .def("profile", &IOrganizer::profile, bpy::return_value_policy()) + .def("startApplication", + +[](IOrganizer* o, const QString& executable, const QStringList& args, const QString& cwd, const QString& profile, + const QString& forcedCustomOverwrite, bool ignoreCustomOverwrite) { + return (std::uintptr_t) o->startApplication(executable, args, cwd, profile, forcedCustomOverwrite, ignoreCustomOverwrite); + }, + ((bpy::arg("args") = QStringList()), (bpy::arg("cwd") = ""), (bpy::arg("profile") = ""), (bpy::arg("forcedCustomOverwrite") = ""), (bpy::arg("ignoreCustomOverwrite") = false)), bpy::return_value_policy()) //.def("waitForApplication", bpy::pure_virtual(&IOrganizer::waitForApplication), (bpy::arg("exitCode")=nullptr), bpy::return_value_policy()) // Use wrapped version - .def("waitForApplication", waitForApplication) - .def("onModInstalled", bpy::pure_virtual(&IOrganizer::onModInstalled)) - .def("onAboutToRun", bpy::pure_virtual(&IOrganizer::onAboutToRun)) - .def("onFinishedRun", bpy::pure_virtual(&IOrganizer::onFinishedRun)) - .def("refreshModList", bpy::pure_virtual(&IOrganizer::refreshModList), (bpy::arg("saveChanges")=true)) - .def("managedGame", bpy::pure_virtual(&IOrganizer::managedGame), bpy::return_value_policy()) - .def("modsSortedByProfilePriority", bpy::pure_virtual(&IOrganizer::modsSortedByProfilePriority)) + .def("waitForApplication", +[](IOrganizer *o, std::uintptr_t handle) { + DWORD returnCode; + bool result = o->waitForApplication((HANDLE)handle, &returnCode); + return std::make_tuple(result, returnCode); + } + ) + .def("onModInstalled", &IOrganizer::onModInstalled) + .def("onAboutToRun", &IOrganizer::onAboutToRun) + .def("onFinishedRun", &IOrganizer::onFinishedRun) + .def("refreshModList", &IOrganizer::refreshModList, (bpy::arg("save_changes")=true)) + .def("managedGame", &IOrganizer::managedGame, bpy::return_value_policy()) + .def("modsSortedByProfilePriority", &IOrganizer::modsSortedByProfilePriority) ; // FileTreeEntry Scope: @@ -977,11 +978,11 @@ BOOST_PYTHON_MODULE(mobase) ; utils::register_sequence_container>>(); - bpy::class_("IInstallationManager") - .def("extractFile", bpy::pure_virtual(&IInstallationManager::extractFile)) - .def("extractFiles", bpy::pure_virtual(&IInstallationManager::extractFiles)) - .def("installArchive", bpy::pure_virtual(&IInstallationManager::installArchive)) - .def("setURL", bpy::pure_virtual(&IInstallationManager::setURL)) + bpy::class_("IInstallationManager", bpy::no_init) + .def("extractFile", &IInstallationManager::extractFile) + .def("extractFiles", &IInstallationManager::extractFiles) + .def("installArchive", &IInstallationManager::installArchive) + .def("setURL", &IInstallationManager::setURL) ; bpy::class_("IModInterface") @@ -1205,27 +1206,39 @@ BOOST_PYTHON_MODULE(mobase) auto result = p->install(modName, tree, version, nexusID); return std::make_tuple(result, tree, version, nexusID); }) - .def("parentWidget", &IPluginInstallerSimpleWrapper::parentWidget, bpy::return_value_policy()) - .def("manager", &IPluginInstallerSimpleWrapper::manager, bpy::return_value_policy()) + .def("_parentWidget", &IPluginInstallerSimpleWrapper::parentWidget, bpy::return_value_policy()) + .def("_manager", &IPluginInstallerSimpleWrapper::manager, bpy::return_value_policy()) ; bpy::class_("IPluginInstallerCustom") .def("isArchiveSupported", &IPluginInstallerCustom::isArchiveSupported) .def("supportedExtensions", &IPluginInstallerCustom::supportedExtensions) .def("install", &IPluginInstallerCustom::install) - .def("parentWidget", &IPluginInstallerSimpleWrapper::parentWidget, bpy::return_value_policy()) - .def("manager", &IPluginInstallerCustomWrapper::manager, bpy::return_value_policy()) + .def("_parentWidget", &IPluginInstallerSimpleWrapper::parentWidget, bpy::return_value_policy()) + .def("_manager", &IPluginInstallerCustomWrapper::manager, bpy::return_value_policy()) ; bpy::class_("IPluginModPage") - .def("setParentWidget", bpy::pure_virtual(&MOBase::IPluginModPage::setParentWidget)) + .def("displayName", bpy::pure_virtual(&IPluginModPage::displayName)) + .def("icon", bpy::pure_virtual(&IPluginModPage::icon)) + .def("pageURL", bpy::pure_virtual(&IPluginModPage::pageURL)) + .def("useIntegratedBrowser", bpy::pure_virtual(&IPluginModPage::useIntegratedBrowser)) + .def("handlesDownload", bpy::pure_virtual(&IPluginModPage::handlesDownload)) + .def("setParentWidget", &IPluginModPage::setParentWidget, &IPluginModPageWrapper::setParentWidget_Default) + .def("_parentWidget", &IPluginModPageWrapper::parentWidget, bpy::return_value_policy()) ; - bpy::class_("IPluginPreview") + bpy::class_, boost::noncopyable>("IPluginPreview") + .def("supportedExtensions", bpy::pure_virtual(&IPluginPreview::supportedExtensions)) + .def("genFilePreview", bpy::pure_virtual(&IPluginPreview::genFilePreview), bpy::return_value_policy()) ; bpy::class_, boost::noncopyable>("IPluginTool") - .def("setParentWidget", bpy::pure_virtual(&MOBase::IPluginTool::setParentWidget)) + .def("displayName", bpy::pure_virtual(&IPluginTool::displayName)) + .def("tooltip", bpy::pure_virtual(&IPluginTool::tooltip)) + .def("icon", bpy::pure_virtual(&IPluginTool::icon)) + .def("setParentWidget", &IPluginTool::setParentWidget, &IPluginToolWrapper::setParentWidget_Default) + .def("_parentWidget", &IPluginToolWrapper::parentWidget, bpy::return_value_policy()) ; HANDLE_converters(); @@ -1374,8 +1387,7 @@ QList PythonRunner::instantiate(const QString &pluginName) std::string temp = ToString(pluginName); if (handled_exec_file(temp.c_str(), moduleNamespace)) { - reportPythonError(); - return QList(); + throw pyexcept::PythonError(); } m_PythonObjects[pluginName] = moduleNamespace["createPlugin"](); @@ -1399,7 +1411,7 @@ QList PythonRunner::instantiate(const QString &pluginName) return interfaceList; } catch (const bpy::error_already_set&) { qWarning("failed to run python script \"%s\"", qUtf8Printable(pluginName)); - reportPythonError(); + throw pyexcept::PythonError(); } return QList(); } diff --git a/src/runner/pythonutils.h b/src/runner/pythonutils.h index 4aeb550..b424d15 100644 --- a/src/runner/pythonutils.h +++ b/src/runner/pythonutils.h @@ -70,11 +70,12 @@ namespace utils { bpy::list pyList; try { - for (auto& item : container) + for (auto& item : container) { pyList.append(item); + } } catch (const bpy::error_already_set&) { - reportPythonError(); + throw pyexcept::PythonError(); } return bpy::incref(pyList.ptr()); @@ -115,7 +116,7 @@ namespace utils { pyList.append(item); } catch (const bpy::error_already_set&) { - reportPythonError(); + throw pyexcept::PythonError(); } return bpy::incref(pyList.ptr()); diff --git a/src/runner/pythonwrapperutilities.h b/src/runner/pythonwrapperutilities.h index 86317e0..d11acc2 100644 --- a/src/runner/pythonwrapperutilities.h +++ b/src/runner/pythonwrapperutilities.h @@ -1,32 +1,71 @@ #ifndef PYTHONWRAPPERUTILITIES_H #define PYTHONWRAPPERUTILITIES_H +#include + #include #include "error.h" -class MissingImplementation : public MOBase::MyException { -public: - MissingImplementation(QString className, QString methodName) : MyException("Python class implementing \"" + - className + - "\" has no implementation of method \"" + - methodName + "\"") {} -}; - -#define PYCATCH catch (const boost::python::error_already_set &) { reportPythonError(); throw MOBase::MyException("unhandled exception"); }\ - catch (const MissingImplementation &missingImplementationException) { throw missingImplementationException; }\ - catch (...) { throw MOBase::MyException("An unknown exception was thrown in python code"); } - -template +template ReturnType basicWrapperFunctionImplementation(const WrapperType *wrapper, const char *methodName, Args... args) { try { GILock lock; boost::python::override implementation = wrapper->get_override(methodName); if (!implementation) - throw MissingImplementation(wrapper->className, methodName); + throw pyexcept::MissingImplementation(wrapper->className, methodName); return implementation(args...).as(); - } PYCATCH; + } + catch (const boost::python::error_already_set&) { + throw pyexcept::PythonError(); + } + catch (pyexcept::MissingImplementation const& missingImplementation) { + throw missingImplementation; + } + catch (...) { + throw pyexcept::UnknownException(); + } +} + +template +ReturnType basicWrapperFunctionImplementationWithDefault(WrapperType* wrapper, Fn fn, const char* methodName, Args... args) +{ + try { + GILock lock; + boost::python::override implementation = wrapper->get_override(methodName); + if (implementation) { + return implementation(args...).as(); + } + } + catch (const boost::python::error_already_set&) { + throw pyexcept::PythonError(); + } + catch (...) { + throw pyexcept::UnknownException(); + } + + return std::invoke(fn, wrapper, args...); +} + +template +ReturnType basicWrapperFunctionImplementationWithDefault(const WrapperType* wrapper, Fn fn, const char* methodName, Args... args) +{ + try { + GILock lock; + boost::python::override implementation = wrapper->get_override(methodName); + if (implementation) { + return implementation(args...).as(); + } + } + catch (const boost::python::error_already_set&) { + throw pyexcept::PythonError(); + } + catch (...) { + throw pyexcept::UnknownException(); + } + + return std::invoke(fn, wrapper, args...); } #endif // PYTHONWRAPPERUTILITIES_H diff --git a/src/runner/uibasewrappers.h b/src/runner/uibasewrappers.h index bab65bb..e1e14ce 100644 --- a/src/runner/uibasewrappers.h +++ b/src/runner/uibasewrappers.h @@ -126,7 +126,7 @@ private Q_SLOTS: GILock lock; m_FilesAvailableHandler(modID, userData, resultData); } catch (const boost::python::error_already_set&) { - reportPythonError(); + throw pyexcept::PythonError(); } } @@ -141,7 +141,7 @@ private Q_SLOTS: GILock lock; m_DescriptionAvailableHandler(modID, userData, resultData); } catch (const boost::python::error_already_set&) { - reportPythonError(); + throw pyexcept::PythonError(); } } catch (const std::exception &e) { qCritical("failed to report event: %s", e.what()); @@ -160,7 +160,7 @@ private Q_SLOTS: GILock lock; m_FileInfoHandler(modID, fileID, userData, resultData); } catch (const boost::python::error_already_set&) { - reportPythonError(); + throw pyexcept::PythonError(); } } catch (const std::exception &e) { qCritical("failed to report event: %s", e.what()); @@ -180,7 +180,7 @@ private Q_SLOTS: GILock lock; m_EndorsementToggledHandler(modID, userData, resultData); } catch (const boost::python::error_already_set&) { - reportPythonError(); + throw pyexcept::PythonError(); } } catch (const std::exception &e) { qCritical("failed to report event: %s", e.what()); @@ -200,7 +200,7 @@ private Q_SLOTS: GILock lock; m_TrackingToggledHandler(modID, userData, tracked); } catch (const boost::python::error_already_set&) { - reportPythonError(); + throw pyexcept::PythonError(); } } catch (const std::exception &e) { qCritical("failed to report event: %s", e.what()); @@ -215,7 +215,7 @@ private Q_SLOTS: GILock lock; m_FailedHandler(modID, fileID, userData, errorMessage); } catch (const boost::python::error_already_set&) { - reportPythonError(); + throw pyexcept::PythonError(); } } @@ -231,176 +231,6 @@ private: }; -// NOTE: Completely unnecessary - we're never going to override IOrganizer from within Python -struct IOrganizerWrapper : MOBase::IOrganizer, - boost::python::wrapper { - virtual MOBase::IModRepositoryBridge *createNexusBridge() const override - { - return this->get_override("createNexusBridge")(); - } - virtual QString profileName() const override - { - return this->get_override("profileName")(); - } - virtual QString profilePath() const override - { - return this->get_override("profilePath")(); - } - virtual QString downloadsPath() const override - { - return this->get_override("downloadsPath")(); - } - virtual QString overwritePath() const override - { - return this->get_override("overwritePath")(); - } - virtual QString basePath() const // override - { - return this->get_override("basePath")(); - } - virtual QString modsPath() const override - { - return this->get_override("modsPath")(); - } - virtual MOBase::VersionInfo appVersion() const override - { - return this->get_override("appVersion")(); - } - virtual MOBase::IModInterface *getMod(const QString &name) const override - { - return this->get_override("getMod")(name); - } - virtual MOBase::IModInterface * - createMod(MOBase::GuessedValue &name) override - { - return this->get_override("createMod")(name); - } - virtual MOBase::IPluginGame *getGame(const QString &gameName) const override - { - return this->get_override("getGame")(gameName); - } - virtual bool removeMod(MOBase::IModInterface *mod) override - { - return this->get_override("removeMod")(mod); - } - virtual void modDataChanged(MOBase::IModInterface *mod) override - { - this->get_override("modDataChanged")(mod); - } - virtual QVariant pluginSetting(const QString &pluginName, - const QString &key) const override - { - return this->get_override("pluginSetting")(pluginName, key).as(); - } - virtual void setPluginSetting(const QString &pluginName, const QString &key, - const QVariant &value) override - { - this->get_override("setPluginSetting")(pluginName, key, value); - } - virtual QVariant persistent(const QString &pluginName, const QString &key, - const QVariant &def = QVariant()) const override - { - return this->get_override("persistent")(pluginName, key, def).as(); - } - virtual void setPersistent(const QString &pluginName, const QString &key, - const QVariant &value, bool sync = true) override - { - this->get_override("setPersistent")(pluginName, key, value, sync); - } - virtual QString pluginDataPath() const override - { - return this->get_override("pluginDataPath")(); - } - virtual MOBase::IModInterface *installMod(const QString &fileName, - const QString &nameSuggestion - = QString()) override - { - return this->get_override("installMod")(fileName, nameSuggestion); - } - virtual MOBase::IDownloadManager *downloadManager() const override - { - return this->get_override("downloadManager")(); - } - virtual MOBase::IPluginList *pluginList() const override - { - return this->get_override("pluginList")(); - } - virtual MOBase::IModList *modList() const override - { - return this->get_override("modList")(); - } - virtual QString resolvePath(const QString &fileName) const override - { - return this->get_override("resolvePath")(fileName); - } - virtual QStringList - listDirectories(const QString &directoryName) const override - { - return this->get_override("listDirectories")(directoryName); - } - virtual QStringList - findFiles(const QString &path, - const std::function &filter) const override - { - return this->get_override("findFiles")(path, filter); - } - virtual QStringList getFileOrigins(const QString &fileName) const override - { - return this->get_override("getFileOrigins")(fileName); - } - virtual QList findFileInfos( - const QString &path, - const std::function &filter) const override - { - return this->get_override("findFileInfos")(path, filter); - } - virtual HANDLE startApplication(const QString &executable, - const QStringList &args = QStringList(), - const QString &cwd = "", - const QString &profile = "", - const QString &forcedCustomOverwrite = "", - bool ignoreCustomOverwrite = false) override - { - return reinterpret_cast(this->get_override("startApplication")(executable, args, cwd, profile, forcedCustomOverwrite, ignoreCustomOverwrite).as()); - } - virtual bool waitForApplication(HANDLE handle, - LPDWORD exitCode = nullptr) const override - { - return this->get_override("waitForApplication")(reinterpret_cast(handle), exitCode); - } - virtual void refreshModList(bool saveChanges = true) override - { - this->get_override("refreshModList")(saveChanges); - } - virtual bool - onAboutToRun(const std::function &func) override - { - return this->get_override("onAboutToRun")(func); - } - virtual bool onFinishedRun( - const std::function &func) override - { - return this->get_override("onFinishedRun")(func); - } - virtual bool - onModInstalled(const std::function &func) override - { - return this->get_override("onModInstalled")(func); - } - virtual MOBase::IProfile *profile() const override - { - return this->get_override("profile")(); - } - virtual MOBase::IPluginGame const *managedGame() const override - { - return this->get_override("managedGame")(); - } - virtual QStringList modsSortedByProfilePriority() const override - { - return this->get_override("modsSortedByProfilePriority")(); - } -}; - struct IProfileWrapper: MOBase::IProfile, boost::python::wrapper { virtual QString name() const override { return this->get_override("name")(); } @@ -426,15 +256,6 @@ struct IModRepositoryBridgeWrapper: MOBase::IModRepositoryBridge, boost::python: virtual void requestToggleEndorsement(QString gameName, int modID, QString modVersion, bool endorse, QVariant userData) { this->get_override("requestToggleEndorsement")(gameName, modID, endorse, userData); } }; -struct IInstallationManagerWrapper: MOBase::IInstallationManager, boost::python::wrapper -{ - virtual QString extractFile(std::shared_ptr entry) override { return this->get_override("extractFile")(entry); } - virtual QStringList extractFiles(std::vector> const& entries) override { return this->get_override("extractFiles")(entries); } - virtual MOBase::IPluginInstaller::EInstallResult installArchive(MOBase::GuessedValue &modName, const QString &archiveFile, int modId = 0) override { - return this->get_override("installArchive")(modName, archiveFile, modId); } - virtual void setURL(QString const &url) override { this->get_override("setURL")(url); } -}; - struct IModInterfaceWrapper: MOBase::IModInterface, boost::python::wrapper { virtual QString name() const override { return this->get_override("name")(); }