Browse Source

python: reorder trade.MeshData APIs to have enum overloads first.

Because for some reason pybind11 on *some platforms* (or in some
configurations?) picks the integer overload even for enum arguments,
only because it's first in the overload set.

This is extremely brittle, but for now I don't know any better solution.
next
Vladimír Vondruš 3 years ago
parent
commit
b3e24a11b4
  1. 113
      src/python/magnum/trade.cpp

113
src/python/magnum/trade.cpp

@ -520,6 +520,14 @@ void trade(py::module_& m) {
.def("attribute_count", static_cast<UnsignedInt(Trade::MeshData::*)() const>(&Trade::MeshData::attributeCount), "Attribute array count") .def("attribute_count", static_cast<UnsignedInt(Trade::MeshData::*)() const>(&Trade::MeshData::attributeCount), "Attribute array count")
/** @todo direct access to MeshAttributeData, once making custom /** @todo direct access to MeshAttributeData, once making custom
MeshData is desired */ MeshData is desired */
.def("has_attribute", &Trade::MeshData::hasAttribute, "Whether the mesh has given attribute", py::arg("name"))
.def("attribute_count", static_cast<UnsignedInt(Trade::MeshData::*)(Trade::MeshAttribute) const>(&Trade::MeshData::attributeCount), "Count of given named attribute", py::arg("name"))
/* IMPORTANT: due to yet-uninvestigated pybind11 platform-specific
behavioral differences the following overloads need to have the
MeshAttribute overload *before* the UnsignedInt overload, otherwise
the integer overload gets picked even if an enum is passed from
Python, causing massive suffering */
.def("attribute_name", [](Trade::MeshData& self, UnsignedInt id) { .def("attribute_name", [](Trade::MeshData& self, UnsignedInt id) {
if(id >= self.attributeCount()) { if(id >= self.attributeCount()) {
PyErr_SetString(PyExc_IndexError, ""); PyErr_SetString(PyExc_IndexError, "");
@ -527,6 +535,12 @@ void trade(py::module_& m) {
} }
return self.attributeName(id); return self.attributeName(id);
}, "Attribute name", py::arg("id")) }, "Attribute name", py::arg("id"))
.def("attribute_id", [](Trade::MeshData& self, Trade::MeshAttribute name, UnsignedInt id) {
if(const Containers::Optional<UnsignedInt> found = self.findAttributeId(name, id))
return *found;
PyErr_SetString(PyExc_KeyError, "");
throw py::error_already_set{};
}, "Absolute ID of a named attribute", py::arg("name"), py::arg("id") = 0)
.def("attribute_id", [](Trade::MeshData& self, UnsignedInt id) { .def("attribute_id", [](Trade::MeshData& self, UnsignedInt id) {
if(id >= self.attributeCount()) { if(id >= self.attributeCount()) {
PyErr_SetString(PyExc_IndexError, ""); PyErr_SetString(PyExc_IndexError, "");
@ -534,6 +548,12 @@ void trade(py::module_& m) {
} }
return self.attributeId(id); return self.attributeId(id);
}, "Attribute ID in a set of attributes of the same name", py::arg("id")) }, "Attribute ID in a set of attributes of the same name", py::arg("id"))
.def("attribute_format", [](Trade::MeshData& self, Trade::MeshAttribute name, UnsignedInt id) {
if(const Containers::Optional<UnsignedInt> found = self.findAttributeId(name, id))
return self.attributeFormat(*found);
PyErr_SetString(PyExc_KeyError, "");
throw py::error_already_set{};
}, "Format of a named attribute", py::arg("name"), py::arg("id") = 0)
.def("attribute_format", [](Trade::MeshData& self, UnsignedInt id) { .def("attribute_format", [](Trade::MeshData& self, UnsignedInt id) {
if(id >= self.attributeCount()) { if(id >= self.attributeCount()) {
PyErr_SetString(PyExc_IndexError, ""); PyErr_SetString(PyExc_IndexError, "");
@ -541,6 +561,12 @@ void trade(py::module_& m) {
} }
return self.attributeFormat(id); return self.attributeFormat(id);
}, "Attribute format", py::arg("id")) }, "Attribute format", py::arg("id"))
.def("attribute_offset", [](Trade::MeshData& self, Trade::MeshAttribute name, UnsignedInt id) {
if(const Containers::Optional<UnsignedInt> found = self.findAttributeId(name, id))
return self.attributeOffset(*found);
PyErr_SetString(PyExc_KeyError, "");
throw py::error_already_set{};
}, "Offset of a named attribute", py::arg("name"), py::arg("id") = 0)
.def("attribute_offset", [](Trade::MeshData& self, UnsignedInt id) { .def("attribute_offset", [](Trade::MeshData& self, UnsignedInt id) {
if(id >= self.attributeCount()) { if(id >= self.attributeCount()) {
PyErr_SetString(PyExc_IndexError, ""); PyErr_SetString(PyExc_IndexError, "");
@ -548,6 +574,12 @@ void trade(py::module_& m) {
} }
return self.attributeOffset(id); return self.attributeOffset(id);
}, "Attribute offset", py::arg("id")) }, "Attribute offset", py::arg("id"))
.def("attribute_stride", [](Trade::MeshData& self, Trade::MeshAttribute name, UnsignedInt id) {
if(const Containers::Optional<UnsignedInt> found = self.findAttributeId(name, id))
return self.attributeStride(*found);
PyErr_SetString(PyExc_KeyError, "");
throw py::error_already_set{};
}, "Stride of a named attribute", py::arg("name"), py::arg("id") = 0)
.def("attribute_stride", [](Trade::MeshData& self, UnsignedInt id) { .def("attribute_stride", [](Trade::MeshData& self, UnsignedInt id) {
if(id >= self.attributeCount()) { if(id >= self.attributeCount()) {
PyErr_SetString(PyExc_IndexError, ""); PyErr_SetString(PyExc_IndexError, "");
@ -555,93 +587,67 @@ void trade(py::module_& m) {
} }
return self.attributeStride(id); return self.attributeStride(id);
}, "Attribute stride", py::arg("id")) }, "Attribute stride", py::arg("id"))
.def("attribute_array_size", [](Trade::MeshData& self, UnsignedInt id) {
if(id >= self.attributeCount()) {
PyErr_SetString(PyExc_IndexError, "");
throw py::error_already_set{};
}
return self.attributeArraySize(id);
}, "Attribute array size", py::arg("id"))
.def("has_attribute", &Trade::MeshData::hasAttribute, "Whether the mesh has given attribute", py::arg("name"))
.def("attribute_count", static_cast<UnsignedInt(Trade::MeshData::*)(Trade::MeshAttribute) const>(&Trade::MeshData::attributeCount), "Count of given named attribute", py::arg("name"))
.def("attribute_id", [](Trade::MeshData& self, Trade::MeshAttribute name, UnsignedInt id) {
if(const Containers::Optional<UnsignedInt> found = self.findAttributeId(name, id))
return *found;
PyErr_SetString(PyExc_KeyError, "");
throw py::error_already_set{};
}, "Absolute ID of a named attribute", py::arg("name"), py::arg("id") = 0)
.def("attribute_format", [](Trade::MeshData& self, Trade::MeshAttribute name, UnsignedInt id) {
if(const Containers::Optional<UnsignedInt> found = self.findAttributeId(name, id))
return self.attributeFormat(*found);
PyErr_SetString(PyExc_KeyError, "");
throw py::error_already_set{};
}, "Format of a named attribute", py::arg("name"), py::arg("id") = 0)
.def("attribute_offset", [](Trade::MeshData& self, Trade::MeshAttribute name, UnsignedInt id) {
if(const Containers::Optional<UnsignedInt> found = self.findAttributeId(name, id))
return self.attributeOffset(*found);
PyErr_SetString(PyExc_KeyError, "");
throw py::error_already_set{};
}, "Offset of a named attribute", py::arg("name"), py::arg("id") = 0)
.def("attribute_stride", [](Trade::MeshData& self, Trade::MeshAttribute name, UnsignedInt id) {
if(const Containers::Optional<UnsignedInt> found = self.findAttributeId(name, id))
return self.attributeStride(*found);
PyErr_SetString(PyExc_KeyError, "");
throw py::error_already_set{};
}, "Stride of a named attribute", py::arg("name"), py::arg("id") = 0)
.def("attribute_array_size", [](Trade::MeshData& self, Trade::MeshAttribute name, UnsignedInt id) { .def("attribute_array_size", [](Trade::MeshData& self, Trade::MeshAttribute name, UnsignedInt id) {
if(const Containers::Optional<UnsignedInt> found = self.findAttributeId(name, id)) if(const Containers::Optional<UnsignedInt> found = self.findAttributeId(name, id))
return self.attributeArraySize(*found); return self.attributeArraySize(*found);
PyErr_SetString(PyExc_KeyError, ""); PyErr_SetString(PyExc_KeyError, "");
throw py::error_already_set{}; throw py::error_already_set{};
}, "Array size of a named attribute", py::arg("name"), py::arg("id") = 0) }, "Array size of a named attribute", py::arg("name"), py::arg("id") = 0)
.def("attribute", [](Trade::MeshData& self, UnsignedInt id) { .def("attribute_array_size", [](Trade::MeshData& self, UnsignedInt id) {
if(id >= self.attributeCount()) { if(id >= self.attributeCount()) {
PyErr_SetString(PyExc_IndexError, ""); PyErr_SetString(PyExc_IndexError, "");
throw py::error_already_set{}; throw py::error_already_set{};
} }
return self.attributeArraySize(id);
}, "Attribute array size", py::arg("id"))
.def("attribute", [](Trade::MeshData& self, Trade::MeshAttribute name, UnsignedInt id) {
const Containers::Optional<UnsignedInt> found = self.findAttributeId(name, id);
if(!found) {
PyErr_SetString(PyExc_KeyError, "");
throw py::error_already_set{};
}
/** @todo handle arrays (return a 2D view, and especially annotate /** @todo handle arrays (return a 2D view, and especially annotate
the return type properly in the docs) */ the return type properly in the docs) */
if(self.attributeArraySize(id) != 0) { if(self.attributeArraySize(*found) != 0) {
PyErr_SetString(PyExc_NotImplementedError, "array attributes not implemented yet, sorry"); PyErr_SetString(PyExc_NotImplementedError, "array attributes not implemented yet, sorry");
throw py::error_already_set{}; throw py::error_already_set{};
} }
return meshAttributeView(self, id, self.attribute(id)); return meshAttributeView(self, *found, self.attribute(*found));
}, "Data for given attribute", py::arg("id")) }, "Data for given named attribute", py::arg("name"), py::arg("id") = 0)
.def("mutable_attribute", [](Trade::MeshData& self, UnsignedInt id) { .def("attribute", [](Trade::MeshData& self, UnsignedInt id) {
if(id >= self.attributeCount()) { if(id >= self.attributeCount()) {
PyErr_SetString(PyExc_IndexError, ""); PyErr_SetString(PyExc_IndexError, "");
throw py::error_already_set{}; throw py::error_already_set{};
} }
if(!(self.vertexDataFlags() & Trade::DataFlag::Mutable)) {
PyErr_SetString(PyExc_AttributeError, "mesh vertex data is not mutable");
throw py::error_already_set{};
}
/** @todo handle arrays (return a 2D view, and especially annotate /** @todo handle arrays (return a 2D view, and especially annotate
the return type properly in the docs) */ the return type properly in the docs) */
if(self.attributeArraySize(id) != 0) { if(self.attributeArraySize(id) != 0) {
PyErr_SetString(PyExc_NotImplementedError, "array attributes not implemented yet, sorry"); PyErr_SetString(PyExc_NotImplementedError, "array attributes not implemented yet, sorry");
throw py::error_already_set{}; throw py::error_already_set{};
} }
return meshAttributeView(self, id, self.mutableAttribute(id)); return meshAttributeView(self, id, self.attribute(id));
}, "Mutable data for given attribute", py::arg("id")) }, "Data for given attribute", py::arg("id"))
.def("attribute", [](Trade::MeshData& self, Trade::MeshAttribute name, UnsignedInt id) { .def("mutable_attribute", [](Trade::MeshData& self, Trade::MeshAttribute name, UnsignedInt id) {
const Containers::Optional<UnsignedInt> found = self.findAttributeId(name, id); const Containers::Optional<UnsignedInt> found = self.findAttributeId(name, id);
if(!found) { if(!found) {
PyErr_SetString(PyExc_KeyError, ""); PyErr_SetString(PyExc_KeyError, "");
throw py::error_already_set{}; throw py::error_already_set{};
} }
if(!(self.vertexDataFlags() & Trade::DataFlag::Mutable)) {
PyErr_SetString(PyExc_AttributeError, "mesh vertex data is not mutable");
throw py::error_already_set{};
}
/** @todo handle arrays (return a 2D view, and especially annotate /** @todo handle arrays (return a 2D view, and especially annotate
the return type properly in the docs) */ the return type properly in the docs) */
if(self.attributeArraySize(*found) != 0) { if(self.attributeArraySize(*found) != 0) {
PyErr_SetString(PyExc_NotImplementedError, "array attributes not implemented yet, sorry"); PyErr_SetString(PyExc_NotImplementedError, "array attributes not implemented yet, sorry");
throw py::error_already_set{}; throw py::error_already_set{};
} }
return meshAttributeView(self, *found, self.attribute(*found)); return meshAttributeView(self, *found, self.mutableAttribute(*found));
}, "Data for given named attribute", py::arg("name"), py::arg("id") = 0) }, "Data for given named attribute", py::arg("name"), py::arg("id") = 0)
.def("mutable_attribute", [](Trade::MeshData& self, Trade::MeshAttribute name, UnsignedInt id) { .def("mutable_attribute", [](Trade::MeshData& self, UnsignedInt id) {
const Containers::Optional<UnsignedInt> found = self.findAttributeId(name, id); if(id >= self.attributeCount()) {
if(!found) { PyErr_SetString(PyExc_IndexError, "");
PyErr_SetString(PyExc_KeyError, "");
throw py::error_already_set{}; throw py::error_already_set{};
} }
if(!(self.vertexDataFlags() & Trade::DataFlag::Mutable)) { if(!(self.vertexDataFlags() & Trade::DataFlag::Mutable)) {
@ -650,13 +656,12 @@ void trade(py::module_& m) {
} }
/** @todo handle arrays (return a 2D view, and especially annotate /** @todo handle arrays (return a 2D view, and especially annotate
the return type properly in the docs) */ the return type properly in the docs) */
if(self.attributeArraySize(*found) != 0) { if(self.attributeArraySize(id) != 0) {
PyErr_SetString(PyExc_NotImplementedError, "array attributes not implemented yet, sorry"); PyErr_SetString(PyExc_NotImplementedError, "array attributes not implemented yet, sorry");
throw py::error_already_set{}; throw py::error_already_set{};
} }
return meshAttributeView(self, *found, self.mutableAttribute(*found)); return meshAttributeView(self, id, self.mutableAttribute(id));
}, "Data for given named attribute", py::arg("name"), py::arg("id") = 0) }, "Mutable data for given attribute", py::arg("id"));
;
py::class_<Trade::ImageData1D> imageData1D{m, "ImageData1D", "One-dimensional image data"}; py::class_<Trade::ImageData1D> imageData1D{m, "ImageData1D", "One-dimensional image data"};
py::class_<Trade::ImageData2D> imageData2D{m, "ImageData2D", "Two-dimensional image data"}; py::class_<Trade::ImageData2D> imageData2D{m, "ImageData2D", "Two-dimensional image data"};

Loading…
Cancel
Save