Temporary commit.

This commit is contained in:
Mikaël Capelle
2020-05-09 21:13:45 +02:00
parent 29a5eb8366
commit 62f10c03ff
8 changed files with 271 additions and 296 deletions
-17
View File
@@ -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;
+103 -7
View File
@@ -1,16 +1,17 @@
#ifndef ERROR_H
#define ERROR_H
#include <QString>
#include <sstream>
// turn an error from the python interpreter into an exception
void reportPythonError();
#include <QString>
#include <fmt/format.h>
#include <sstream>
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
+13 -4
View File
@@ -393,7 +393,7 @@ bool IPluginModPageWrapper::handlesDownload(const QUrl & pageURL, const QUrl & d
void IPluginModPageWrapper::setParentWidget(QWidget * widget)
{
basicWrapperFunctionImplementation<IPluginModPageWrapper, void>(this, "setParentWidget", widget);
basicWrapperFunctionImplementationWithDefault<IPluginModPageWrapper, void>(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<QWidget *>(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<IPluginToolWrapper, void>(this, "setParentWidget", parent);
basicWrapperFunctionImplementationWithDefault<IPluginToolWrapper, void>(this, &IPluginToolWrapper::setParentWidget_Default, "setParentWidget", parent);
}
void IPluginToolWrapper::display() const
+14
View File
@@ -186,12 +186,19 @@ public:
static constexpr const char* className = "IPluginModPageWrapper";
using boost::python::wrapper<MOBase::IPluginModPage>::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<MOBase::IPluginTool>::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;
};
+77 -65
View File
@@ -569,16 +569,6 @@ struct Functor_converter<RET(PARAMS... )>
};
// 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<IOrganizer&>(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<IFileTree::OverwritesType>();
// Tuple:
bpy::register_tuple<std::tuple<bool, DWORD>>(); // IOrganizer::waitForApplication
bpy::register_tuple<std::tuple<IPluginInstaller::EInstallResult, std::shared_ptr<IFileTree>, QString, int>>();
// Variants:
@@ -683,13 +674,13 @@ BOOST_PYTHON_MODULE(mobase)
// Functions:
Functor_converter<void()>(); // converter for the onRefreshed-callback
Functor_converter<void(const QString&)>();
Functor_converter<void(const QString&, unsigned int)>();
Functor_converter<void(const QString&, IModList::ModStates)>(); // converter for the onModStateChanged-callback
Functor_converter<bool(const IOrganizer::FileInfo&)>();
Functor_converter<void(const QString&)>();
Functor_converter<bool(const QString&)>();
Functor_converter<void(const QString&, unsigned int)>();
Functor_converter<std::variant<QString, bool>(QString const&)>();
Functor_converter<bool(std::shared_ptr<FileTreeEntry> const&)>();
Functor_converter<std::variant<QString, bool>(QString const&)>();
bpy::def("toPyQt", &toPyQt<IModRepositoryBridge>);
@@ -765,45 +756,55 @@ BOOST_PYTHON_MODULE(mobase)
.def_readwrite("origins", &IOrganizer::FileInfo::origins)
;
bpy::class_<IOrganizerWrapper, boost::noncopyable>("IOrganizer")
.def("createNexusBridge", bpy::pure_virtual(&IOrganizer::createNexusBridge), bpy::return_value_policy<bpy::reference_existing_object>())
.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<bpy::reference_existing_object>())
.def("createMod", bpy::pure_virtual(&IOrganizer::createMod), bpy::return_value_policy<bpy::reference_existing_object>())
.def("getGame", bpy::pure_virtual(&IOrganizer::getGame), bpy::return_value_policy<bpy::reference_existing_object>())
.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<bpy::reference_existing_object>())
.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<bpy::reference_existing_object>())
.def("pluginList", bpy::pure_virtual(&IOrganizer::pluginList), bpy::return_value_policy<bpy::reference_existing_object>())
.def("modList", bpy::pure_virtual(&IOrganizer::modList), bpy::return_value_policy<bpy::reference_existing_object>())
.def("profile", bpy::pure_virtual(&IOrganizer::profile), bpy::return_value_policy<bpy::reference_existing_object>())
.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::return_by_value>())
bpy::class_<IOrganizer, boost::noncopyable>("IOrganizer", bpy::no_init)
.def("createNexusBridge", &IOrganizer::createNexusBridge, bpy::return_value_policy<bpy::reference_existing_object>())
.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<bpy::reference_existing_object>())
.def("createMod", &IOrganizer::createMod, bpy::return_value_policy<bpy::reference_existing_object>())
.def("getGame", &IOrganizer::getGame, bpy::return_value_policy<bpy::reference_existing_object>())
.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<bpy::reference_existing_object>())
.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<bpy::reference_existing_object>())
.def("pluginList", &IOrganizer::pluginList, bpy::return_value_policy<bpy::reference_existing_object>())
.def("modList", &IOrganizer::modList, bpy::return_value_policy<bpy::reference_existing_object>())
.def("profile", &IOrganizer::profile, bpy::return_value_policy<bpy::reference_existing_object>())
.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<bpy::return_by_value>())
//.def("waitForApplication", bpy::pure_virtual(&IOrganizer::waitForApplication), (bpy::arg("exitCode")=nullptr), bpy::return_value_policy<bpy::return_by_value>())
// 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<bpy::reference_existing_object>())
.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<bpy::reference_existing_object>())
.def("modsSortedByProfilePriority", &IOrganizer::modsSortedByProfilePriority)
;
// FileTreeEntry Scope:
@@ -977,11 +978,11 @@ BOOST_PYTHON_MODULE(mobase)
;
utils::register_sequence_container<std::vector<std::shared_ptr<const MOBase::FileTreeEntry>>>();
bpy::class_<IInstallationManagerWrapper, boost::noncopyable>("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, boost::noncopyable>("IInstallationManager", bpy::no_init)
.def("extractFile", &IInstallationManager::extractFile)
.def("extractFiles", &IInstallationManager::extractFiles)
.def("installArchive", &IInstallationManager::installArchive)
.def("setURL", &IInstallationManager::setURL)
;
bpy::class_<IModInterfaceWrapper, boost::noncopyable>("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<bpy::return_by_value>())
.def("manager", &IPluginInstallerSimpleWrapper::manager, bpy::return_value_policy<bpy::reference_existing_object>())
.def("_parentWidget", &IPluginInstallerSimpleWrapper::parentWidget, bpy::return_value_policy<bpy::return_by_value>())
.def("_manager", &IPluginInstallerSimpleWrapper::manager, bpy::return_value_policy<bpy::reference_existing_object>())
;
bpy::class_<IPluginInstallerCustomWrapper, boost::noncopyable>("IPluginInstallerCustom")
.def("isArchiveSupported", &IPluginInstallerCustom::isArchiveSupported)
.def("supportedExtensions", &IPluginInstallerCustom::supportedExtensions)
.def("install", &IPluginInstallerCustom::install)
.def("parentWidget", &IPluginInstallerSimpleWrapper::parentWidget, bpy::return_value_policy<bpy::return_by_value>())
.def("manager", &IPluginInstallerCustomWrapper::manager, bpy::return_value_policy<bpy::reference_existing_object>())
.def("_parentWidget", &IPluginInstallerSimpleWrapper::parentWidget, bpy::return_value_policy<bpy::return_by_value>())
.def("_manager", &IPluginInstallerCustomWrapper::manager, bpy::return_value_policy<bpy::reference_existing_object>())
;
bpy::class_<IPluginModPageWrapper, boost::noncopyable>("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::return_by_value>())
;
bpy::class_<IPluginPreviewWrapper, boost::noncopyable>("IPluginPreview")
bpy::class_<IPluginPreviewWrapper, bpy::bases<IPlugin>, boost::noncopyable>("IPluginPreview")
.def("supportedExtensions", bpy::pure_virtual(&IPluginPreview::supportedExtensions))
.def("genFilePreview", bpy::pure_virtual(&IPluginPreview::genFilePreview), bpy::return_value_policy<bpy::return_by_value>())
;
bpy::class_<IPluginToolWrapper, bpy::bases<IPlugin>, 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<bpy::return_by_value>())
;
HANDLE_converters();
@@ -1374,8 +1387,7 @@ QList<QObject*> PythonRunner::instantiate(const QString &pluginName)
std::string temp = ToString(pluginName);
if (handled_exec_file(temp.c_str(), moduleNamespace)) {
reportPythonError();
return QList<QObject*>();
throw pyexcept::PythonError();
}
m_PythonObjects[pluginName] = moduleNamespace["createPlugin"]();
@@ -1399,7 +1411,7 @@ QList<QObject*> 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<QObject*>();
}
+4 -3
View File
@@ -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());
+54 -15
View File
@@ -1,32 +1,71 @@
#ifndef PYTHONWRAPPERUTILITIES_H
#define PYTHONWRAPPERUTILITIES_H
#include <functional>
#include <utility.h>
#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 <typename WrapperType, typename ReturnType, typename... Args>
template <class WrapperType, class ReturnType, class... Args>
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<ReturnType>();
} PYCATCH;
}
catch (const boost::python::error_already_set&) {
throw pyexcept::PythonError();
}
catch (pyexcept::MissingImplementation const& missingImplementation) {
throw missingImplementation;
}
catch (...) {
throw pyexcept::UnknownException();
}
}
template <class WrapperType, class ReturnType, class Fn, class... Args>
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<ReturnType>();
}
}
catch (const boost::python::error_already_set&) {
throw pyexcept::PythonError();
}
catch (...) {
throw pyexcept::UnknownException();
}
return std::invoke(fn, wrapper, args...);
}
template <class WrapperType, class ReturnType, class Fn, class... Args>
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<ReturnType>();
}
}
catch (const boost::python::error_already_set&) {
throw pyexcept::PythonError();
}
catch (...) {
throw pyexcept::UnknownException();
}
return std::invoke(fn, wrapper, args...);
}
#endif // PYTHONWRAPPERUTILITIES_H
+6 -185
View File
@@ -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<MOBase::IOrganizer> {
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<QString> &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<QVariant>();
}
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<QVariant>();
}
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<bool(const QString &)> &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<FileInfo> findFileInfos(
const QString &path,
const std::function<bool(const FileInfo &)> &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<HANDLE>(this->get_override("startApplication")(executable, args, cwd, profile, forcedCustomOverwrite, ignoreCustomOverwrite).as<size_t>());
}
virtual bool waitForApplication(HANDLE handle,
LPDWORD exitCode = nullptr) const override
{
return this->get_override("waitForApplication")(reinterpret_cast<size_t>(handle), exitCode);
}
virtual void refreshModList(bool saveChanges = true) override
{
this->get_override("refreshModList")(saveChanges);
}
virtual bool
onAboutToRun(const std::function<bool(const QString &)> &func) override
{
return this->get_override("onAboutToRun")(func);
}
virtual bool onFinishedRun(
const std::function<void(const QString &, unsigned int)> &func) override
{
return this->get_override("onFinishedRun")(func);
}
virtual bool
onModInstalled(const std::function<void(const QString &)> &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<MOBase::IProfile>
{
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<MOBase::IInstallationManager>
{
virtual QString extractFile(std::shared_ptr<const MOBase::FileTreeEntry> entry) override { return this->get_override("extractFile")(entry); }
virtual QStringList extractFiles(std::vector<std::shared_ptr<const MOBase::FileTreeEntry>> const& entries) override { return this->get_override("extractFiles")(entries); }
virtual MOBase::IPluginInstaller::EInstallResult installArchive(MOBase::GuessedValue<QString> &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<MOBase::IModInterface>
{
virtual QString name() const override { return this->get_override("name")(); }