From 9faed0651ef3fb39753c00c35df0b78ce1494179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 8 Sep 2019 18:11:53 +0200 Subject: [PATCH] python: expose basics of plugin manager. Just the minimum needed to get Trade::AbstractImporter running. --- doc/python/conf.py | 3 +- src/Corrade/Python.h | 11 ++++ src/Magnum/Python.h | 11 ---- src/python/corrade/CMakeLists.txt | 28 +++++++- src/python/corrade/bootstrap.h | 1 + src/python/corrade/corrade.cpp | 5 ++ src/python/corrade/pluginmanager.cpp | 77 ++++++++++++++++++++++ src/python/corrade/staticconfigure.h.cmake | 29 ++++++++ src/python/magnum/shaders.cpp | 2 +- src/python/setup.py.cmake | 1 + 10 files changed, 154 insertions(+), 14 deletions(-) create mode 100644 src/python/corrade/pluginmanager.cpp create mode 100644 src/python/corrade/staticconfigure.h.cmake diff --git a/doc/python/conf.py b/doc/python/conf.py index 69da6e0..1fb217e 100644 --- a/doc/python/conf.py +++ b/doc/python/conf.py @@ -6,6 +6,7 @@ sys.path = [os.path.join(os.path.dirname(__file__), '../../build/src/python/')] import corrade import corrade.containers +import corrade.pluginmanager import magnum import magnum.gl @@ -22,7 +23,7 @@ import magnum.trade # So the doc see everything # TODO: use just +=, m.css should reorder this on its own -corrade.__all__ = ['containers', 'BUILD_STATIC', 'BUILD_MULTITHREADED', 'TARGET_UNIX', 'TARGET_APPLE', 'TARGET_IOS', 'TARGET_IOS_SIMULATOR', 'TARGET_WINDOWS', 'TARGET_WINDOWS_RT', 'TARGET_EMSCRIPTEN', 'TARGET_ANDROID'] +corrade.__all__ = ['containers', 'pluginmanager', 'BUILD_STATIC', 'BUILD_MULTITHREADED', 'TARGET_UNIX', 'TARGET_APPLE', 'TARGET_IOS', 'TARGET_IOS_SIMULATOR', 'TARGET_WINDOWS', 'TARGET_WINDOWS_RT', 'TARGET_EMSCRIPTEN', 'TARGET_ANDROID'] magnum.__all__ = ['math', 'gl', 'meshtools', 'platform', 'primitives', 'shaders', 'scenegraph', 'trade', 'BUILD_STATIC', 'TARGET_GL', 'TARGET_GLES', 'TARGET_GLES2', 'TARGET_WEBGL', 'TARGET_VK'] + magnum.__all__ # hide values of the preprocessor defines to avoid confusion by assigning a diff --git a/src/Corrade/Python.h b/src/Corrade/Python.h index aac8f8e..98789ea 100644 --- a/src/Corrade/Python.h +++ b/src/Corrade/Python.h @@ -88,6 +88,17 @@ template class T, class U> T& pyObjectHolderFor(U& obj) { return pyObjectHolderFor>(pybind11::detail::get_object_handle(&obj, typeinfo), typeinfo); } +/* This is a variant of https://github.com/pybind/pybind11/issues/1178, + implemented on the client side instead of patching pybind itself */ +template struct PyNonDestructibleBaseDeleter; +template struct PyNonDestructibleBaseDeleter { + void operator()(T*) { CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } +}; +template struct PyNonDestructibleBaseDeleter { + void operator()(T* ptr) { delete ptr; } +}; +template using PyNonDestructibleClass = pybind11::class_::value>>>; + } #endif diff --git a/src/Magnum/Python.h b/src/Magnum/Python.h index ba2b44d..7f685ad 100644 --- a/src/Magnum/Python.h +++ b/src/Magnum/Python.h @@ -48,17 +48,6 @@ template PyImageViewHolder pyImageViewHolder(const T& view, pybind11 return PyImageViewHolder{new T{view}, owner}; } -/* This is a variant of https://github.com/pybind/pybind11/issues/1178, - implemented on the client side instead of patching pybind itself */ -template struct PyNonDestructibleBaseDeleter; -template struct PyNonDestructibleBaseDeleter { - void operator()(T*) { CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } -}; -template struct PyNonDestructibleBaseDeleter { - void operator()(T* ptr) { delete ptr; } -}; -template using PyNonDestructibleClass = pybind11::class_::value>>>; - } PYBIND11_DECLARE_HOLDER_TYPE(T, Magnum::PyImageViewHolder) diff --git a/src/python/corrade/CMakeLists.txt b/src/python/corrade/CMakeLists.txt index 4952796..ce20cd6 100644 --- a/src/python/corrade/CMakeLists.txt +++ b/src/python/corrade/CMakeLists.txt @@ -23,6 +23,10 @@ # DEALINGS IN THE SOFTWARE. # +# *Not* REQUIRED +find_package(Corrade COMPONENTS + PluginManager) + set(corrade_SRCS corrade.cpp) @@ -32,6 +36,9 @@ set(corrade_LIBS ) set(corrade_containers_SRCS containers.cpp) +set(corrade_pluginmanager_SRCS + pluginmanager.cpp) + # If Corrade is not built as static, compile the sub-libraries as separate # modules if(NOT CORRADE_BUILD_STATIC) @@ -47,18 +54,37 @@ if(NOT CORRADE_BUILD_STATIC) OUTPUT_NAME "containers" LIBRARY_OUTPUT_DIRECTORY ${output_dir}/corrade) + if(Corrade_PluginManager_FOUND) + pybind11_add_module(corrade_pluginmanager SYSTEM ${corrade_pluginmanager_SRCS}) + target_include_directories(corrade_pluginmanager PRIVATE + ${PROJECT_SOURCE_DIR}/src + ${PROJECT_SOURCE_DIR}/src/python) + target_link_libraries(corrade_pluginmanager PRIVATE + Corrade::PluginManager) + set_target_properties(corrade_pluginmanager PROPERTIES + FOLDER "python/corrade" + OUTPUT_NAME "pluginmanager" + LIBRARY_OUTPUT_DIRECTORY ${output_dir}/corrade) + endif() + # Otherwise put it all into one library so it's easier to install (which is the # point of static builds). It also nicely avoids problems with multiply-defined # global data. else() list(APPEND corrade_SRCS ${corrade_containers_SRCS}) list(APPEND corrade_LIBS Corrade::Containers) + + if(Corrade_PluginManager_FOUND) + list(APPEND corrade_SRCS ${corrade_pluginmanager_SRCS}) + list(APPEND corrade_LIBS Corrade::PluginManager) + endif() endif() pybind11_add_module(corrade SYSTEM ${corrade_SRCS}) target_include_directories(corrade PRIVATE ${PROJECT_SOURCE_DIR}/src - ${PROJECT_SOURCE_DIR}/src/python) + ${PROJECT_SOURCE_DIR}/src/python + ${PROJECT_BINARY_DIR}/src/python) # for static build target_link_libraries(corrade PRIVATE Corrade::Utility ${corrade_LIBS}) set_target_properties(corrade PROPERTIES FOLDER "python" diff --git a/src/python/corrade/bootstrap.h b/src/python/corrade/bootstrap.h index cb73578..3f2ad6f 100644 --- a/src/python/corrade/bootstrap.h +++ b/src/python/corrade/bootstrap.h @@ -34,6 +34,7 @@ using namespace Corrade; namespace py = pybind11; void containers(py::module& m); +void pluginmanager(py::module& m); } diff --git a/src/python/corrade/corrade.cpp b/src/python/corrade/corrade.cpp index bc1ed78..85ef5d6 100644 --- a/src/python/corrade/corrade.cpp +++ b/src/python/corrade/corrade.cpp @@ -116,5 +116,10 @@ PYBIND11_MODULE(_corrade, m) { #ifdef CORRADE_BUILD_STATIC py::module containers = m.def_submodule("containers"); corrade::containers(containers); + + #ifdef Corrade_PluginManager_FOUND + py::module pluginmanager = m.def_submodule("pluginmanager"); + corrade::pluginmanager(pluginmanager); + #endif #endif } diff --git a/src/python/corrade/pluginmanager.cpp b/src/python/corrade/pluginmanager.cpp new file mode 100644 index 0000000..f9a193a --- /dev/null +++ b/src/python/corrade/pluginmanager.cpp @@ -0,0 +1,77 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include /* for pluginList() and aliasList() */ +#include + +#include "Corrade/Python.h" + +#include "corrade/bootstrap.h" +#include "corrade/EnumOperators.h" + +namespace corrade { + +void pluginmanager(py::module& m) { + m.doc() = "Plugin management"; + + py::enum_ loadState{m, "LoadState", "Plugin load state"}; + loadState + .value("NOT_FOUND", PluginManager::LoadState::NotFound) + .value("WRONG_PLUGIN_VERSION", PluginManager::LoadState::WrongPluginVersion) + .value("WRONG_INTERFACE_VERSION", PluginManager::LoadState::WrongInterfaceVersion) + .value("WRONG_METADATA_FILE", PluginManager::LoadState::WrongMetadataFile) + .value("UNRESOLVED_DEPENDENCY", PluginManager::LoadState::UnresolvedDependency) + .value("STATIC", PluginManager::LoadState::Static) + .value("LOADED", PluginManager::LoadState::Loaded) + .value("NOT_LOADED", PluginManager::LoadState::NotLoaded) + .value("UNLOAD_FAILED", PluginManager::LoadState::UnloadFailed) + .value("REQUIRED", PluginManager::LoadState::Required) + .value("USED", PluginManager::LoadState::Used); + corrade::enumOperators(loadState); + + PyNonDestructibleClass manager{m, "AbstractManager", "Base for plugin managers"}; + manager.attr("VERSION") = PluginManager::AbstractManager::Version; + manager + .def_property_readonly("plugin_interface", &PluginManager::AbstractManager::pluginInterface, "Plugin interface") + .def_property("plugin_directory", &PluginManager::AbstractManager::pluginDirectory, &PluginManager::AbstractManager::setPluginDirectory, "Plugin directory") + .def("reload_plugin_directory", &PluginManager::AbstractManager::reloadPluginDirectory, "Reload plugin directory") + /** @todo setPreferredPlugins (takes an init list) */ + .def("plugin_list", &PluginManager::AbstractManager::pluginList, "List of all available plugin names") + .def("alias_list", &PluginManager::AbstractManager::aliasList, "List of all available alias names") + /** @todo metadata() (figure out the ownership) */ + .def("load_state", &PluginManager::AbstractManager::loadState, "Load state of a plugin") + .def("load", &PluginManager::AbstractManager::load, "Load a plugin") + .def("unload", &PluginManager::AbstractManager::unload, "Unload a plugin"); +} + +} + +#ifndef CORRADE_BUILD_STATIC +extern "C" PYBIND11_EXPORT PyObject* PyInit_pluginmanager(); +PYBIND11_MODULE(pluginmanager, m) { + corrade::pluginmanager(m); +} +#endif diff --git a/src/python/corrade/staticconfigure.h.cmake b/src/python/corrade/staticconfigure.h.cmake new file mode 100644 index 0000000..3b9201f --- /dev/null +++ b/src/python/corrade/staticconfigure.h.cmake @@ -0,0 +1,29 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/* Named corrade/staticconfigure.h to avoid it colliding with Corrade/configure.h + on case-insensitive filesystems */ + +#cmakedefine Corrade_PluginManager_FOUND diff --git a/src/python/magnum/shaders.cpp b/src/python/magnum/shaders.cpp index 85f664d..55484cb 100644 --- a/src/python/magnum/shaders.cpp +++ b/src/python/magnum/shaders.cpp @@ -29,7 +29,7 @@ #include #include -#include "Magnum/Python.h" +#include "Corrade/Python.h" #include "corrade/EnumOperators.h" #include "magnum/bootstrap.h" diff --git a/src/python/setup.py.cmake b/src/python/setup.py.cmake index 1d1e946..66f34f9 100644 --- a/src/python/setup.py.cmake +++ b/src/python/setup.py.cmake @@ -35,6 +35,7 @@ extension_paths = { # present. '_corrade': '$', 'corrade.containers': '${corrade_containers_file}', + 'corrade.pluginmanager': '${corrade_pluginmanager_file}', '_magnum': '$', 'magnum.gl': '${magnum_gl_file}', 'magnum.meshtools': '${magnum_meshtools_file}',