Merge remote-tracking branch 'origin/master' into category_revamp

This commit is contained in:
Jeremy Rimpo
2021-03-25 10:28:50 -05:00
6 changed files with 57 additions and 9 deletions
+1 -1
View File
@@ -216,7 +216,7 @@ QString ProxyPython::description() const
VersionInfo ProxyPython::version() const
{
return VersionInfo(2, 1, 0, VersionInfo::RELEASE_FINAL);
return VersionInfo(2, 2, 0, VersionInfo::RELEASE_FINAL);
}
QList<PluginSetting> ProxyPython::settings() const
+4 -1
View File
@@ -9,6 +9,7 @@
#include <isavegame.h>
#include <isavegameinfowidget.h>
#include "shared_ptr_converter.h"
#include "ifiletree.h"
#include "pythonwrapperutilities.h"
@@ -108,7 +109,9 @@ ModDataChecker::CheckReturn ModDataCheckerWrapper::dataLooksValid(std::shared_pt
}
std::shared_ptr<MOBase::IFileTree> ModDataCheckerWrapper::fix(std::shared_ptr<MOBase::IFileTree> fileTree) const {
return basicWrapperFunctionImplementationWithDefault<std::shared_ptr<MOBase::IFileTree>>(this, [](auto&&... args) { return nullptr; }, "fix", fileTree);
return utils::clean_shared_ptr(
basicWrapperFunctionImplementationWithDefault<std::shared_ptr<MOBase::IFileTree>>(
this, [](auto&&... args) { return nullptr; }, "fix", fileTree));
}
/// end ModDataChecker Wrapper
+12 -3
View File
@@ -4,6 +4,7 @@
#include <QUrl>
#include <QWidget>
#include "shared_ptr_converter.h"
#include "pythonwrapperutilities.h"
#include "uibasewrappers.h"
@@ -76,7 +77,12 @@ BOOST_PP_EXPR_IF(include_requirements, \
return basicWrapperFunctionImplementationWithDefault<std::vector<std::shared_ptr<const MOBase::IPluginRequirement>>>( \
this, &class_name::requirements_Default, "requirements"); \
} \
std::vector<std::shared_ptr<const MOBase::IPluginRequirement>> class_name::requirements_Default() const { return IPlugin::requirements(); })
std::vector<std::shared_ptr<const MOBase::IPluginRequirement>> class_name::requirements_Default() const { return IPlugin::requirements(); } \
bool class_name::enabledByDefault() const \
{ \
return basicWrapperFunctionImplementationWithDefault<bool>(this, &class_name::enabledByDefault_Default, "enabledByDefault"); \
} \
bool class_name::enabledByDefault_Default() const { return IPlugin::enabledByDefault(); })
#define COMMON_I_PLUGIN_WRAPPER_DEFINITIONS(class_name) COMMON_I_PLUGIN_WRAPPER_DEFINITIONS_IMPL(class_name, 1)
@@ -330,10 +336,10 @@ IPluginInstaller::EInstallResult IPluginInstallerSimpleWrapper::install(
using return_type = std::variant<
IPluginInstaller::EInstallResult,
std::shared_ptr<IFileTree>,
std::tuple<IPluginInstaller::EInstallResult, std::shared_ptr<IFileTree>, QString, int>> ;
std::tuple<IPluginInstaller::EInstallResult, std::shared_ptr<IFileTree>, QString, int>>;
auto ret = basicWrapperFunctionImplementation<return_type>(this, "install", boost::ref(modName), tree, version, nexusID);
return std::visit([&](auto const& t) {
auto result = std::visit([&](auto const& t) {
using type = std::decay_t<decltype(t)>;
if constexpr (std::is_same_v<type, IPluginInstaller::EInstallResult>) {
return t;
@@ -349,6 +355,9 @@ IPluginInstaller::EInstallResult IPluginInstallerSimpleWrapper::install(
return std::get<0>(t);
}
}, ret);
tree = utils::clean_shared_ptr(tree);
return result;
}
/// end IPluginInstallerSimple Wrapper
+4 -2
View File
@@ -16,7 +16,7 @@
#include <boost/python.hpp>
#endif
// The wrapper for IPluginGame cannot override requirements() since it's final,
// The wrapper for IPluginGame cannot override requirements or enabledByDefault since they're final,
// so we need to be able to exclude the declarations.
#define COMMON_I_PLUGIN_WRAPPER_DECLARATIONS_IMPL(include_requirements) \
public: \
@@ -32,7 +32,9 @@ QString localizedName_Default() const; \
QString master_Default() const; \
BOOST_PP_EXPR_IF(include_requirements, \
virtual std::vector<std::shared_ptr<const MOBase::IPluginRequirement>> requirements() const override; \
std::vector<std::shared_ptr<const MOBase::IPluginRequirement>> requirements_Default() const;)
std::vector<std::shared_ptr<const MOBase::IPluginRequirement>> requirements_Default() const; \
virtual bool enabledByDefault() const override; \
bool enabledByDefault_Default() const;)
#define COMMON_I_PLUGIN_WRAPPER_DECLARATIONS COMMON_I_PLUGIN_WRAPPER_DECLARATIONS_IMPL(1)
+12 -2
View File
@@ -867,7 +867,7 @@ BOOST_PYTHON_MODULE(mobase)
.def("onModMoved", &MOBase::IModList::onModMoved, bpy::arg("callback"))
;
// Note: localizedName(), master() and requirements have to go in all the plugin wrappers declaration,
// Note: localizedName, master, requirements and enabledByDefault have to go in all the plugin wrappers declaration,
// since the default functions are specific to each wrapper, otherwise in turns into an
// infinite recursion mess.
bpy::class_<IPluginWrapper, boost::noncopyable>("IPlugin")
@@ -880,12 +880,14 @@ BOOST_PYTHON_MODULE(mobase)
.def("version", bpy::pure_virtual(&MOBase::IPlugin::version))
.def("requirements", &MOBase::IPlugin::requirements, &IPluginWrapper::requirements_Default)
.def("settings", bpy::pure_virtual(&MOBase::IPlugin::settings))
.def("enabledByDefault", &MOBase::IPlugin::enabledByDefault, &IPluginWrapper::enabledByDefault_Default)
;
bpy::class_<IPluginDiagnoseWrapper, bpy::bases<IPlugin>, boost::noncopyable>("IPluginDiagnose")
.def("localizedName", &MOBase::IPlugin::localizedName, &IPluginDiagnoseWrapper::localizedName_Default)
.def("master", &MOBase::IPlugin::master, &IPluginDiagnoseWrapper::master_Default)
.def("requirements", &MOBase::IPlugin::requirements, &IPluginDiagnoseWrapper::requirements_Default)
.def("enabledByDefault", &MOBase::IPlugin::enabledByDefault, &IPluginDiagnoseWrapper::enabledByDefault_Default)
.def("activeProblems", bpy::pure_virtual(&MOBase::IPluginDiagnose::activeProblems))
.def("shortDescription", bpy::pure_virtual(&MOBase::IPluginDiagnose::shortDescription), bpy::arg("key"))
@@ -913,6 +915,8 @@ BOOST_PYTHON_MODULE(mobase)
.def("localizedName", &MOBase::IPlugin::localizedName, &IPluginFileMapperWrapper::localizedName_Default)
.def("master", &MOBase::IPlugin::master, &IPluginFileMapperWrapper::master_Default)
.def("requirements", &MOBase::IPlugin::requirements, &IPluginFileMapperWrapper::requirements_Default)
.def("enabledByDefault", &MOBase::IPlugin::enabledByDefault, &IPluginFileMapperWrapper::enabledByDefault_Default)
.def("mappings", bpy::pure_virtual(&MOBase::IPluginFileMapper::mappings))
;
@@ -1045,6 +1049,7 @@ BOOST_PYTHON_MODULE(mobase)
.def("localizedName", &MOBase::IPlugin::localizedName, &IPluginInstallerSimpleWrapper::localizedName_Default)
.def("master", &MOBase::IPlugin::master, &IPluginInstallerSimpleWrapper::master_Default)
.def("requirements", &MOBase::IPlugin::requirements, &IPluginInstallerSimpleWrapper::requirements_Default)
.def("enabledByDefault", &MOBase::IPlugin::enabledByDefault, &IPluginInstallerSimpleWrapper::enabledByDefault_Default)
// Note: Keeping the variant here even if we always return a tuple to be consistent with the wrapper and
// have proper stubs generation.
@@ -1063,6 +1068,7 @@ BOOST_PYTHON_MODULE(mobase)
.def("localizedName", &MOBase::IPlugin::localizedName, &IPluginInstallerCustomWrapper::localizedName_Default)
.def("master", &MOBase::IPlugin::master, &IPluginInstallerCustomWrapper::master_Default)
.def("requirements", &MOBase::IPlugin::requirements, &IPluginInstallerCustomWrapper::requirements_Default)
.def("enabledByDefault", &MOBase::IPlugin::enabledByDefault, &IPluginInstallerCustomWrapper::enabledByDefault_Default)
// Needs to add both otherwize boost does not understand:
.def("isArchiveSupported", &IPluginInstaller::isArchiveSupported, bpy::arg("tree"))
@@ -1077,6 +1083,7 @@ BOOST_PYTHON_MODULE(mobase)
.def("localizedName", &MOBase::IPlugin::localizedName, &IPluginModPageWrapper::localizedName_Default)
.def("master", &MOBase::IPlugin::master, &IPluginModPageWrapper::master_Default)
.def("requirements", &MOBase::IPlugin::requirements, &IPluginModPageWrapper::requirements_Default)
.def("enabledByDefault", &MOBase::IPlugin::enabledByDefault, &IPluginModPageWrapper::enabledByDefault_Default)
.def("displayName", bpy::pure_virtual(&IPluginModPage::displayName))
.def("icon", bpy::pure_virtual(&IPluginModPage::icon))
@@ -1091,6 +1098,7 @@ BOOST_PYTHON_MODULE(mobase)
.def("localizedName", &MOBase::IPlugin::localizedName, &IPluginPreviewWrapper::localizedName_Default)
.def("master", &MOBase::IPlugin::master, &IPluginPreviewWrapper::master_Default)
.def("requirements", &MOBase::IPlugin::requirements, &IPluginPreviewWrapper::requirements_Default)
.def("enabledByDefault", &MOBase::IPlugin::enabledByDefault, &IPluginPreviewWrapper::enabledByDefault_Default)
.def("supportedExtensions", bpy::pure_virtual(&IPluginPreview::supportedExtensions))
.def("genFilePreview", bpy::pure_virtual(&IPluginPreview::genFilePreview), bpy::return_value_policy<bpy::return_by_value>(),
@@ -1101,6 +1109,7 @@ BOOST_PYTHON_MODULE(mobase)
.def("localizedName", &MOBase::IPlugin::localizedName, &IPluginToolWrapper::localizedName_Default)
.def("master", &MOBase::IPlugin::master, &IPluginToolWrapper::master_Default)
.def("requirements", &MOBase::IPlugin::requirements, &IPluginToolWrapper::requirements_Default)
.def("enabledByDefault", &MOBase::IPlugin::enabledByDefault, &IPluginToolWrapper::enabledByDefault_Default)
.def("displayName", bpy::pure_virtual(&IPluginTool::displayName))
.def("tooltip", bpy::pure_virtual(&IPluginTool::tooltip))
@@ -1319,13 +1328,14 @@ bool PythonRunner::initPython(const QString &pythonPath)
bpy::object mainNamespace = mainModule.attr("__dict__");
mainNamespace["sys"] = bpy::import("sys");
mainNamespace["moprivate"] = bpy::import("moprivate");
mainNamespace["mobase"] = bpy::import("mobase");
bpy::import("site");
bpy::exec("sys.stdout = moprivate.PrintWrapper()\n"
"sys.stderr = moprivate.ErrWrapper.instance()\n"
"sys.excepthook = lambda x, y, z: sys.__excepthook__(x, y, z)\n",
mainNamespace);
mainNamespace["mobase"] = bpy::import("mobase");
configure_python_logging(mainNamespace["mobase"]);
PyEval_SaveThread();
+24
View File
@@ -96,6 +96,30 @@ namespace utils {
}
};
// release the bpy::object associated with the deleter of the given shared_ptr,
// if the given shared_ptr has a Boost.Python deleter
//
// this should only be used when returning from Python objects that have been created
// on the C++ side, e.g. if IFileTree.createOrphanTree() from Python and then return
// the tree
//
// for reason yet to be known, Boost.Python had a custom deleter in this case that tries
// to delete the bpy::object and fails, so we have to release the object manually
//
template <class SharedPtr>
SharedPtr clean_shared_ptr(SharedPtr&& ptr) {
if (auto* d = get_deleter<boost::python::converter::shared_ptr_deleter>(ptr); d != nullptr) {
// we cannot do a proper reset() here, even with the GIL lock, for unknown reason,
// so we only release
//
// this might create lost references to Python object but this should not happen
// too often so hopefully it's not a big issue
//
d->owner.release();
}
return ptr;
}
}
#endif