From 58a163adf7bb9b41b49bf1e014aae741cf9f47c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 8 Mar 2023 14:17:27 +0100 Subject: [PATCH] python: expose plugin configuration as well. In both PluginMetadata and AbstractPlugin itself. This makes the pluginmanager module depend on the utility module (which currently contains just the Configuration bindings). --- src/python/corrade/corrade.cpp | 8 ++++--- src/python/corrade/pluginmanager.cpp | 15 ++++++++++-- src/python/magnum/test/test_trade.py | 34 ++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/python/corrade/corrade.cpp b/src/python/corrade/corrade.cpp index c6bacfb..6d10125 100644 --- a/src/python/corrade/corrade.cpp +++ b/src/python/corrade/corrade.cpp @@ -128,12 +128,14 @@ PYBIND11_MODULE(_corrade, m) { py::module_ containers = m.def_submodule("containers"); corrade::containers(containers); + py::module_ utility = m.def_submodule("utility"); + corrade::utility(utility); + + /* PluginManager needs Utility::ConfigurationGroup, needs to be defined + after */ #ifdef Corrade_PluginManager_FOUND py::module_ pluginmanager = m.def_submodule("pluginmanager"); corrade::pluginmanager(pluginmanager); #endif - - py::module_ utility = m.def_submodule("utility"); - corrade::utility(utility); #endif } diff --git a/src/python/corrade/pluginmanager.cpp b/src/python/corrade/pluginmanager.cpp index fbc97dd..bf67c25 100644 --- a/src/python/corrade/pluginmanager.cpp +++ b/src/python/corrade/pluginmanager.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include "Corrade/PythonBindings.h" @@ -43,6 +44,13 @@ namespace corrade { void pluginmanager(py::module_& m) { m.doc() = "Plugin management"; + #ifndef CORRADE_BUILD_STATIC + /* Need ConfigurationGroup from there. These are a part of the same module + in the static build, no need to import (also can't import because there + it's _corrade.*) */ + py::module_::import("corrade.utility"); + #endif + py::enum_ loadState{m, "LoadState", "Plugin load state"}; loadState .value("NOT_FOUND", PluginManager::LoadState::NotFound) @@ -62,7 +70,9 @@ void pluginmanager(py::module_& m) { .def_property_readonly("name", &PluginManager::PluginMetadata::name, "Plugin name") .def_property_readonly("depends", &PluginManager::PluginMetadata::depends, "Plugins on which this plugin depends") .def_property_readonly("used_by", &PluginManager::PluginMetadata::usedBy, "Plugins which depend on this plugin") - .def_property_readonly("provides", &PluginManager::PluginMetadata::provides, "Plugins which are provided by this plugin"); + .def_property_readonly("provides", &PluginManager::PluginMetadata::provides, "Plugins which are provided by this plugin") + /** @todo data? no plugin uses this at the moment */ + .def_property_readonly("configuration", static_cast(&PluginManager::PluginMetadata::configuration), "Initial plugin-specific configuration", py::return_value_policy::reference_internal); PyNonDestructibleClass manager{m, "AbstractManager", "Base for plugin managers"}; manager.attr("VERSION") = PluginManager::AbstractManager::Version; @@ -143,7 +153,8 @@ void pluginmanager(py::module_& m) { /** @todo drop std::string in favor of our own string caster */ return std::string{self.plugin()}; }, "Plugin identifier string") - .def_property_readonly("metadata", &PluginManager::AbstractPlugin::metadata, "Plugin metadata", py::return_value_policy::reference_internal); + .def_property_readonly("metadata", &PluginManager::AbstractPlugin::metadata, "Plugin metadata", py::return_value_policy::reference_internal) + .def_property_readonly("configuration", static_cast(&PluginManager::AbstractPlugin::configuration), "Plugin-specific configuration", py::return_value_policy::reference_internal); } } diff --git a/src/python/magnum/test/test_trade.py b/src/python/magnum/test/test_trade.py index 1223d4e..e78cfbf 100644 --- a/src/python/magnum/test/test_trade.py +++ b/src/python/magnum/test/test_trade.py @@ -1081,6 +1081,40 @@ class Importer(unittest.TestCase): del metadata self.assertEqual(sys.getrefcount(manager), manager_refcount) + def test_configuration(self): + manager = trade.ImporterManager() + + metadata = manager.metadata('StbImageImporter') + metadata_refcount = sys.getrefcount(metadata) + + # Setting the value from initial configuration should make the plugin + # inherit that + initial_configuration = metadata.configuration + self.assertEqual(sys.getrefcount(metadata), metadata_refcount + 1) + self.assertEqual(initial_configuration['forceChannelCount'], '0') + initial_configuration['forceChannelCount'] = '7' + + del initial_configuration + self.assertEqual(sys.getrefcount(metadata), metadata_refcount) + + importer = manager.load_and_instantiate('StbImageImporter') + importer_refcount = sys.getrefcount(importer) + + configuration = importer.configuration + self.assertEqual(sys.getrefcount(importer), importer_refcount + 1) + self.assertEqual(configuration['forceChannelCount'], '7') + + configuration['forceChannelCount'] = '2' + + del configuration + self.assertEqual(sys.getrefcount(importer), importer_refcount) + + # Verify the config change is actually used and not being done on some + # copy that gets thrown away + importer.open_file(os.path.join(os.path.dirname(__file__), 'rgb.png')) + image = importer.image2d(0) + self.assertEqual(image.format, PixelFormat.RG8_UNORM) # not RGB8 + def test_no_file_opened(self): importer = trade.ImporterManager().load_and_instantiate('StbImageImporter') self.assertFalse(importer.is_opened)