mirror of
https://github.com/ModOrganizer2/modorganizer-plugin_python.git
synced 2026-07-27 14:03:33 -07:00
Properly load plugins.
This commit is contained in:
+11
-10
@@ -120,17 +120,18 @@ QList<QList<QObject*>> ProxyPython::load(const PluginExtension& extension)
|
||||
return {};
|
||||
}
|
||||
|
||||
// currently, only handle __init__.py directly in the folder
|
||||
const auto pyIniFile = extension.directory() / "__init__.py";
|
||||
if (!exists(pyIniFile)) {
|
||||
if (extension.autodetect()) {
|
||||
log::error("{}: automatic plugin detection is not supported for Python plugins",
|
||||
extension.metadata().name());
|
||||
return {};
|
||||
}
|
||||
|
||||
m_ExtensionModules[&extension] = {pyIniFile};
|
||||
m_ExtensionModules[&extension] = {};
|
||||
|
||||
QList<QList<QObject*>> plugins;
|
||||
for (auto&& pythonModule : m_ExtensionModules[&extension]) {
|
||||
plugins.append(m_Runner->load(pythonModule));
|
||||
for (auto& [moduleName, modulePath] : extension.plugins()) {
|
||||
m_ExtensionModules[&extension].push_back({moduleName, modulePath});
|
||||
plugins.append(m_Runner->load(moduleName, modulePath));
|
||||
}
|
||||
|
||||
return plugins;
|
||||
@@ -143,8 +144,8 @@ void ProxyPython::unload(const PluginExtension& extension)
|
||||
}
|
||||
|
||||
if (auto it = m_ExtensionModules.find(&extension); it != m_ExtensionModules.end()) {
|
||||
for (auto&& pythonModule : it->second) {
|
||||
m_Runner->unload(pythonModule);
|
||||
for (auto& [moduleName, modulePath] : it->second) {
|
||||
m_Runner->unload(moduleName, modulePath);
|
||||
}
|
||||
m_ExtensionModules.erase(it);
|
||||
}
|
||||
@@ -154,8 +155,8 @@ void ProxyPython::unloadAll()
|
||||
{
|
||||
if (m_Runner) {
|
||||
for (auto& [ext, modules] : m_ExtensionModules) {
|
||||
for (auto& pythonModule : modules) {
|
||||
m_Runner->unload(pythonModule);
|
||||
for (auto& [moduleName, modulePath] : modules) {
|
||||
m_Runner->unload(moduleName, modulePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ private:
|
||||
HMODULE m_RunnerLib;
|
||||
std::unique_ptr<mo2::python::IPythonRunner> m_Runner;
|
||||
std::unordered_map<const MOBase::PluginExtension*,
|
||||
std::vector<std::filesystem::path>>
|
||||
std::vector<std::pair<std::string, std::filesystem::path>>>
|
||||
m_ExtensionModules;
|
||||
};
|
||||
|
||||
|
||||
+15
-16
@@ -36,8 +36,10 @@ namespace mo2::python {
|
||||
PythonRunner() = default;
|
||||
~PythonRunner() = default;
|
||||
|
||||
QList<QList<QObject*>> load(std::filesystem::path const& pythonModule) override;
|
||||
void unload(std::filesystem::path const& pythonModule) override;
|
||||
QList<QList<QObject*>> load(std::string_view moduleName,
|
||||
std::filesystem::path const& modulePath) override;
|
||||
void unload(std::string_view moduleName,
|
||||
std::filesystem::path const& modulePath) override;
|
||||
|
||||
bool initialize(std::vector<std::filesystem::path> const& pythonPaths) override;
|
||||
void addDllSearchPath(std::filesystem::path const& dllPath) override;
|
||||
@@ -150,7 +152,8 @@ namespace mo2::python {
|
||||
py::module_::import("os").attr("add_dll_directory")(absolute(dllPath));
|
||||
}
|
||||
|
||||
QList<QList<QObject*>> PythonRunner::load(const std::filesystem::path& pythonModule)
|
||||
QList<QList<QObject*>> PythonRunner::load(std::string_view name,
|
||||
const std::filesystem::path& pythonModule)
|
||||
{
|
||||
py::gil_scoped_acquire lock;
|
||||
|
||||
@@ -160,24 +163,19 @@ namespace mo2::python {
|
||||
auto sys = py::module_::import("sys");
|
||||
auto importlib_util = py::module_::import("importlib.util");
|
||||
|
||||
// check the file type
|
||||
const auto moduleName =
|
||||
pythonModule.filename() == "__init__.py"
|
||||
? pythonModule.parent_path().filename().u8string()
|
||||
: pythonModule.filename().u8string();
|
||||
|
||||
// check if the module is already loaded
|
||||
py::dict modules = sys.attr("modules");
|
||||
py::module_ pymodule;
|
||||
if (modules.contains(moduleName)) {
|
||||
pymodule = modules[py::str(moduleName)];
|
||||
if (modules.contains(name)) {
|
||||
pymodule = modules[py::str(name)];
|
||||
pymodule.reload();
|
||||
}
|
||||
else {
|
||||
// load the module
|
||||
auto spec = importlib_util.attr("find_spec")(moduleName, pythonModule);
|
||||
pymodule = importlib_util.attr("module_from_spec")(spec);
|
||||
sys.attr("modules")[py::str(moduleName)] = pymodule;
|
||||
auto spec =
|
||||
importlib_util.attr("spec_from_file_location")(name, pythonModule);
|
||||
pymodule = importlib_util.attr("module_from_spec")(spec);
|
||||
sys.attr("modules")[py::str(name)] = pymodule;
|
||||
spec.attr("loader").attr("exec_module")(pymodule);
|
||||
}
|
||||
|
||||
@@ -243,12 +241,13 @@ namespace mo2::python {
|
||||
}
|
||||
}
|
||||
|
||||
void PythonRunner::unload(const std::filesystem::path& pythonModule)
|
||||
void PythonRunner::unload(std::string_view moduleName,
|
||||
std::filesystem::path const& modulePath)
|
||||
{
|
||||
py::gil_scoped_acquire lock;
|
||||
|
||||
// At this point, the identifier is the full path to the module.
|
||||
QDir folder(pythonModule);
|
||||
QDir folder(modulePath);
|
||||
|
||||
// we want to "unload" (remove from sys.modules) modules that come
|
||||
// from this plugin (whose __path__ points under this module,
|
||||
|
||||
@@ -24,8 +24,9 @@ namespace mo2::python {
|
||||
class IPythonRunner {
|
||||
public:
|
||||
virtual QList<QList<QObject*>>
|
||||
load(std::filesystem::path const& pythonModule) = 0;
|
||||
virtual void unload(std::filesystem::path const& pythonModule) = 0;
|
||||
load(std::string_view moduleName, std::filesystem::path const& modulePath) = 0;
|
||||
virtual void unload(std::string_view moduleName,
|
||||
std::filesystem::path const& modulePath) = 0;
|
||||
|
||||
// initialize Python
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user