Browse Source

python: lazily adapt to Corrade & Magnum std::string removal.

Because making & testing my own string caster is not something I'd want
to do right now (seems complicated by looking at what's all done for
std::string), the functions currently all go through a std::string
instead.
pull/15/head
Vladimír Vondruš 4 years ago
parent
commit
b58b53bfda
  1. 36
      src/python/corrade/pluginmanager.cpp
  2. 40
      src/python/magnum/trade.cpp

36
src/python/corrade/pluginmanager.cpp

@ -25,6 +25,8 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include <pybind11/stl.h> /* for pluginList() and aliasList() */ #include <pybind11/stl.h> /* for pluginList() and aliasList() */
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/StringStl.h> /** @todo drop once we have our string casters */
#include <Corrade/PluginManager/AbstractManager.h> #include <Corrade/PluginManager/AbstractManager.h>
#include "Corrade/PythonBindings.h" #include "Corrade/PythonBindings.h"
@ -55,14 +57,38 @@ void pluginmanager(py::module_& m) {
PyNonDestructibleClass<PluginManager::AbstractManager> manager{m, "AbstractManager", "Base for plugin managers"}; PyNonDestructibleClass<PluginManager::AbstractManager> manager{m, "AbstractManager", "Base for plugin managers"};
manager.attr("VERSION") = PluginManager::AbstractManager::Version; manager.attr("VERSION") = PluginManager::AbstractManager::Version;
manager manager
.def_property_readonly("plugin_interface", &PluginManager::AbstractManager::pluginInterface, "Plugin interface") .def_property_readonly("plugin_interface", [](PluginManager::AbstractManager& self) {
.def_property("plugin_directory", &PluginManager::AbstractManager::pluginDirectory, &PluginManager::AbstractManager::setPluginDirectory, "Plugin directory") /** @todo drop std::string in favor of our own string caster */
return std::string{self.pluginInterface()};
}, "Plugin interface")
.def_property("plugin_directory",
/** @todo drop std::string in favor of our own string caster */
[](PluginManager::AbstractManager& self) {
return std::string{self.pluginDirectory()};
}, [](PluginManager::AbstractManager& self, const std::string& directory) {
self.setPluginDirectory(directory);
}, "Plugin directory")
.def("reload_plugin_directory", &PluginManager::AbstractManager::reloadPluginDirectory, "Reload plugin directory") .def("reload_plugin_directory", &PluginManager::AbstractManager::reloadPluginDirectory, "Reload plugin directory")
/** @todo setPreferredPlugins (takes an init list) */ /** @todo setPreferredPlugins (takes an init list) */
.def_property_readonly("plugin_list", &PluginManager::AbstractManager::pluginList, "List of all available plugin names") .def_property_readonly("plugin_list", [](PluginManager::AbstractManager& self) {
.def_property_readonly("alias_list", &PluginManager::AbstractManager::aliasList, "List of all available alias names") /** @todo make a generic caster for arbitrary arrays and strings */
std::vector<std::string> out;
for(Containers::StringView i: self.pluginList())
out.push_back(i);
return out;
}, "List of all available plugin names")
.def_property_readonly("alias_list", [](PluginManager::AbstractManager& self) {
/** @todo make a generic caster for arbitrary arrays and strings */
std::vector<std::string> out;
for(Containers::StringView i: self.aliasList())
out.push_back(i);
return out;
}, "List of all available alias names")
/** @todo metadata() (figure out the ownership) */ /** @todo metadata() (figure out the ownership) */
.def("load_state", &PluginManager::AbstractManager::loadState, "Load state of a plugin") /** @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);
}, "Load state of a plugin")
.def("load", [](PluginManager::AbstractManager& self, const std::string& plugin) { .def("load", [](PluginManager::AbstractManager& self, const std::string& plugin) {
/** @todo log redirection -- but we'd need assertions to not be /** @todo log redirection -- but we'd need assertions to not be
part of that so when it dies, the user can still see why */ part of that so when it dies, the user can still see why */

40
src/python/magnum/trade.cpp

@ -26,6 +26,7 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include <Corrade/Containers/Optional.h> #include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/StridedArrayView.h> #include <Corrade/Containers/StridedArrayView.h>
#include <Corrade/Containers/StringStl.h> /** @todo drop once we have our string casters */
#include <Magnum/ImageView.h> #include <Magnum/ImageView.h>
#include <Magnum/Trade/AbstractImporter.h> #include <Magnum/Trade/AbstractImporter.h>
#include <Magnum/Trade/ImageData.h> #include <Magnum/Trade/ImageData.h>
@ -154,6 +155,14 @@ template<class R, class Arg1, R(Trade::AbstractImporter::*f)(Arg1)> R checkOpene
} }
return (self.*f)(arg1); return (self.*f)(arg1);
} }
/** @todo drop this in favor of our own string caster */
template<class R, R(Trade::AbstractImporter::*f)(Containers::StringView)> R checkOpenedString(Trade::AbstractImporter& self, const std::string& arg1) {
if(!self.isOpened()) {
PyErr_SetString(PyExc_RuntimeError, "no file opened");
throw py::error_already_set{};
}
return (self.*f)(arg1);
}
template<class R, R(Trade::AbstractImporter::*f)(UnsignedInt), UnsignedInt(Trade::AbstractImporter::*bounds)() const> R checkOpenedBounds(Trade::AbstractImporter& self, UnsignedInt id) { template<class R, R(Trade::AbstractImporter::*f)(UnsignedInt), UnsignedInt(Trade::AbstractImporter::*bounds)() const> R checkOpenedBounds(Trade::AbstractImporter& self, UnsignedInt id) {
if(!self.isOpened()) { if(!self.isOpened()) {
@ -168,6 +177,20 @@ template<class R, R(Trade::AbstractImporter::*f)(UnsignedInt), UnsignedInt(Trade
return (self.*f)(id); return (self.*f)(id);
} }
/** @todo drop this in favor of our own string caster */
template<Containers::String(Trade::AbstractImporter::*f)(UnsignedInt), UnsignedInt(Trade::AbstractImporter::*bounds)() const> std::string checkOpenedBoundsReturnsString(Trade::AbstractImporter& self, UnsignedInt id) {
if(!self.isOpened()) {
PyErr_SetString(PyExc_RuntimeError, "no file opened");
throw py::error_already_set{};
}
if(id >= (self.*bounds)()) {
PyErr_SetNone(PyExc_IndexError);
throw py::error_already_set{};
}
return (self.*f)(id);
}
template<class R, Containers::Optional<R>(Trade::AbstractImporter::*f)(UnsignedInt), UnsignedInt(Trade::AbstractImporter::*bounds)() const> R checkOpenedBoundsResult(Trade::AbstractImporter& self, UnsignedInt id) { template<class R, Containers::Optional<R>(Trade::AbstractImporter::*f)(UnsignedInt), UnsignedInt(Trade::AbstractImporter::*bounds)() const> R checkOpenedBoundsResult(Trade::AbstractImporter& self, UnsignedInt id) {
if(!self.isOpened()) { if(!self.isOpened()) {
@ -257,6 +280,7 @@ void trade(py::module_& m) {
PyErr_SetString(PyExc_RuntimeError, "opening data failed"); PyErr_SetString(PyExc_RuntimeError, "opening data failed");
throw py::error_already_set{}; throw py::error_already_set{};
}, "Open raw data", py::arg("data")) }, "Open raw data", py::arg("data"))
/** @todo drop std::string in favor of our own string caster */
.def("open_file", [](Trade::AbstractImporter& self, const std::string& filename) { .def("open_file", [](Trade::AbstractImporter& self, const std::string& filename) {
/** @todo log redirection -- but we'd need assertions to not be /** @todo log redirection -- but we'd need assertions to not be
part of that so when it dies, the user can still see why */ part of that so when it dies, the user can still see why */
@ -270,8 +294,8 @@ void trade(py::module_& m) {
/** @todo all other data types */ /** @todo all other data types */
.def_property_readonly("mesh_count", checkOpened<UnsignedInt, &Trade::AbstractImporter::meshCount>, "Mesh count") .def_property_readonly("mesh_count", checkOpened<UnsignedInt, &Trade::AbstractImporter::meshCount>, "Mesh count")
.def("mesh_level_count", checkOpenedBounds<UnsignedInt, &Trade::AbstractImporter::meshLevelCount, &Trade::AbstractImporter::meshCount>, "Mesh level count", py::arg("id")) .def("mesh_level_count", checkOpenedBounds<UnsignedInt, &Trade::AbstractImporter::meshLevelCount, &Trade::AbstractImporter::meshCount>, "Mesh level count", py::arg("id"))
.def("mesh_for_name", checkOpened<Int, const std::string&, &Trade::AbstractImporter::meshForName>, "Mesh ID for given name") .def("mesh_for_name", checkOpenedString<Int, &Trade::AbstractImporter::meshForName>, "Mesh ID for given name")
.def("mesh_name", checkOpenedBounds<std::string, &Trade::AbstractImporter::meshName, &Trade::AbstractImporter::meshCount>, "Mesh name", py::arg("id")) .def("mesh_name", checkOpenedBoundsReturnsString<&Trade::AbstractImporter::meshName, &Trade::AbstractImporter::meshCount>, "Mesh name", py::arg("id"))
.def("mesh", checkOpenedBoundsResult<Trade::MeshData, &Trade::AbstractImporter::mesh, &Trade::AbstractImporter::meshCount, &Trade::AbstractImporter::meshLevelCount>, "Mesh", py::arg("id"), py::arg("level") = 0) .def("mesh", checkOpenedBoundsResult<Trade::MeshData, &Trade::AbstractImporter::mesh, &Trade::AbstractImporter::meshCount, &Trade::AbstractImporter::meshLevelCount>, "Mesh", py::arg("id"), py::arg("level") = 0)
/** @todo mesh_attribute_for_name / mesh_attribute_name */ /** @todo mesh_attribute_for_name / mesh_attribute_name */
@ -281,12 +305,12 @@ void trade(py::module_& m) {
.def("image1d_level_count", checkOpenedBounds<UnsignedInt, &Trade::AbstractImporter::image1DLevelCount, &Trade::AbstractImporter::image1DCount>, "One-dimensional image level count", py::arg("id")) .def("image1d_level_count", checkOpenedBounds<UnsignedInt, &Trade::AbstractImporter::image1DLevelCount, &Trade::AbstractImporter::image1DCount>, "One-dimensional image level count", py::arg("id"))
.def("image2d_level_count", checkOpenedBounds<UnsignedInt, &Trade::AbstractImporter::image2DLevelCount, &Trade::AbstractImporter::image2DCount>, "Two-dimensional image level count", py::arg("id")) .def("image2d_level_count", checkOpenedBounds<UnsignedInt, &Trade::AbstractImporter::image2DLevelCount, &Trade::AbstractImporter::image2DCount>, "Two-dimensional image level count", py::arg("id"))
.def("image3d_level_count", checkOpenedBounds<UnsignedInt, &Trade::AbstractImporter::image3DLevelCount, &Trade::AbstractImporter::image3DCount>, "Three-dimensional image level count", py::arg("id")) .def("image3d_level_count", checkOpenedBounds<UnsignedInt, &Trade::AbstractImporter::image3DLevelCount, &Trade::AbstractImporter::image3DCount>, "Three-dimensional image level count", py::arg("id"))
.def("image1d_for_name", checkOpened<Int, const std::string&, &Trade::AbstractImporter::image1DForName>, "One-dimensional image ID for given name") .def("image1d_for_name", checkOpenedString<Int, &Trade::AbstractImporter::image1DForName>, "One-dimensional image ID for given name")
.def("image2d_for_name", checkOpened<Int, const std::string&, &Trade::AbstractImporter::image2DForName>, "Two-dimensional image ID for given name") .def("image2d_for_name", checkOpenedString<Int, &Trade::AbstractImporter::image2DForName>, "Two-dimensional image ID for given name")
.def("image3d_for_name", checkOpened<Int, const std::string&, &Trade::AbstractImporter::image3DForName>, "Three-dimensional image ID for given name") .def("image3d_for_name", checkOpenedString<Int, &Trade::AbstractImporter::image3DForName>, "Three-dimensional image ID for given name")
.def("image1d_name", checkOpenedBounds<std::string, &Trade::AbstractImporter::image1DName, &Trade::AbstractImporter::image1DCount>, "One-dimensional image name", py::arg("id")) .def("image1d_name", checkOpenedBoundsReturnsString<&Trade::AbstractImporter::image1DName, &Trade::AbstractImporter::image1DCount>, "One-dimensional image name", py::arg("id"))
.def("image2d_name", checkOpenedBounds<std::string, &Trade::AbstractImporter::image2DName, &Trade::AbstractImporter::image2DCount>, "Two-dimensional image name", py::arg("id")) .def("image2d_name", checkOpenedBoundsReturnsString<&Trade::AbstractImporter::image2DName, &Trade::AbstractImporter::image2DCount>, "Two-dimensional image name", py::arg("id"))
.def("image3d_name", checkOpenedBounds<std::string, &Trade::AbstractImporter::image3DName, &Trade::AbstractImporter::image3DCount>, "Three-dimensional image name", py::arg("id")) .def("image3d_name", checkOpenedBoundsReturnsString< &Trade::AbstractImporter::image3DName, &Trade::AbstractImporter::image3DCount>, "Three-dimensional image name", py::arg("id"))
.def("image1d", checkOpenedBoundsResult<Trade::ImageData1D, &Trade::AbstractImporter::image1D, &Trade::AbstractImporter::image1DCount, &Trade::AbstractImporter::image1DLevelCount>, "One-dimensional image", py::arg("id"), py::arg("level") = 0) .def("image1d", checkOpenedBoundsResult<Trade::ImageData1D, &Trade::AbstractImporter::image1D, &Trade::AbstractImporter::image1DCount, &Trade::AbstractImporter::image1DLevelCount>, "One-dimensional image", py::arg("id"), py::arg("level") = 0)
.def("image2d", checkOpenedBoundsResult<Trade::ImageData2D, &Trade::AbstractImporter::image2D, &Trade::AbstractImporter::image2DCount, &Trade::AbstractImporter::image2DLevelCount>, "Two-dimensional image", py::arg("id"), py::arg("level") = 0) .def("image2d", checkOpenedBoundsResult<Trade::ImageData2D, &Trade::AbstractImporter::image2D, &Trade::AbstractImporter::image2DCount, &Trade::AbstractImporter::image2DLevelCount>, "Two-dimensional image", py::arg("id"), py::arg("level") = 0)
.def("image3d", checkOpenedBoundsResult<Trade::ImageData3D, &Trade::AbstractImporter::image3D, &Trade::AbstractImporter::image3DCount, &Trade::AbstractImporter::image3DLevelCount>, "Three-dimensional image", py::arg("id"), py::arg("level") = 0); .def("image3d", checkOpenedBoundsResult<Trade::ImageData3D, &Trade::AbstractImporter::image3D, &Trade::AbstractImporter::image3DCount, &Trade::AbstractImporter::image3DLevelCount>, "Three-dimensional image", py::arg("id"), py::arg("level") = 0);

Loading…
Cancel
Save