mirror of
https://github.com/ModOrganizer2/modorganizer-plugin_python.git
synced 2026-07-27 14:03:33 -07:00
Fix issue with unloading single .py file and fix tests.
This commit is contained in:
@@ -246,12 +246,13 @@ namespace mo2::python {
|
||||
{
|
||||
py::gil_scoped_acquire lock;
|
||||
|
||||
// At this point, the identifier is the full path to the module.
|
||||
// at this point, the identifier is the full path to the module.
|
||||
QDir folder(modulePath);
|
||||
|
||||
// we want to "unload" (remove from sys.modules) modules that come
|
||||
// from this plugin (whose __path__ points under this module,
|
||||
// including the module of the plugin itself)
|
||||
//
|
||||
py::object sys = py::module_::import("sys");
|
||||
py::dict modules = sys.attr("modules");
|
||||
py::list keys = modules.attr("keys")();
|
||||
@@ -269,6 +270,14 @@ namespace mo2::python {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for simple Python file - not really used anymore, but actually used in
|
||||
// testing - we need to remove using the module name
|
||||
//
|
||||
py::str pyModuleName(moduleName);
|
||||
if (modules.contains(pyModuleName)) {
|
||||
PyDict_DelItem(modules.ptr(), pyModuleName.ptr());
|
||||
}
|
||||
}
|
||||
|
||||
bool PythonRunner::isInitialized() const
|
||||
|
||||
@@ -16,19 +16,20 @@ using ::testing::ElementsAre;
|
||||
|
||||
TEST(IPluginDiagnose, Simple)
|
||||
{
|
||||
const auto plugins_folder = QString(std::getenv("PLUGIN_DIR"));
|
||||
const auto plugins_folder = std::filesystem::path(std::getenv("PLUGIN_DIR"));
|
||||
|
||||
auto runner = mo2::python::createPythonRunner();
|
||||
runner->initialize();
|
||||
|
||||
// load objects
|
||||
const auto objects = runner->load(plugins_folder + "/dummy-diagnose.py");
|
||||
EXPECT_EQ(objects.size(), 3);
|
||||
const auto objects =
|
||||
runner->load("dummy_diagnose", plugins_folder / "dummy-diagnose.py");
|
||||
ASSERT_EQ(objects.size(), 2);
|
||||
|
||||
// load the first IPluginDiagnose
|
||||
{
|
||||
IPluginDiagnose* plugin = qobject_cast<IPluginDiagnose*>(objects[0]);
|
||||
EXPECT_NE(plugin, nullptr);
|
||||
IPluginDiagnose* plugin = qobject_cast<IPluginDiagnose*>(objects[0][0]);
|
||||
ASSERT_NE(plugin, nullptr);
|
||||
|
||||
ASSERT_THAT(plugin->activeProblems(), ElementsAre(1, 2));
|
||||
EXPECT_EQ(plugin->shortDescription(1), "short-1");
|
||||
@@ -41,8 +42,8 @@ TEST(IPluginDiagnose, Simple)
|
||||
|
||||
// load the second one (this is cast before IPluginGame so should be before)
|
||||
{
|
||||
IPluginDiagnose* plugin = qobject_cast<IPluginDiagnose*>(objects[1]);
|
||||
EXPECT_NE(plugin, nullptr);
|
||||
IPluginDiagnose* plugin = qobject_cast<IPluginDiagnose*>(objects[1][0]);
|
||||
ASSERT_NE(plugin, nullptr);
|
||||
|
||||
ASSERT_THAT(plugin->activeProblems(), ElementsAre(5, 7));
|
||||
EXPECT_EQ(plugin->shortDescription(5), "short-5");
|
||||
@@ -55,7 +56,7 @@ TEST(IPluginDiagnose, Simple)
|
||||
|
||||
// load the game plugin
|
||||
{
|
||||
IPluginGame* plugin = qobject_cast<IPluginGame*>(objects[2]);
|
||||
EXPECT_NE(plugin, nullptr);
|
||||
IPluginGame* plugin = qobject_cast<IPluginGame*>(objects[1][1]);
|
||||
ASSERT_NE(plugin, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,22 +14,24 @@ using namespace MOBase;
|
||||
|
||||
TEST(IPluginFileMapper, Simple)
|
||||
{
|
||||
const auto plugins_folder = QString(std::getenv("PLUGIN_DIR"));
|
||||
const auto plugins_folder = std::filesystem::path(std::getenv("PLUGIN_DIR"));
|
||||
|
||||
auto runner = mo2::python::createPythonRunner();
|
||||
runner->initialize();
|
||||
|
||||
// load objects
|
||||
const auto objects = runner->load(plugins_folder + "/dummy-filemapper.py");
|
||||
EXPECT_EQ(objects.size(), 3);
|
||||
const auto objects =
|
||||
runner->load("dummy_filemapper", plugins_folder / "dummy-filemapper.py");
|
||||
EXPECT_EQ(objects.size(), 2);
|
||||
|
||||
// load the first IPluginFileMapper
|
||||
{
|
||||
IPluginFileMapper* plugin = qobject_cast<IPluginFileMapper*>(objects[0]);
|
||||
EXPECT_NE(plugin, nullptr);
|
||||
ASSERT_EQ(objects[0].size(), 1);
|
||||
IPluginFileMapper* plugin = qobject_cast<IPluginFileMapper*>(objects[0][0]);
|
||||
ASSERT_NE(plugin, nullptr);
|
||||
|
||||
const auto m = plugin->mappings();
|
||||
EXPECT_EQ(m.size(), 2);
|
||||
ASSERT_EQ(m.size(), 2);
|
||||
|
||||
EXPECT_EQ(m[0].source, "the source");
|
||||
EXPECT_EQ(m[0].destination, "the destination");
|
||||
@@ -44,11 +46,12 @@ TEST(IPluginFileMapper, Simple)
|
||||
|
||||
// load the second one (this is cast before IPluginGame so should be before)
|
||||
{
|
||||
IPluginFileMapper* plugin = qobject_cast<IPluginFileMapper*>(objects[1]);
|
||||
EXPECT_NE(plugin, nullptr);
|
||||
ASSERT_EQ(objects[1].size(), 2);
|
||||
IPluginFileMapper* plugin = qobject_cast<IPluginFileMapper*>(objects[1][0]);
|
||||
ASSERT_NE(plugin, nullptr);
|
||||
|
||||
const auto m = plugin->mappings();
|
||||
EXPECT_EQ(m.size(), 1);
|
||||
ASSERT_EQ(m.size(), 1);
|
||||
|
||||
EXPECT_EQ(m[0].source, "the source");
|
||||
EXPECT_EQ(m[0].destination, "the destination");
|
||||
@@ -58,7 +61,7 @@ TEST(IPluginFileMapper, Simple)
|
||||
|
||||
// load the game plugin
|
||||
{
|
||||
IPluginGame* plugin = qobject_cast<IPluginGame*>(objects[2]);
|
||||
EXPECT_NE(plugin, nullptr);
|
||||
IPluginGame* plugin = qobject_cast<IPluginGame*>(objects[1][1]);
|
||||
ASSERT_NE(plugin, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,16 +13,16 @@ using namespace MOBase;
|
||||
|
||||
TEST(IPluginGame, Simple)
|
||||
{
|
||||
const auto plugins_folder = QString(std::getenv("PLUGIN_DIR"));
|
||||
const auto plugins_folder = std::filesystem::path(std::getenv("PLUGIN_DIR"));
|
||||
|
||||
auto runner = mo2::python::createPythonRunner();
|
||||
runner->initialize();
|
||||
|
||||
// load objects
|
||||
const auto objects = runner->load(plugins_folder + "/dummy-game.py");
|
||||
const auto objects = runner->load("dummy_game", plugins_folder / "dummy-game.py");
|
||||
EXPECT_EQ(objects.size(), 1);
|
||||
|
||||
// load the IPlugin
|
||||
IPluginGame* plugin = qobject_cast<IPluginGame*>(objects[0]);
|
||||
IPluginGame* plugin = qobject_cast<IPluginGame*>(objects[0][0]);
|
||||
EXPECT_NE(plugin, nullptr);
|
||||
}
|
||||
|
||||
@@ -14,17 +14,19 @@ using namespace MOBase;
|
||||
|
||||
TEST(IPluginInstaller, Simple)
|
||||
{
|
||||
const auto plugins_folder = QString(std::getenv("PLUGIN_DIR"));
|
||||
const auto plugins_folder = std::filesystem::path(std::getenv("PLUGIN_DIR"));
|
||||
|
||||
auto runner = mo2::python::createPythonRunner();
|
||||
runner->initialize();
|
||||
|
||||
// load objects
|
||||
const auto objects = runner->load(plugins_folder + "/dummy-installer.py");
|
||||
const auto objects =
|
||||
runner->load("dummy_installer", plugins_folder / "dummy-installer.py");
|
||||
EXPECT_EQ(objects.size(), 1);
|
||||
|
||||
// load the IPlugin
|
||||
IPluginInstallerSimple* plugin = qobject_cast<IPluginInstallerSimple*>(objects[0]);
|
||||
IPluginInstallerSimple* plugin =
|
||||
qobject_cast<IPluginInstallerSimple*>(objects[0][0]);
|
||||
EXPECT_NE(plugin, nullptr);
|
||||
|
||||
// basic tests
|
||||
|
||||
@@ -12,17 +12,18 @@ using namespace MOBase;
|
||||
|
||||
TEST(IPlugin, Basic)
|
||||
{
|
||||
const auto plugins_folder = QString(std::getenv("PLUGIN_DIR"));
|
||||
const auto plugins_folder = std::filesystem::path(std::getenv("PLUGIN_DIR"));
|
||||
|
||||
auto runner = mo2::python::createPythonRunner();
|
||||
runner->initialize();
|
||||
|
||||
// load objects
|
||||
const auto objects = runner->load(plugins_folder + "/dummy-iplugin.py");
|
||||
const auto objects =
|
||||
runner->load("dummy_iplugin", plugins_folder / "dummy-iplugin.py");
|
||||
EXPECT_EQ(objects.size(), 1);
|
||||
|
||||
// load the IPlugin
|
||||
const IPlugin* plugin = qobject_cast<IPlugin*>(objects[0]);
|
||||
const IPlugin* plugin = qobject_cast<IPlugin*>(objects[0][0]);
|
||||
EXPECT_NE(plugin, nullptr);
|
||||
|
||||
EXPECT_EQ(plugin->author(), "The Author");
|
||||
|
||||
@@ -7,38 +7,42 @@
|
||||
|
||||
TEST(Lifetime, Plugins)
|
||||
{
|
||||
const auto plugins_folder = QString(std::getenv("PLUGIN_DIR"));
|
||||
const auto plugins_folder = std::filesystem::path(std::getenv("PLUGIN_DIR"));
|
||||
|
||||
auto runner = mo2::python::createPythonRunner();
|
||||
runner->initialize();
|
||||
|
||||
{
|
||||
const auto objects = runner->load(plugins_folder + "/dummy-iplugin.py");
|
||||
const auto objects =
|
||||
runner->load("dummy_iplugin", plugins_folder / "dummy-iplugin.py");
|
||||
|
||||
// we found one plugin
|
||||
EXPECT_EQ(objects.size(), 1);
|
||||
ASSERT_EQ(objects.size(), 1);
|
||||
|
||||
// check that deleting the object actually destroys it
|
||||
bool destroyed = false;
|
||||
QObject::connect(objects[0], &QObject::destroyed, [&destroyed]() {
|
||||
QObject::connect(objects[0][0], &QObject::destroyed, [&destroyed]() {
|
||||
destroyed = true;
|
||||
});
|
||||
delete objects[0];
|
||||
delete objects[0][0];
|
||||
EXPECT_EQ(destroyed, true);
|
||||
|
||||
runner->unload("dummy_iplugin", plugins_folder / "dummy-iplugin.py");
|
||||
}
|
||||
|
||||
// same things but with a parent
|
||||
{
|
||||
QObject* dummy_parent = new QObject();
|
||||
const auto objects = runner->load(plugins_folder + "/dummy-iplugin.py");
|
||||
const auto objects =
|
||||
runner->load("dummy_iplugin", plugins_folder / "dummy-iplugin.py");
|
||||
|
||||
// we found one plugin
|
||||
EXPECT_EQ(objects.size(), 1);
|
||||
objects[0]->setParent(dummy_parent);
|
||||
ASSERT_EQ(objects.size(), 1);
|
||||
objects[0][0]->setParent(dummy_parent);
|
||||
|
||||
// check that deleting the object actually destroys it
|
||||
bool destroyed = false;
|
||||
QObject::connect(objects[0], &QObject::destroyed, [&destroyed]() {
|
||||
QObject::connect(objects[0][0], &QObject::destroyed, [&destroyed]() {
|
||||
destroyed = true;
|
||||
});
|
||||
delete dummy_parent;
|
||||
|
||||
Reference in New Issue
Block a user