diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index b46575c3..af9139a5 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -156,6 +156,9 @@ def __new__(cls, *args, **kwargs): return self + def __reduce__(self): + return type(self).__new__, (type(self), self.x, self.y) + #: Return a new :py:class:`Vector2` replacing specified fields with new values. update = dataclasses.replace diff --git a/tests/test_vector2_ctor.py b/tests/test_vector2_ctor.py index a30e6c4d..3aa4cd33 100644 --- a/tests/test_vector2_ctor.py +++ b/tests/test_vector2_ctor.py @@ -1,3 +1,5 @@ +import pickle + import pytest # type: ignore from hypothesis import given @@ -38,3 +40,13 @@ def test_ctor_noncopy_subclass(): def test_ctor_noncopy_superclass(): v = Vector2(1, 2) assert V(v) is not v + + +@pytest.mark.parametrize("cls", [Vector2, V]) +@given(v=vectors()) +def test_ctor_pickle(cls, v: Vector2): + """Round-trip Vector2 and subclasses through `pickle.{dumps,loads}`.""" + w = pickle.loads(pickle.dumps(cls(v))) + + assert v == w + assert isinstance(w, cls)