diff --git a/doc/python/pages/changelog.rst b/doc/python/pages/changelog.rst index 3f44441..222f72c 100644 --- a/doc/python/pages/changelog.rst +++ b/doc/python/pages/changelog.rst @@ -125,8 +125,9 @@ Changelog - Exposed the :ref:`text` library - Exposed the minimal interface of :ref:`utility.ConfigurationGroup` and :ref:`utility.Configuration` -- Exposed :ref:`pluginmanager.AbstractManager.set_preferred_plugins()` and - the base :ref:`pluginmanager.AbstractPlugin` class +- Exposed :ref:`pluginmanager.AbstractManager.set_preferred_plugins()`, the + base :ref:`pluginmanager.AbstractPlugin` class and + :ref:`pluginmanager.PluginMetadata` - Fixed issues with an in-source build (see :gh:`mosra/magnum-bindings#13`) - All CMake build options are now prefixed with ``MAGNUM_``. For backwards compatibility, unless ``MAGNUM_BUILD_DEPRECATED`` is disabled and unless a diff --git a/src/python/corrade/pluginmanager.cpp b/src/python/corrade/pluginmanager.cpp index 948a8d4..fbc97dd 100644 --- a/src/python/corrade/pluginmanager.cpp +++ b/src/python/corrade/pluginmanager.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include "Corrade/PythonBindings.h" @@ -57,6 +58,12 @@ void pluginmanager(py::module_& m) { .value("USED", PluginManager::LoadState::Used); corrade::enumOperators(loadState); + py::class_{m, "PluginMetadata", "Plugin metadata"} + .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"); + PyNonDestructibleClass manager{m, "AbstractManager", "Base for plugin managers"}; manager.attr("VERSION") = PluginManager::AbstractManager::Version; manager @@ -99,7 +106,9 @@ void pluginmanager(py::module_& m) { out.push_back(i); return out; }, "List of all available alias names") - /** @todo metadata() (figure out the ownership) */ + .def("metadata", [](PluginManager::AbstractManager& self, const std::string& plugin) { + return self.metadata(plugin); + }, "Plugin metadata", py::arg("plugin"), py::return_value_policy::reference_internal) /** @todo drop std::string in favor of our own string caster */ .def("load_state", [](PluginManager::AbstractManager& self, const std::string& plugin) { return self.loadState(plugin); @@ -133,7 +142,8 @@ void pluginmanager(py::module_& m) { .def_property_readonly("plugin", [](PluginManager::AbstractPlugin& self) { /** @todo drop std::string in favor of our own string caster */ return std::string{self.plugin()}; - }, "Plugin identifier string"); + }, "Plugin identifier string") + .def_property_readonly("metadata", &PluginManager::AbstractPlugin::metadata, "Plugin metadata", 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 801ef55..1223d4e 100644 --- a/src/python/magnum/test/test_trade.py +++ b/src/python/magnum/test/test_trade.py @@ -1042,6 +1042,45 @@ class Importer(unittest.TestCase): with self.assertRaises(KeyError): manager.set_preferred_plugins('ApngImporter', []) + def test_metadata(self): + manager = trade.ImporterManager() + manager.set_preferred_plugins('PngImporter', ['StbImageImporter']) + manager_refcount = sys.getrefcount(manager) + + metadata = manager.metadata('PngImporter') + self.assertEqual(sys.getrefcount(manager), manager_refcount + 1) + self.assertEqual(metadata.name, 'StbImageImporter') + self.assertEqual(metadata.provides, ['BmpImporter', 'GifImporter', 'HdrImporter', 'JpegImporter', 'PgmImporter', 'PicImporter', 'PngImporter', 'PpmImporter', 'PsdImporter', 'TgaImporter']) + + del metadata + self.assertEqual(sys.getrefcount(manager), manager_refcount) + + metadata = manager.metadata('GltfImporter') + self.assertEqual(sys.getrefcount(manager), manager_refcount + 1) + self.assertEqual(metadata.depends, ['AnyImageImporter']) + + importer = manager.load_and_instantiate('GltfImporter') + importer_refcount = sys.getrefcount(importer) + self.assertEqual(sys.getrefcount(manager), manager_refcount + 2) + + metadata = manager.metadata('AnyImageImporter') + # Replacing the previous metadata instance so it stays the same + self.assertEqual(sys.getrefcount(manager), manager_refcount + 2) + self.assertEqual(metadata.used_by, ['GltfImporter']) + + # Retrieving metadata from the plugin instance should be the same + # instance + metadata_from_plugin = importer.metadata + self.assertEqual(sys.getrefcount(importer), importer_refcount + 1) + self.assertEqual(metadata_from_plugin.depends, ['AnyImageImporter']) + + del metadata_from_plugin + self.assertEqual(sys.getrefcount(importer), importer_refcount) + + del importer + del metadata + self.assertEqual(sys.getrefcount(manager), manager_refcount) + def test_no_file_opened(self): importer = trade.ImporterManager().load_and_instantiate('StbImageImporter') self.assertFalse(importer.is_opened)