11"""Tests for `cattrs.v.ensure`."""
22import sys
3- from typing import List , MutableSequence , Sequence
3+ from typing import Dict , List , MutableSequence , Sequence
44
55from pytest import fixture , mark , raises
66
77from cattrs import BaseConverter
88from cattrs ._compat import ExceptionGroup
9+ from cattrs .errors import IterableValidationError
910from cattrs .v import ensure
1011from cattrs .v ._hooks import is_validated , validator_factory
1112
1213
1314@fixture
1415def valconv (converter ) -> BaseConverter :
15- converter .register_structure_hook_factory (is_validated )( validator_factory )
16+ converter .register_structure_hook_factory (is_validated , validator_factory )
1617 return converter
1718
1819
@@ -38,7 +39,7 @@ def test_ensured_lists(valconv: BaseConverter):
3839 valconv .structure ([], ensure (List [int ], lambda lst : len (lst ) > 0 ))
3940
4041 if valconv .detailed_validation :
41- assert isinstance (exc .value , ExceptionGroup )
42+ assert isinstance (exc .value , IterableValidationError )
4243 assert isinstance (exc .value .exceptions [0 ], ValueError )
4344 else :
4445 assert isinstance (exc .value , ValueError )
@@ -53,7 +54,53 @@ def test_ensured_list_elements(valconv: BaseConverter, type):
5354 valconv .structure ([1 , - 2 ], ensure (type , elems = ensure (int , lambda i : i > 0 )))
5455
5556 if valconv .detailed_validation :
56- assert isinstance (exc .value , ExceptionGroup )
57+ assert isinstance (exc .value , IterableValidationError )
58+ assert isinstance (exc .value .exceptions [0 ], ExceptionGroup )
59+ assert isinstance (exc .value .exceptions [0 ].exceptions [0 ], ValueError )
60+ else :
61+ assert isinstance (exc .value , ValueError )
62+
63+ # Now both elements and the list itself.
64+ assert valconv .structure (
65+ [1 , 2 ],
66+ ensure (type , lambda lst : len (lst ) < 3 , elems = ensure (int , lambda i : i > 0 )),
67+ )
68+
69+ with raises (Exception ) as exc :
70+ valconv .structure (
71+ [1 , 2 , 3 ],
72+ ensure (type , lambda lst : len (lst ) < 3 , elems = ensure (int , lambda i : i > 0 )),
73+ )
74+
75+ if valconv .detailed_validation :
76+ assert isinstance (exc .value , IterableValidationError )
77+ assert isinstance (exc .value .exceptions [0 ], ValueError )
78+ else :
79+ assert isinstance (exc .value , ValueError )
80+
81+ with raises (Exception ) as exc :
82+ valconv .structure (
83+ [1 , - 2 ],
84+ ensure (type , lambda lst : len (lst ) < 3 , elems = ensure (int , lambda i : i > 0 )),
85+ )
86+
87+ if valconv .detailed_validation :
88+ assert isinstance (exc .value , IterableValidationError )
89+ assert isinstance (exc .value .exceptions [0 ], ExceptionGroup )
90+ assert isinstance (exc .value .exceptions [0 ].exceptions [0 ], ValueError )
91+ else :
92+ assert isinstance (exc .value , ValueError )
93+
94+
95+ def test_ensured_typing_list (valconv : BaseConverter ):
96+ """Ensure works for typing lists."""
97+ assert valconv .structure ([1 , 2 ], ensure (List , elems = ensure (int , lambda i : i > 0 )))
98+
99+ with raises (Exception ) as exc :
100+ valconv .structure ([1 , - 2 ], ensure (List , elems = ensure (int , lambda i : i > 0 )))
101+
102+ if valconv .detailed_validation :
103+ assert isinstance (exc .value , IterableValidationError )
57104 assert isinstance (exc .value .exceptions [0 ], ExceptionGroup )
58105 assert isinstance (exc .value .exceptions [0 ].exceptions [0 ], ValueError )
59106 else :
@@ -63,13 +110,42 @@ def test_ensured_list_elements(valconv: BaseConverter, type):
63110@mark .skipif (sys .version_info [:2 ] < (3 , 10 ), reason = "Not supported on older Pythons" )
64111def test_ensured_list (valconv : BaseConverter ):
65112 """Ensure works for builtin lists."""
66- assert valconv .structure ([1 , 2 ], ensure (List , elems = ensure (int , lambda i : i > 0 )))
113+ assert valconv .structure ([1 , 2 ], ensure (list , elems = ensure (int , lambda i : i > 0 )))
67114
68115 with raises (Exception ) as exc :
69- valconv .structure ([1 , - 2 ], ensure (List , elems = ensure (int , lambda i : i > 0 )))
116+ valconv .structure ([1 , - 2 ], ensure (list , elems = ensure (int , lambda i : i > 0 )))
70117
71118 if valconv .detailed_validation :
72- assert isinstance (exc .value , ExceptionGroup )
119+ assert isinstance (exc .value , IterableValidationError )
120+ assert isinstance (exc .value .exceptions [0 ], ExceptionGroup )
121+ assert isinstance (exc .value .exceptions [0 ].exceptions [0 ], ValueError )
122+ else :
123+ assert isinstance (exc .value , ValueError )
124+
125+
126+ def test_ensured_typing_dict (valconv : BaseConverter ):
127+ """Ensure works for typing.Dicts."""
128+ assert valconv .structure (
129+ {"a" : 1 }, ensure (Dict , lambda d : len (d ) > 0 , keys = str , values = int )
130+ )
131+
132+ with raises (Exception ) as exc :
133+ valconv .structure ({}, ensure (Dict , lambda d : len (d ) > 0 , keys = str , values = int ))
134+
135+ if valconv .detailed_validation :
136+ assert isinstance (exc .value , IterableValidationError )
137+ assert isinstance (exc .value .exceptions [0 ], ValueError )
138+ else :
139+ assert isinstance (exc .value , ValueError )
140+
141+ with raises (Exception ) as exc :
142+ valconv .structure (
143+ {"b" : 1 , "c" : "a" },
144+ ensure (Dict , keys = ensure (str , lambda s : s .startswith ("a" )), values = int ),
145+ )
146+
147+ if valconv .detailed_validation :
148+ assert isinstance (exc .value , IterableValidationError )
73149 assert isinstance (exc .value .exceptions [0 ], ExceptionGroup )
74150 assert isinstance (exc .value .exceptions [0 ].exceptions [0 ], ValueError )
75151 else :
0 commit comments