mirror of
https://github.com/ModOrganizer2/modorganizer-plugin_python.git
synced 2026-07-27 14:03:33 -07:00
Merge remote-tracking branch 'origin/master' into category_revamp
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user