1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
|
import datetime
import pickle
import pytest
from pyrsistent import CheckedPVector, InvariantException, optional, CheckedValueTypeError, PVector
class Naturals(CheckedPVector):
__type__ = int
__invariant__ = lambda value: (value >= 0, 'Negative value')
def test_instantiate():
x = Naturals([1, 2, 3])
assert list(x) == [1, 2, 3]
assert isinstance(x, Naturals)
assert isinstance(x, PVector)
def test_append():
x = Naturals()
x2 = x.append(1)
assert list(x2) == [1]
assert isinstance(x2, Naturals)
def test_extend():
x = Naturals()
x2 = x.extend([1])
assert list(x2) == [1]
assert isinstance(x2, Naturals)
def test_set():
x = Naturals([1, 2])
x2 = x.set(1, 3)
assert list(x2) == [1, 3]
assert isinstance(x2, Naturals)
def test_invalid_type():
try:
Naturals([1, 2.0])
assert False
except CheckedValueTypeError as e:
assert e.expected_types == (int,)
assert e.actual_type is float
assert e.actual_value == 2.0
assert e.source_class is Naturals
x = Naturals([1, 2])
with pytest.raises(TypeError):
x.append(3.0)
with pytest.raises(TypeError):
x.extend([3, 4.0])
with pytest.raises(TypeError):
x.set(1, 2.0)
with pytest.raises(TypeError):
x.evolver()[1] = 2.0
def test_breaking_invariant():
try:
Naturals([1, -1])
assert False
except InvariantException as e:
assert e.invariant_errors == ('Negative value',)
x = Naturals([1, 2])
try:
x.append(-1)
assert False
except InvariantException as e:
assert e.invariant_errors == ('Negative value',)
try:
x.extend([-1])
assert False
except InvariantException as e:
assert e.invariant_errors == ('Negative value',)
try:
x.set(1, -1)
assert False
except InvariantException as e:
assert e.invariant_errors == ('Negative value',)
def test_create_base_case():
x = Naturals.create([1, 2, 3])
assert isinstance(x, Naturals)
assert x == Naturals([1, 2, 3])
def test_create_with_instance_of_checked_pvector_returns_the_argument():
x = Naturals([1, 2, 3])
assert Naturals.create(x) is x
class OptionalNaturals(CheckedPVector):
__type__ = optional(int)
__invariant__ = lambda value: (value is None or value >= 0, 'Negative value')
def test_multiple_allowed_types():
assert list(OptionalNaturals([1, None, 3])) == [1, None, 3]
class NaturalsVector(CheckedPVector):
__type__ = optional(Naturals)
def test_create_of_nested_structure():
assert NaturalsVector([Naturals([1, 2]), Naturals([3, 4]), None]) ==\
NaturalsVector.create([[1, 2], [3, 4], None])
def test_serialize_default_case():
v = CheckedPVector([1, 2, 3])
assert v.serialize() == [1, 2, 3]
class Dates(CheckedPVector):
__type__ = datetime.date
@staticmethod
def __serializer__(format, d):
return d.strftime(format)
def test_serialize_custom_serializer():
d = datetime.date
v = Dates([d(2015, 2, 2), d(2015, 2, 3)])
assert v.serialize(format='%Y-%m-%d') == ['2015-02-02', '2015-02-03']
def test_type_information_is_inherited():
class MultiDates(Dates):
__type__ = int
MultiDates([datetime.date(2015, 2, 4), 5])
with pytest.raises(TypeError):
MultiDates([5.0])
def test_invariants_are_inherited():
class LimitNaturals(Naturals):
__invariant__ = lambda value: (value < 10, 'Too big')
try:
LimitNaturals([10, -1])
assert False
except InvariantException as e:
assert e.invariant_errors == ('Too big', 'Negative value')
def test_invariant_must_be_callable():
with pytest.raises(TypeError):
class InvalidInvariant(CheckedPVector):
__invariant__ = 1
def test_type_spec_must_be_type():
with pytest.raises(TypeError):
class InvalidType(CheckedPVector):
__type__ = 1
def test_repr():
x = Naturals([1, 2])
assert str(x) == 'Naturals([1, 2])'
def test_evolver_returns_same_instance_when_no_updates():
x = Naturals([1, 2])
assert x.evolver().persistent() is x
def test_pickling():
x = Naturals([1, 2])
y = pickle.loads(pickle.dumps(x, -1))
assert x == y
assert isinstance(y, Naturals)
def test_multiple_optional_types():
class Numbers(CheckedPVector):
__type__ = optional(int, float)
numbers = Numbers([1, 2.5, None])
assert numbers.serialize() == [1, 2.5, None]
with pytest.raises(TypeError):
numbers.append('foo')
class NaturalsVectorStr(CheckedPVector):
__type__ = 'checked_vector_test.Naturals'
def test_check_with_string_specification():
naturals_list = [Naturals([1, 2]), Naturals([3, 4])]
nv = NaturalsVectorStr(naturals_list)
assert nv == naturals_list
def test_create_with_string_specification():
naturals_list = [[1, 2], [3, 4]]
nv = NaturalsVectorStr.create(naturals_list)
assert nv == naturals_list
def test_supports_weakref():
import weakref
weakref.ref(Naturals([]))
def test_create_with_generator_iterator():
# See issue #97
class Numbers(CheckedPVector):
__type__ = int
n = Numbers(i for i in [1, 2, 3])
assert n == Numbers([1, 2, 3])
|