Skip to content

Commit 5d7d33e

Browse files
committed
Validator coverage
1 parent 1d83a41 commit 5d7d33e

File tree

2 files changed

+108
-2
lines changed

2 files changed

+108
-2
lines changed

src/cattrs/v/_validators.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def between(min: C, max: C) -> Callable[[C], None]:
2828
"""Ensure the value of the attribute is between min (inclusive) and max (exclusive)."""
2929

3030
def assert_between(val: C, _min: C = min, _max: C = max) -> None:
31-
if not (_min <= val) and not (_max < val):
31+
if val < _min or val >= _max:
3232
raise ValueError(f"{val} not between {_min} and {_max}")
3333

3434
return assert_between
@@ -39,7 +39,7 @@ def len_between(min: int, max: int) -> Callable[[Sized], None]:
3939

4040
def assert_len_between(val: Sized, _min: int = min, _max: int = max) -> None:
4141
length = len(val)
42-
if not (_min <= length < max):
42+
if not (_min <= length < _max):
4343
raise ValueError(f"length ({length}) not between {_min} and {_max}")
4444

4545
return assert_len_between

tests/v/test_validators.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
from typing import List
2+
3+
from attrs import define
4+
from attrs import fields as f
5+
from pytest import raises
6+
7+
from cattrs import BaseConverter
8+
from cattrs.errors import ClassValidationError
9+
from cattrs.v import V, between, customize, greater_than, len_between, transform_error
10+
11+
12+
@define
13+
class WithInt:
14+
a: int
15+
16+
17+
@define
18+
class WithList:
19+
a: List[int]
20+
21+
22+
def test_gt(converter: BaseConverter):
23+
"""The greater_than validator works."""
24+
customize(converter, WithInt, V(f(WithInt).a).ensure(greater_than(10)))
25+
26+
assert converter.structure({"a": 11}, WithInt) == WithInt(11)
27+
28+
if converter.detailed_validation:
29+
with raises(ClassValidationError) as exc_info:
30+
converter.structure({"a": 10}, WithInt)
31+
32+
assert transform_error(exc_info.value) == [
33+
"invalid value (10 not greater than 10) @ $.a"
34+
]
35+
else:
36+
with raises(ValueError) as exc_info:
37+
converter.structure({"a": 10}, WithInt)
38+
39+
assert repr(exc_info.value) == "ValueError('10 not greater than 10')"
40+
41+
42+
def test_between(converter: BaseConverter):
43+
"""The between validator works."""
44+
customize(converter, WithInt, V(f(WithInt).a).ensure(between(10, 20)))
45+
46+
assert converter.structure({"a": 10}, WithInt) == WithInt(10)
47+
assert converter.structure({"a": 19}, WithInt) == WithInt(19)
48+
49+
if converter.detailed_validation:
50+
with raises(ClassValidationError) as exc_info:
51+
converter.structure({"a": 9}, WithInt)
52+
53+
assert transform_error(exc_info.value) == [
54+
"invalid value (9 not between 10 and 20) @ $.a"
55+
]
56+
else:
57+
with raises(ValueError) as exc_info:
58+
converter.structure({"a": 9}, WithInt)
59+
60+
assert repr(exc_info.value) == "ValueError('9 not between 10 and 20')"
61+
62+
if converter.detailed_validation:
63+
with raises(ClassValidationError) as exc_info:
64+
converter.structure({"a": 20}, WithInt)
65+
66+
assert transform_error(exc_info.value) == [
67+
"invalid value (20 not between 10 and 20) @ $.a"
68+
]
69+
else:
70+
with raises(ValueError) as exc_info:
71+
converter.structure({"a": 20}, WithInt)
72+
73+
assert repr(exc_info.value) == "ValueError('20 not between 10 and 20')"
74+
75+
76+
def test_len_between(converter: BaseConverter):
77+
"""The len_between validator works."""
78+
customize(converter, WithList, V(f(WithList).a).ensure(len_between(1, 2)))
79+
80+
assert converter.structure({"a": [1]}, WithList) == WithList([1])
81+
82+
if converter.detailed_validation:
83+
with raises(ClassValidationError) as exc_info:
84+
converter.structure({"a": []}, WithList)
85+
86+
assert transform_error(exc_info.value) == [
87+
"invalid value (length (0) not between 1 and 2) @ $.a"
88+
]
89+
else:
90+
with raises(ValueError) as exc_info:
91+
converter.structure({"a": []}, WithList)
92+
93+
assert repr(exc_info.value) == "ValueError('length (0) not between 1 and 2')"
94+
95+
if converter.detailed_validation:
96+
with raises(ClassValidationError) as exc_info:
97+
converter.structure({"a": [1, 2]}, WithList)
98+
99+
assert transform_error(exc_info.value) == [
100+
"invalid value (length (2) not between 1 and 2) @ $.a"
101+
]
102+
else:
103+
with raises(ValueError) as exc_info:
104+
converter.structure({"a": [1, 2]}, WithList)
105+
106+
assert repr(exc_info.value) == "ValueError('length (2) not between 1 and 2')"

0 commit comments

Comments
 (0)