diff --git a/src/python/magnum/math.cpp b/src/python/magnum/math.cpp index 7770751..48e1272 100644 --- a/src/python/magnum/math.cpp +++ b/src/python/magnum/math.cpp @@ -125,9 +125,16 @@ template void boolVector(py::class_& c) { .def("none", &T::none, "Whether no bits are set") .def("any", &T::any, "Whether any bit is set") - /* Set / get */ - .def("__setitem__", &T::set, "Set a bit at given position", py::arg("i"), py::arg("value")) - .def("__getitem__", &T::operator[], "Bit at given position") + /* Set / get. Need to throw IndexError in order to allow iteration: + https://docs.python.org/3/reference/datamodel.html#object.__getitem__ */ + .def("__setitem__",[](T& self, std::size_t i, bool value) { + if(i >= T::Size) throw pybind11::index_error{}; + self.set(i, value); + }, "Set a bit at given position") + .def("__getitem__", [](const T& self, std::size_t i) { + if(i >= T::Size) throw pybind11::index_error{}; + return self[i]; + }, "Bit at given position") /* Operators */ .def(~py::self, "Bitwise inversion") diff --git a/src/python/magnum/math.vector.h b/src/python/magnum/math.vector.h index a638378..886a62d 100644 --- a/src/python/magnum/math.vector.h +++ b/src/python/magnum/math.vector.h @@ -63,11 +63,14 @@ template void vector(py::module& m, py::class_& c) { .def(py::self <= py::self, "Component-wise less than or equal comparison") .def(py::self >= py::self, "Component-wise greater than or equal comparison") - /* Set / get */ + /* Set / get. Need to throw IndexError in order to allow iteration: + https://docs.python.org/3/reference/datamodel.html#object.__getitem__ */ .def("__setitem__", [](T& self, std::size_t i, typename T::Type value) { + if(i >= T::Size) throw pybind11::index_error{}; self[i] = value; }, "Set a value at given position") .def("__getitem__", [](const T& self, std::size_t i) { + if(i >= T::Size) throw pybind11::index_error{}; return self[i]; }, "Value at given position") diff --git a/src/python/magnum/test/test_math.py b/src/python/magnum/test/test_math.py index ecc8685..08de790 100644 --- a/src/python/magnum/test/test_math.py +++ b/src/python/magnum/test/test_math.py @@ -91,6 +91,10 @@ class BoolVector(unittest.TestCase): a[2] = True self.assertEqual(a, BoolVector4(0b1110)) + def test_iterate(self): + a = [i for i in BoolVector4(0b1010)] + self.assertEqual(a, [False, True, False, True]) + def test_ops(self): a = BoolVector3(0b101) | BoolVector3(0b010) self.assertEqual(a, BoolVector3(0b111)) @@ -219,6 +223,12 @@ class Vector(unittest.TestCase): b.xy += Vector2i(1, -1) self.assertEqual(b, Vector4i(4, 3, 15, 6)) + def test_iterate(self): + a = [i for i in Vector4(1.0, 3.25, 3.5, -1.125)] + # assertAlmostEqual doesn't work on lists so i'm using values directly + # representable as floats to avoid the need for delta comparison + self.assertEqual(a, [1.0, 3.25, 3.5, -1.125]) + def test_ops(self): self.assertEqual(math.dot(Vector2(0.5, 3.0), Vector2(2.0, 0.5)), 2.5) self.assertEqual(Deg(math.angle(