Browse Source

python: add a dedicated test for StridedArrayView of a dynamic type.

Yup, this could work very well for MeshData / SceneData generic
attribute and field access with what's already there, no changes needed.
next
Vladimír Vondruš 3 years ago
parent
commit
27983b66ba
  1. 29
      src/python/corrade/test/test_containers.py
  2. 25
      src/python/corrade/test/test_containers_numpy.py
  3. 46
      src/python/corrade/test/test_stridedarrayview.cpp

29
src/python/corrade/test/test_containers.py

@ -902,6 +902,35 @@ class StridedArrayViewCustomType(unittest.TestCase):
# mutable_vector3d and mutable_long_float tested in test_containers_numpy
# as memoryview can't handle their types
class StridedArrayViewCustomDynamicType(unittest.TestCase):
def test_float(self):
a = test_stridedarrayview.MutableContainerDynamicType('f')
self.assertEqual(a.view.size, (2, 3))
self.assertEqual(a.view.stride, (12, 4))
self.assertEqual(a.view.format, 'f')
a.view[0][1] = 15.0
a.view[1][0] = -22.0
self.assertEqual(a.view[0][0], 0.0)
self.assertEqual(a.view[0][1], 15.0)
self.assertEqual(a.view[0][2], 0.0)
self.assertEqual(a.view[1][0], -22.0)
self.assertEqual(a.view[1][1], 0.0)
self.assertEqual(a.view[1][2], 0.0)
def test_int(self):
a = test_stridedarrayview.MutableContainerDynamicType('i')
self.assertEqual(a.view.size, (2, 3))
self.assertEqual(a.view.stride, (12, 4))
self.assertEqual(a.view.format, 'i')
a.view[0][2] = 15
a.view[1][1] = -773
self.assertEqual(a.view[0][0], 0)
self.assertEqual(a.view[0][1], 0)
self.assertEqual(a.view[0][2], 15)
self.assertEqual(a.view[1][0], 0)
self.assertEqual(a.view[1][1], -773)
self.assertEqual(a.view[1][2], 0)
class TestOptional(unittest.TestCase):
def test_simple(self):
self.assertIsNone(test_optional.simple_type(False))

25
src/python/corrade/test/test_containers_numpy.py

@ -130,3 +130,28 @@ class StridedArrayViewCustomType(unittest.TestCase):
(1001, 1.125),
(4666025, -7.5)
])
class StridedArrayViewCustomDynamicType(unittest.TestCase):
def test_short_short(self):
a = test_stridedarrayview.MutableContainerDynamicType('hh')
self.assertEqual(a.view.size, (2, 3))
self.assertEqual(a.view.stride, (12, 4))
self.assertEqual(a.view.format, 'hh')
# Test that numpy understands the type and has changes reflected
av = np.array(a.view, copy=False)
av[1][0] = (22563, -17665)
a.view[0][1] = (15, 34)
a.view[1][1] = (-22, 18)
# Converting to a tuple, otherwise numpy always compares to False
self.assertEqual(tuple(av[0][1]), (15, 34))
self.assertEqual(tuple(av[1][0]), (22563, -17665))
self.assertEqual(tuple(av[1][1]), (-22, 18))
# And the other way around as well
self.assertEqual(a.view[0][0], (0, 0))
self.assertEqual(a.view[0][1], (15, 34))
self.assertEqual(a.view[0][2], (0, 0))
self.assertEqual(a.view[1][0], (22563, -17665))
self.assertEqual(a.view[1][1], (-22, 18))
self.assertEqual(a.view[1][2], (0, 0))

46
src/python/corrade/test/test_stridedarrayview.cpp

@ -57,6 +57,17 @@ template<class T> struct Container {
T data[3*2]{};
};
struct MutableContainerDynamicType {
explicit MutableContainerDynamicType(const std::string& format): format{format} {}
Containers::StridedArrayView2D<void> view() {
return {Containers::arrayView(data), {2, 3}, {12, 4}};
}
std::string format;
char data[3*2*4]{};
};
template<class T> void container(py::class_<Container<T>>& c) {
c
.def(py::init())
@ -81,6 +92,41 @@ PYBIND11_MODULE(test_stridedarrayview, m) {
container(mutableContainer3d);
container(mutableContainerlf);
py::class_<MutableContainerDynamicType>{m, "MutableContainerDynamicType"}
.def(py::init<const std::string&>())
.def_property_readonly("view", [](MutableContainerDynamicType & self) {
std::size_t itemsize;
py::object(*getitem)(const char*);
void(*setitem)(char*, py::handle);
if(self.format == "f") {
itemsize = 4;
getitem = [](const char* item) {
return py::cast(*reinterpret_cast<const float*>(item));
};
setitem = [](char* item, py::handle object) {
*reinterpret_cast<float*>(item) = py::cast<float>(object);
};
} else if(self.format == "i") {
itemsize = 4;
getitem = [](const char* item) {
return py::cast(*reinterpret_cast<const int*>(item));
};
setitem = [](char* item, py::handle object) {
*reinterpret_cast<int*>(item) = py::cast<int>(object);
};
} else if(self.format == "hh") {
itemsize = 4;
getitem = [](const char* item) {
return py::cast(*reinterpret_cast<const std::pair<short, short>*>(item));
};
setitem = [](char* item, py::handle object) {
*reinterpret_cast<std::pair<short, short>*>(item) = py::cast<std::pair<short, short>>(object);
};
} else throw py::attribute_error{};
return Containers::pyArrayViewHolder(Containers::PyStridedArrayView<2, char>{Containers::arrayCast<char>(self.view()), self.format.data(), itemsize, getitem, setitem}, py::cast(self));
});
m.def("get_containers", []() {
return Container<const std::int16_t>{3, -17565, 5};
});

Loading…
Cancel
Save