Browse Source

python: implement pickling for all math types.

next
Vladimír Vondruš 3 years ago
parent
commit
f561337caa
  1. 322
      doc/python/magnum.math.rst
  2. 46
      src/python/magnum/math.cpp
  3. 18
      src/python/magnum/math.matrix.h
  4. 18
      src/python/magnum/math.range.cpp
  5. 18
      src/python/magnum/math.vector.h
  6. 75
      src/python/magnum/test/test_math.py

322
doc/python/magnum.math.rst

@ -229,3 +229,325 @@
:py:`Matrix4.translation(vec)` will return a translation matrix, while
:py:`mat.translation` is a read-write property accessing the fourth column
of the matrix. Similarly for the :ref:`Matrix3` class.
.. For pickling, because py::pickle() doesn't seem to have a way to set the
__setstate__ / __getstate__ docs directly FFS
.. py:function:: magnum.Deg.__getstate__
:summary: Dumps the in-memory representation as a float
.. py:function:: magnum.Rad.__getstate__
:summary: Dumps the in-memory representation as a float
.. py:function:: magnum.BitVector2.__getstate__
:summary: Dumps the in-memory representation of vector bits
.. py:function:: magnum.BitVector3.__getstate__
:summary: Dumps the in-memory representation of vector bits
.. py:function:: magnum.BitVector4.__getstate__
:summary: Dumps the in-memory representation of vector bits
.. py:function:: magnum.Vector2.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector3.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector4.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector2d.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector3d.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector4d.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector2i.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector3i.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector4i.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector2ui.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector3ui.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Vector4ui.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Color3.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Color4.__getstate__
:summary: Dumps the in-memory representation of vector components
.. py:function:: magnum.Matrix2x2.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix2x3.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix2x4.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix3x2.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix3x3.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix3x4.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix4x2.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix4x3.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix4x4.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix2x2d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix2x3d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix2x4d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix3x2d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix3x3d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix3x4d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix4x2d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix4x3d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix4x4d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix3.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix4.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix3d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Matrix4d.__getstate__
:summary: Dumps the in-memory representation of matrix components
.. py:function:: magnum.Quaternion.__getstate__
:summary: Dumps the in-memory representation of quaternion components
.. py:function:: magnum.Quaterniond.__getstate__
:summary: Dumps the in-memory representation of quaternion components
.. py:function:: magnum.Range1D.__getstate__
:summary: Dumps the in-memory representation of range min/max components
.. py:function:: magnum.Range2D.__getstate__
:summary: Dumps the in-memory representation of range min/max components
.. py:function:: magnum.Range3D.__getstate__
:summary: Dumps the in-memory representation of range min/max components
.. py:function:: magnum.Range1Dd.__getstate__
:summary: Dumps the in-memory representation of range min/max components
.. py:function:: magnum.Range2Dd.__getstate__
:summary: Dumps the in-memory representation of range min/max components
.. py:function:: magnum.Range3Dd.__getstate__
:summary: Dumps the in-memory representation of range min/max components
.. py:function:: magnum.Range1Di.__getstate__
:summary: Dumps the in-memory representation of range min/max components
.. py:function:: magnum.Range2Di.__getstate__
:summary: Dumps the in-memory representation of range min/max components
.. py:function:: magnum.Range3Di.__getstate__
:summary: Dumps the in-memory representation of range min/max components
.. py:function:: magnum.Deg.__setstate__
:summary: Uses the float as the in-memory representation
.. py:function:: magnum.Rad.__setstate__
:summary: Uses the float as the in-memory representation
.. py:function:: magnum.BitVector2.__setstate__
:summary: Treats the data as the in-memory representation of vector bits
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.BitVector3.__setstate__
:summary: Treats the data as the in-memory representation of vector bits
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.BitVector4.__setstate__
:summary: Treats the data as the in-memory representation of vector bits
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector2.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector3.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector4.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector2d.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector3d.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector4d.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector2i.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector3i.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector4i.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector2ui.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector3ui.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Vector4ui.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Color3.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Color4.__setstate__
:summary: Treats the data as the in-memory representation of vector
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix2x2.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix2x3.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix2x4.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix3x2.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix3x3.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix3x4.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix4x2.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix4x3.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix4x4.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix2x2d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix2x3d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix2x4d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix3x2d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix3x3d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix3x4d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix4x2d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix4x3d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix4x4d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix3.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix4.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix3d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Matrix4d.__setstate__
:summary: Treats the data as the in-memory representation of matrix
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Quaternion.__setstate__
:summary: Treats the data as the in-memory representation of quaternion
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Quaterniond.__setstate__
:summary: Treats the data as the in-memory representation of quaternion
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Range1D.__setstate__
:summary: Treats the data as the in-memory representation of range min/max
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Range2D.__setstate__
:summary: Treats the data as the in-memory representation of range min/max
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Range3D.__setstate__
:summary: Treats the data as the in-memory representation of range min/max
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Range1Dd.__setstate__
:summary: Treats the data as the in-memory representation of range min/max
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Range2Dd.__setstate__
:summary: Treats the data as the in-memory representation of range min/max
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Range3Dd.__setstate__
:summary: Treats the data as the in-memory representation of range min/max
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Range1Di.__setstate__
:summary: Treats the data as the in-memory representation of range min/max
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Range2Di.__setstate__
:summary: Treats the data as the in-memory representation of range min/max
components
:raise ValueError: If the data size doesn't match type size
.. py:function:: magnum.Range3Di.__setstate__
:summary: Treats the data as the in-memory representation of range min/max
components
:raise ValueError: If the data size doesn't match type size

