4
4
5
5
from wtforms .validators import regexp
6
6
from wtforms .validators import ValidationError
7
+ from wtforms .validators import ValidatorSetupError
7
8
8
9
9
10
def grab_error_message (callable , form , field ):
@@ -14,43 +15,187 @@ def grab_error_message(callable, form, field):
14
15
15
16
16
17
@pytest .mark .parametrize (
17
- "re_pattern, re_flags, test_v, expected_v" ,
18
+ "re_pattern, re_flags, re_mode, test_v, expected_v" ,
18
19
[
19
- ("^a" , None , "abcd" , "a" ),
20
- ("^a" , re .I , "ABcd" , "A" ),
21
- (re .compile ("^a" ), None , "abcd" , "a" ),
22
- (re .compile ("^a" , re .I ), None , "ABcd" , "A" ),
20
+ # match mode
21
+ ("^a" , None , "match" , "abcd" , "a" ),
22
+ ("^a" , re .I , "match" , "ABcd" , "A" ),
23
+ ("^ab" , None , "match" , "abcd" , "ab" ),
24
+ ("^ab" , re .I , "match" , "ABcd" , "AB" ),
25
+ ("^abcd" , None , "match" , "abcd" , "abcd" ),
26
+ ("^abcd" , re .I , "match" , "ABcd" , "ABcd" ),
27
+ (r"^\w+" , None , "match" , "abcd" , "abcd" ),
28
+ (r"^\w+" , re .I , "match" , "ABcd" , "ABcd" ),
29
+ (re .compile ("^a" ), None , "match" , "abcd" , "a" ),
30
+ (re .compile ("^a" , re .I ), None , "match" , "ABcd" , "A" ),
31
+ (re .compile ("^ab" ), None , "match" , "abcd" , "ab" ),
32
+ (re .compile ("^ab" , re .I ), None , "match" , "ABcd" , "AB" ),
33
+ (re .compile ("^abcd" ), None , "match" , "abcd" , "abcd" ),
34
+ (re .compile ("^abcd" , re .I ), None , "match" , "ABcd" , "ABcd" ),
35
+ (re .compile (r"^\w+" ), None , "match" , "abcd" , "abcd" ),
36
+ (re .compile (r"^\w+" , re .I ), None , "match" , "ABcd" , "ABcd" ),
37
+ # fullmatch mode
38
+ ("^abcd" , None , "fullmatch" , "abcd" , "abcd" ),
39
+ ("^abcd" , re .I , "fullmatch" , "ABcd" , "ABcd" ),
40
+ ("^abcd$" , None , "fullmatch" , "abcd" , "abcd" ),
41
+ ("^abcd$" , re .I , "fullmatch" , "ABcd" , "ABcd" ),
42
+ (r"^\w+" , None , "fullmatch" , "abcd" , "abcd" ),
43
+ (r"^\w+" , re .I , "fullmatch" , "ABcd" , "ABcd" ),
44
+ (r"^\w+$" , None , "fullmatch" , "abcd" , "abcd" ),
45
+ (r"^\w+$" , re .I , "fullmatch" , "ABcd" , "ABcd" ),
46
+ (re .compile ("^abcd" ), None , "fullmatch" , "abcd" , "abcd" ),
47
+ (re .compile ("^abcd" , re .I ), None , "fullmatch" , "ABcd" , "ABcd" ),
48
+ (re .compile ("^abcd$" ), None , "fullmatch" , "abcd" , "abcd" ),
49
+ (re .compile ("^abcd$" , re .I ), None , "fullmatch" , "ABcd" , "ABcd" ),
50
+ (re .compile (r"^\w+" ), None , "fullmatch" , "abcd" , "abcd" ),
51
+ (re .compile (r"^\w+" , re .I ), None , "fullmatch" , "ABcd" , "ABcd" ),
52
+ (re .compile (r"^\w+$" ), None , "fullmatch" , "abcd" , "abcd" ),
53
+ (re .compile (r"^\w+$" , re .I ), None , "fullmatch" , "ABcd" , "ABcd" ),
54
+ # search mode
55
+ ("^a" , None , "search" , "abcd" , "a" ),
56
+ ("^a" , re .I , "search" , "ABcd" , "A" ),
57
+ ("bc" , None , "search" , "abcd" , "bc" ),
58
+ ("bc" , re .I , "search" , "ABcd" , "Bc" ),
59
+ ("cd$" , None , "search" , "abcd" , "cd" ),
60
+ ("cd$" , re .I , "search" , "ABcd" , "cd" ),
61
+ (r"\w" , None , "search" , "abcd" , "a" ),
62
+ (r"\w" , re .I , "search" , "ABcd" , "A" ),
63
+ (r"\w$" , None , "search" , "abcd" , "d" ),
64
+ (r"\w$" , re .I , "search" , "ABcd" , "d" ),
65
+ (r"\w+" , None , "search" , "abcd" , "abcd" ),
66
+ (r"\w+" , re .I , "search" , "ABcd" , "ABcd" ),
67
+ (r"\w+$" , None , "search" , "abcd" , "abcd" ),
68
+ (r"\w+$" , re .I , "search" , "ABcd" , "ABcd" ),
69
+ (re .compile ("^a" ), None , "search" , "abcd" , "a" ),
70
+ (re .compile ("^a" , re .I ), None , "search" , "ABcd" , "A" ),
71
+ (re .compile (r"d$" ), None , "search" , "abcd" , "d" ),
72
+ (re .compile (r"d$" , re .I ), None , "search" , "ABcd" , "d" ),
73
+ (re .compile ("bc" ), None , "search" , "abcd" , "bc" ),
74
+ (re .compile ("bc" , re .I ), None , "search" , "ABcd" , "Bc" ),
75
+ (re .compile (r"\w" ), None , "search" , "abcd" , "a" ),
76
+ (re .compile (r"\w" , re .I ), None , "search" , "ABcd" , "A" ),
77
+ (re .compile (r"\w+" ), None , "search" , "abcd" , "abcd" ),
78
+ (re .compile (r"\w+" , re .I ), None , "search" , "ABcd" , "ABcd" ),
23
79
],
24
80
)
25
81
def test_regex_passes (
26
- re_pattern , re_flags , test_v , expected_v , dummy_form , dummy_field
82
+ re_pattern , re_flags , re_mode , test_v , expected_v , dummy_form , dummy_field
27
83
):
28
84
"""
29
85
Regex should pass if there is a match.
30
- Should work for complie regex too
86
+ Should work for compile regex too
31
87
"""
32
- validator = regexp (re_pattern , re_flags ) if re_flags else regexp (re_pattern )
88
+ kwargs = {
89
+ "regex" : re_pattern ,
90
+ "flags" : re_flags if re_flags else 0 ,
91
+ "message" : None ,
92
+ "mode" : re_mode ,
93
+ }
94
+ validator = regexp (** kwargs )
33
95
dummy_field .data = test_v
34
96
assert validator (dummy_form , dummy_field ).group (0 ) == expected_v
35
97
36
98
37
99
@pytest .mark .parametrize (
38
- "re_pattern, re_flags, test_v" ,
100
+ "re_pattern, re_flags, re_mode, test_v" ,
39
101
[
40
- ("^a" , None , "ABC" ),
41
- ("^a" , re .I , "foo" ),
42
- ("^a" , None , None ),
43
- (re .compile ("^a" ), None , "foo" ),
44
- (re .compile ("^a" , re .I ), None , None ),
102
+ # math mode
103
+ ("^a" , None , "match" , "ABC" ),
104
+ ("^a" , re .I , "match" , "foo" ),
105
+ ("^a" , None , "match" , None ),
106
+ ("^ab" , None , "match" , "ABC" ),
107
+ ("^ab" , re .I , "match" , "foo" ),
108
+ ("^ab" , None , "match" , None ),
109
+ ("^ab$" , None , "match" , "ABC" ),
110
+ ("^ab$" , re .I , "match" , "foo" ),
111
+ ("^ab$" , None , "match" , None ),
112
+ (re .compile ("^a" ), None , "match" , "ABC" ),
113
+ (re .compile ("^a" , re .I ), None , "match" , "foo" ),
114
+ (re .compile ("^a" ), None , "match" , None ),
115
+ (re .compile ("^ab" ), None , "match" , "ABC" ),
116
+ (re .compile ("^ab" , re .I ), None , "match" , "foo" ),
117
+ (re .compile ("^ab" ), None , "match" , None ),
118
+ (re .compile ("^ab$" ), None , "match" , "ABC" ),
119
+ (re .compile ("^ab$" , re .I ), None , "match" , "foo" ),
120
+ (re .compile ("^ab$" ), None , "match" , None ),
121
+ # fullmatch mode
122
+ ("^abcd" , None , "fullmatch" , "abc" ),
123
+ ("^abcd" , re .I , "fullmatch" , "abc" ),
124
+ ("^abcd" , None , "fullmatch" , "foo" ),
125
+ ("^abcd" , re .I , "fullmatch" , "foo" ),
126
+ ("^abcd" , None , "fullmatch" , None ),
127
+ ("^abcd" , re .I , "fullmatch" , None ),
128
+ ("abcd$" , None , "fullmatch" , "abc" ),
129
+ ("abcd$" , re .I , "fullmatch" , "abc" ),
130
+ ("abcd$" , None , "fullmatch" , "foo" ),
131
+ ("abcd$" , re .I , "fullmatch" , "foo" ),
132
+ ("abcd$" , None , "fullmatch" , None ),
133
+ ("abcd$" , re .I , "fullmatch" , None ),
134
+ ("^abcd$" , None , "fullmatch" , "abc" ),
135
+ ("^abcd$" , re .I , "fullmatch" , "abc" ),
136
+ ("^abcd$" , None , "fullmatch" , "foo" ),
137
+ ("^abcd$" , re .I , "fullmatch" , "foo" ),
138
+ ("^abcd$" , None , "fullmatch" , None ),
139
+ ("^abcd$" , re .I , "fullmatch" , None ),
140
+ (re .compile ("^abcd" ), None , "fullmatch" , "abc" ),
141
+ (re .compile ("^abcd" , re .I ), None , "fullmatch" , "abc" ),
142
+ (re .compile ("^abcd" ), None , "fullmatch" , "foo" ),
143
+ (re .compile ("^abcd" , re .I ), None , "fullmatch" , "foo" ),
144
+ (re .compile ("^abcd" ), None , "fullmatch" , None ),
145
+ (re .compile ("^abcd" , re .I ), None , "fullmatch" , None ),
146
+ (re .compile ("abcd$" ), None , "fullmatch" , "abc" ),
147
+ (re .compile ("abcd$" , re .I ), None , "fullmatch" , "abc" ),
148
+ (re .compile ("abcd$" ), None , "fullmatch" , "foo" ),
149
+ (re .compile ("abcd$" , re .I ), None , "fullmatch" , "foo" ),
150
+ (re .compile ("abcd$" ), None , "fullmatch" , None ),
151
+ (re .compile ("abcd$" , re .I ), None , "fullmatch" , None ),
152
+ (re .compile ("^abcd$" ), None , "fullmatch" , "abc" ),
153
+ (re .compile ("^abcd$" , re .I ), None , "fullmatch" , "abc" ),
154
+ (re .compile ("^abcd$" ), None , "fullmatch" , "foo" ),
155
+ (re .compile ("^abcd$" , re .I ), None , "fullmatch" , "foo" ),
156
+ (re .compile ("^abcd$" ), None , "fullmatch" , None ),
157
+ (re .compile ("^abcd$" , re .I ), None , "fullmatch" , None ),
158
+ # search mode
159
+ ("^a" , None , "search" , "foo" ),
160
+ ("^a" , re .I , "search" , "foo" ),
161
+ ("^a" , None , "search" , None ),
162
+ ("^a" , re .I , "search" , None ),
163
+ ("bc" , None , "search" , "foo" ),
164
+ ("bc" , re .I , "search" , "foo" ),
165
+ ("bc" , None , "search" , None ),
166
+ ("bc" , re .I , "search" , None ),
167
+ ("cd$" , None , "search" , "foo" ),
168
+ ("cd$" , re .I , "search" , "foo" ),
169
+ ("cd$" , None , "search" , None ),
170
+ ("cd$" , re .I , "search" , None ),
171
+ (re .compile ("^a" ), None , "search" , "foo" ),
172
+ (re .compile ("^a" , re .I ), None , "search" , "foo" ),
173
+ (re .compile ("^a" ), None , "search" , None ),
174
+ (re .compile ("^a" , re .I ), None , "search" , None ),
175
+ (re .compile ("bc" ), None , "search" , "foo" ),
176
+ (re .compile ("bc" , re .I ), None , "search" , "foo" ),
177
+ (re .compile ("bc" ), None , "search" , None ),
178
+ (re .compile ("bc" , re .I ), None , "search" , None ),
179
+ (re .compile (r"cd$" ), None , "search" , "foo" ),
180
+ (re .compile (r"cd$" , re .I ), None , "search" , "foo" ),
181
+ (re .compile (r"cd$" ), None , "search" , None ),
182
+ (re .compile (r"cd$" , re .I ), None , "search" , None ),
45
183
],
46
184
)
47
- def test_regex_raises (re_pattern , re_flags , test_v , dummy_form , dummy_field ):
185
+ def test_regex_raises (re_pattern , re_flags , re_mode , test_v , dummy_form , dummy_field ):
48
186
"""
49
187
Regex should raise ValidationError if there is no match
50
- Should work for complie regex too
188
+ Should work for compile regex too
51
189
"""
52
- validator = regexp (re_pattern , re_flags ) if re_flags else regexp (re_pattern )
190
+ kwargs = {
191
+ "regex" : re_pattern ,
192
+ "flags" : re_flags if re_flags else 0 ,
193
+ "message" : None ,
194
+ "mode" : re_mode ,
195
+ }
196
+ validator = regexp (** kwargs )
53
197
dummy_field .data = test_v
198
+
54
199
with pytest .raises (ValidationError ):
55
200
validator (dummy_form , dummy_field )
56
201
@@ -62,3 +207,45 @@ def test_regexp_message(dummy_form, dummy_field):
62
207
validator = regexp ("^a" , message = "foo" )
63
208
dummy_field .data = "f"
64
209
assert grab_error_message (validator , dummy_form , dummy_field ) == "foo"
210
+
211
+
212
+ @pytest .mark .parametrize (
213
+ "re_mode" ,
214
+ [
215
+ "MATCH" ,
216
+ "SEARCH" ,
217
+ "FULLMATCH" ,
218
+ "Match" ,
219
+ "Search" ,
220
+ "Fullmatch" ,
221
+ "" ,
222
+ "match " ,
223
+ " match" ,
224
+ "search " ,
225
+ " search" ,
226
+ "fullmatch " ,
227
+ " fullmatch" ,
228
+ None ,
229
+ 1 ,
230
+ 1.0 ,
231
+ True ,
232
+ False ,
233
+ [],
234
+ {},
235
+ (),
236
+ ],
237
+ )
238
+ def test_regex_invalid_mode (dummy_form , dummy_field , re_mode ):
239
+ """
240
+ Regexp validator should raise ValidatorSetupError during an object instantiation,
241
+ if mode is invalid (unsupported).
242
+ """
243
+ with pytest .raises (ValidatorSetupError ) as e :
244
+ regexp ("^a" , mode = re_mode )
245
+
246
+ expected = (
247
+ "Invalid mode value '{}'. "
248
+ "Supported values: search, match, fullmatch"
249
+ ).format (re_mode )
250
+
251
+ assert e .value .args [0 ] == expected
0 commit comments