46
src/python/magnum/math.cpp

@ -116,6 +116,16 @@ template<class T> void angle(py::module_& m, py::class_<T>& c) {
.def(py::self <= py::self, "Less than or equal comparison")
.def(py::self >= py::self, "Greater than or equal comparison")
/* Pickling */
.def(py::pickle(
[](const T& self) {
return typename T::Type(self);
},
[](typename T::Type data) {
return T(data);
}
))
/* Arithmetic ops. Need to use lambdas because the C++ functions return
the Unit base class :( */
.def("__neg__", [](const T& self) -> T {
@ -195,6 +205,24 @@ template<class T> void bitVector(py::module_& m, py::class_<T>& c) {
.def(py::self == py::self, "Equality comparison")
.def(py::self != py::self, "Non-equality comparison")
/* Pickling */
.def(py::pickle(
[](const T& self) {
return py::bytes(reinterpret_cast<const char*>(self.data()), sizeof(T));
},
[](const py::bytes& data) {
const std::size_t size = PyBytes_GET_SIZE(data.ptr());
if(size != sizeof(T)) {
PyErr_Format(PyExc_ValueError, "expected %zu bytes but got %zi", sizeof(T), size);
throw py::error_already_set{};
}
T out;
/** @todo gah is there really no other way to access contents? */
std::memcpy(out.data(), PyBytes_AS_STRING(data.ptr()), sizeof(T));
return out;
}
))
/* Member functions */
.def("all", &T::all, "Whether all bits are set")
.def("none", &T::none, "Whether no bits are set")
@ -314,6 +342,24 @@ template<class T> void quaternion(py::module_& m, py::class_<T>& c) {
.def(py::self == py::self, "Equality comparison")
.def(py::self != py::self, "Non-equality comparison")
/* Pickling */
.def(py::pickle(
[](const T& self) {
return py::bytes(reinterpret_cast<const char*>(self.data()), sizeof(T));
},
[](const py::bytes& data) {
const std::size_t size = PyBytes_GET_SIZE(data.ptr());
if(size != sizeof(T)) {
PyErr_Format(PyExc_ValueError, "expected %zu bytes but got %zi", sizeof(T), size);
throw py::error_already_set{};
}
T out;
/** @todo gah is there really no other way to access contents? */
std::memcpy(out.data(), PyBytes_AS_STRING(data.ptr()), sizeof(T));
return out;
}
))
/* Operators */
.def(-py::self, "Negated quaternion")
.def(py::self += py::self, "Add and assign a quaternion")

18
src/python/magnum/math.matrix.h

@ -67,6 +67,24 @@ template<class T, class ...Args> void everyRectangularMatrix(py::class_<T, Args.
.def(py::init(), "Default constructor")
.def(py::init<typename T::Type>(), "Construct a matrix with one value for all components")
/* Pickling */
.def(py::pickle(
[](const T& self) {
return py::bytes(reinterpret_cast<const char*>(self.data()), sizeof(T));
},
[](const py::bytes& data) {
const std::size_t size = PyBytes_GET_SIZE(data.ptr());
if(size != sizeof(T)) {
PyErr_Format(PyExc_ValueError, "expected %zu bytes but got %zi", sizeof(T), size);
throw py::error_already_set{};
}
T out;
/** @todo gah is there really no other way to access contents? */
std::memcpy(out.data(), PyBytes_AS_STRING(data.ptr()), sizeof(T));
return out;
}
))
/* Operators */
.def(-py::self, "Negated matrix")
.def(py::self += py::self, "Add and assign a matrix")

18
src/python/magnum/math.range.cpp

@ -73,6 +73,24 @@ template<class T> void range(py::module_& m, py::class_<T>& c) {
[](T& self, const typename T::VectorType& value) { self.max() = value; },
"Maximal coordinates (exclusive)")
/* Pickling */
.def(py::pickle(
[](const T& self) {
return py::bytes(reinterpret_cast<const char*>(self.data()), sizeof(T));
},
[](const py::bytes& data) {
const std::size_t size = PyBytes_GET_SIZE(data.ptr());
if(size != sizeof(T)) {
PyErr_Format(PyExc_ValueError, "expected %zu bytes but got %zi", sizeof(T), size);
throw py::error_already_set{};
}
T out;
/** @todo gah is there really no other way to access contents? */
std::memcpy(out.data(), PyBytes_AS_STRING(data.ptr()), sizeof(T));
return out;
}
))
/* Methods */
.def("size", &T::size, "Range size")
.def("center", &T::center, "Range center")

18
src/python/magnum/math.vector.h

@ -92,6 +92,24 @@ template<class T, class ...Args> void everyVector(py::class_<T, Args...>& c) {
}, "Construct a zero vector")
.def(py::init(), "Default constructor")
/* Pickling */
.def(py::pickle(
[](const T& self) {
return py::bytes(reinterpret_cast<const char*>(self.data()), sizeof(T));
},
[](const py::bytes& data) {
const std::size_t size = PyBytes_GET_SIZE(data.ptr());
if(size != sizeof(T)) {
PyErr_Format(PyExc_ValueError, "expected %zu bytes but got %zi", sizeof(T), size);
throw py::error_already_set{};
}
T out;
/** @todo gah is there really no other way to access contents? */
std::memcpy(out.data(), PyBytes_AS_STRING(data.ptr()), sizeof(T));
return out;
}
))
/* Operators */
.def(py::self += py::self, "Add and assign a vector")
.def(py::self + py::self, "Add a vector")

75
src/python/magnum/test/test_math.py

@ -24,6 +24,7 @@
#
import array
import pickle
import unittest
from magnum import *
@ -38,6 +39,12 @@ class Angle(unittest.TestCase):
self.assertEqual(b, Rad(0.0))
self.assertEqual(c, Deg(90.0))
def test_pickle(self):
data = pickle.dumps(Deg(45.0))
self.assertEqual(pickle.loads(data), Deg(45.0))
# There's no way for this pickle to fail
def test_conversion(self):
self.assertEqual(Rad(Deg(90.0)), Rad(math.pi_half))
@ -80,6 +87,12 @@ class BitVector(unittest.TestCase):
self.assertEqual(b, BitVector2(0b00))
self.assertEqual(c, BitVector2(0b11))
def test_pickle(self):
data = pickle.dumps(BitVector4(0b1010))
self.assertEqual(pickle.loads(data), BitVector4(0b1010))
# TODO how to test pickle failure?! direct __setstate__ doesn't work :/
def test_length(self):
self.assertEqual(BitVector3.__len__(), 3)
#self.assertEqual(len(BitVector3), 3) TODO: Y not?
@ -246,6 +259,12 @@ class Vector(unittest.TestCase):
self.assertEqual(d, Vector3(1.0, 0.3, 1.1))
self.assertEqual(e, Vector4d(1.0, 0.3, 1.1, 0.5))
def test_pickle(self):
data = pickle.dumps(Vector4d(1.0, 0.3, 1.1, 0.5))
self.assertEqual(pickle.loads(data), Vector4d(1.0, 0.3, 1.1, 0.5))
# TODO how to test pickle failure?! direct __setstate__ doesn't work :/
def test_convert(self):
a = Vector2i(Vector2(4.3, 3.1))
self.assertEqual(a, Vector2i(4, 3))
@ -500,6 +519,12 @@ class Color3_(unittest.TestCase):
self.assertEqual(blue, Color3(0.0, 0.0, 0.5))
self.assertEqual(yellow, Color3(1.0, 1.0, 0.5))
def test_pickle(self):
data = pickle.dumps(Color3(0.107177, 0.160481, 0.427))
self.assertEqual(pickle.loads(data), Color3(0.107177, 0.160481, 0.427))
# TODO how to test pickle failure?! direct __setstate__ doesn't work :/
def test_srgb(self):
# Cross-checked with C++ tests
a = Color3.from_srgb_int(0xf32a80)
@ -576,6 +601,12 @@ class Color4_(unittest.TestCase):
self.assertEqual(blue, Color4(0.0, 0.0, 0.5, 0.75))
self.assertEqual(yellow, Color4(1.0, 1.0, 0.5, 0.75))
def test_pickle(self):
data = pickle.dumps(Color4(0.107177, 0.160481, 0.427, 0.5))
self.assertEqual(pickle.loads(data), Color4(0.107177, 0.160481, 0.427, 0.5))
# TODO how to test pickle failure?! direct __setstate__ doesn't work :/
def test_srgb(self):
# Cross-checked with C++ tests
a = Color4.from_srgb_int(0xf32a80)
@ -824,6 +855,16 @@ class Matrix(unittest.TestCase):
(0.0, 2.0, 0.0, 0.0),
(0.0, 0.0, 3.0, 0.0)))
def test_pickle(self):
data = pickle.dumps(Matrix3x2((1.0, 2.0),
(3.0, 4.0),
(5.0, 6.0)))
self.assertEqual(pickle.loads(data), Matrix3x2((1.0, 2.0),
(3.0, 4.0),
(5.0, 6.0)))
# TODO how to test pickle failure?! direct __setstate__ doesn't work :/
def test_convert(self):
a = Matrix2x3d(Matrix2x3((1.0, 2.0, 3.0),
(4.0, 5.0, 6.0)))
@ -971,6 +1012,16 @@ class Matrix3_(unittest.TestCase):
c = Matrix3.scaling((1.0, 2.0))
self.assertEqual(c.scaling(), Vector2(1.0, 2.0))
def test_pickle(self):
data = pickle.dumps(Matrix3((1.0, 2.0, 3.0),
(4.0, 5.0, 6.0),
(7.0, 8.0, 9.0)))
self.assertEqual(pickle.loads(data), Matrix3((1.0, 2.0, 3.0),
(4.0, 5.0, 6.0),
(7.0, 8.0, 9.0)))
# TODO how to test pickle failure?! direct __setstate__ doesn't work :/
def test_properties(self):
a = Matrix3.translation(Vector2.y_axis(-5.0))@Matrix3.rotation(Deg(45.0))
self.assertEqual(a.right, Vector2(0.707107, 0.707107))
@ -1074,6 +1125,18 @@ class Matrix4_(unittest.TestCase):
(9.0, 10.0, 11.0, 12.0),
(13.0, 14.0, 15.0, 16.0)))
def test_pickle(self):
data = pickle.dumps(Matrix4((1.0, 2.0, 3.0, 4.0),
(5.0, 6.0, 7.0, 8.0),
(9.0, 10.0, 11.0, 12.0),
(13.0, 14.0, 15.0, 16.0)))
self.assertEqual(pickle.loads(data), Matrix4((1.0, 2.0, 3.0, 4.0),
(5.0, 6.0, 7.0, 8.0),
(9.0, 10.0, 11.0, 12.0),
(13.0, 14.0, 15.0, 16.0)))
# TODO how to test pickle failure?! direct __setstate__ doesn't work :/
def test_static_methods(self):
a = Matrix4.translation((0.0, -1.0, 2.0))
self.assertEqual(a[3].xyz, Vector3(0.0, -1.0, 2.0))
@ -1162,6 +1225,12 @@ class Quaternion_(unittest.TestCase):
self.assertEqual(a, Quaternion((0.382683, 0.0, 0.0), 0.92388))
self.assertEqual(a.to_matrix(), Matrix4.rotation_x(Deg(45.0)).rotation_scaling())
def test_pickle(self):
data = pickle.dumps(Quaternion((1.0, 2.0, 3.0), 4.0))
self.assertEqual(pickle.loads(data), Quaternion((1.0, 2.0, 3.0), 4.0))
# TODO how to test pickle failure?! direct __setstate__ doesn't work :/
def test_methods(self):
a = Quaternion.rotation(Deg(45.0), Vector3.x_axis())
self.assertEqual(a.inverted(),
@ -1236,6 +1305,12 @@ class Range(unittest.TestCase):
self.assertEqual(c.min, Vector2(3.0, 1.0))
self.assertEqual(c.max, Vector2(5.0, 1.5))
def test_pickle(self):
data = pickle.dumps(Range2D((1.0, 0.3), (2.0, 0.6)))
self.assertEqual(pickle.loads(data), Range2D((1.0, 0.3), (2.0, 0.6)))
# TODO how to test pickle failure?! direct __setstate__ doesn't work :/
def test_properties(self):
a = Range2D((1.0, 0.2), (2.0, 0.4))
self.assertEqual(a.bottom_right, Vector2(2.0, 0.2))

Loading…
Cancel
Save