safeshield 1.2.1__py3-none-any.whl → 1.3.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {safeshield-1.2.1.dist-info → safeshield-1.3.2.dist-info}/METADATA +7 -1
- safeshield-1.3.2.dist-info/RECORD +31 -0
- validator/core/validator.py +3 -3
- validator/database/manager.py +6 -1
- validator/rules/array.py +6 -6
- validator/rules/basic.py +200 -4
- validator/rules/comparison.py +12 -12
- validator/rules/conditional.py +71 -238
- validator/rules/date.py +7 -7
- validator/rules/files.py +5 -5
- validator/rules/format.py +8 -8
- validator/rules/string.py +8 -15
- validator/rules/type.py +10 -3
- validator/rules/utilities.py +78 -153
- validator/services/rule_error_handler.py +221 -24
- safeshield-1.2.1.dist-info/RECORD +0 -31
- {safeshield-1.2.1.dist-info → safeshield-1.3.2.dist-info}/LICENSE +0 -0
- {safeshield-1.2.1.dist-info → safeshield-1.3.2.dist-info}/WHEEL +0 -0
- {safeshield-1.2.1.dist-info → safeshield-1.3.2.dist-info}/top_level.txt +0 -0
validator/rules/conditional.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from .base import ValidationRule
|
|
2
2
|
from typing import Any, Dict, List, Optional, Set, Union, Tuple, Type
|
|
3
3
|
from enum import Enum
|
|
4
|
+
from .basic import RequiredRule, ProhibitedRule, PresentRule, MissingRule, ExcludeRule
|
|
4
5
|
import re
|
|
5
6
|
import inspect
|
|
6
7
|
from collections.abc import Iterable
|
|
@@ -9,7 +10,7 @@ from collections.abc import Iterable
|
|
|
9
10
|
# CONDITIONAL VALIDATION RULES
|
|
10
11
|
# =============================================
|
|
11
12
|
|
|
12
|
-
class RequiredIfRule(
|
|
13
|
+
class RequiredIfRule(RequiredRule):
|
|
13
14
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
14
15
|
if len(params) < 2 or len(params) % 2 != 0:
|
|
15
16
|
return True
|
|
@@ -22,30 +23,30 @@ class RequiredIfRule(ValidationRule):
|
|
|
22
23
|
continue
|
|
23
24
|
|
|
24
25
|
actual_value = self.get_field_value(other_field, '')
|
|
26
|
+
|
|
25
27
|
if actual_value == expected_value:
|
|
26
28
|
condition_met = True
|
|
27
29
|
break
|
|
28
|
-
|
|
30
|
+
|
|
29
31
|
if not condition_met:
|
|
30
32
|
return True
|
|
31
|
-
|
|
32
|
-
return
|
|
33
|
+
|
|
34
|
+
return super().validate(field, value, params)
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if len(params)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
]
|
|
36
|
+
class RequiredUnlessRule(RequiredRule):
|
|
37
|
+
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
38
|
+
if len(params) < 2:
|
|
39
|
+
return False
|
|
40
|
+
|
|
41
|
+
other_field, other_value = params[0], params[1]
|
|
42
|
+
actual_value = self.get_field_value(other_field, '')
|
|
42
43
|
|
|
43
|
-
if
|
|
44
|
-
return
|
|
44
|
+
if actual_value == other_value:
|
|
45
|
+
return True
|
|
45
46
|
|
|
46
|
-
return
|
|
47
|
+
return super().validate(field, value, params)
|
|
47
48
|
|
|
48
|
-
class RequiredAllIfRule(
|
|
49
|
+
class RequiredAllIfRule(RequiredRule):
|
|
49
50
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
50
51
|
if len(params) < 2:
|
|
51
52
|
return False
|
|
@@ -60,77 +61,9 @@ class RequiredAllIfRule(ValidationRule):
|
|
|
60
61
|
if not all_conditions_met:
|
|
61
62
|
return True
|
|
62
63
|
|
|
63
|
-
return
|
|
64
|
-
|
|
65
|
-
def message(self, field: str, params: List[str]) -> str:
|
|
66
|
-
conditions = " AND ".join(f"{f} = {v}" for f, v in zip(params[::2], params[1::2]))
|
|
67
|
-
return f"The :name field is required when ALL conditions are met: {conditions}"
|
|
68
|
-
|
|
69
|
-
class RequiredUnlessRule(ValidationRule):
|
|
70
|
-
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
71
|
-
if len(params) < 2:
|
|
72
|
-
return False
|
|
73
|
-
|
|
74
|
-
other_field, other_value = params[0], params[1]
|
|
75
|
-
actual_value = self.get_field_value(other_field, '')
|
|
76
|
-
|
|
77
|
-
if actual_value == other_value:
|
|
78
|
-
return True
|
|
79
|
-
|
|
80
|
-
return not self.is_empty(value)
|
|
81
|
-
|
|
82
|
-
def message(self, field: str, params: List[str]) -> str:
|
|
83
|
-
return f"The :name field is required unless {params[0]} is {params[1]}."
|
|
84
|
-
|
|
85
|
-
class RequiredWithRule(ValidationRule):
|
|
86
|
-
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
87
|
-
if not params:
|
|
88
|
-
return False
|
|
89
|
-
|
|
90
|
-
if any(f in self.validator.data for f in params):
|
|
91
|
-
return not self.is_empty(value)
|
|
92
|
-
return True
|
|
93
|
-
|
|
94
|
-
def message(self, field: str, params: List[str]) -> str:
|
|
95
|
-
return f"The :name field is required when {', '.join(params)} is present."
|
|
96
|
-
|
|
97
|
-
class RequiredWithAllRule(ValidationRule):
|
|
98
|
-
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
99
|
-
if not params:
|
|
100
|
-
return False
|
|
101
|
-
|
|
102
|
-
if all(f in self.validator.data for f in params):
|
|
103
|
-
return not self.is_empty(value)
|
|
104
|
-
return True
|
|
64
|
+
return super().validate(field, value, params)
|
|
105
65
|
|
|
106
|
-
|
|
107
|
-
return f"The :name field is required when all of {', '.join(params)} are present."
|
|
108
|
-
|
|
109
|
-
class RequiredWithoutRule(ValidationRule):
|
|
110
|
-
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
111
|
-
if not params:
|
|
112
|
-
return False
|
|
113
|
-
|
|
114
|
-
if any(f not in self.validator.data for f in params):
|
|
115
|
-
return not self.is_empty(value)
|
|
116
|
-
return True
|
|
117
|
-
|
|
118
|
-
def message(self, field: str, params: List[str]) -> str:
|
|
119
|
-
return f"The :name field is required when {', '.join(params)} is not present."
|
|
120
|
-
|
|
121
|
-
class RequiredWithoutAllRule(ValidationRule):
|
|
122
|
-
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
123
|
-
if not params:
|
|
124
|
-
return False
|
|
125
|
-
|
|
126
|
-
if all(f not in self.validator.data for f in params):
|
|
127
|
-
return not self.is_empty(value)
|
|
128
|
-
return True
|
|
129
|
-
|
|
130
|
-
def message(self, field: str, params: List[str]) -> str:
|
|
131
|
-
return f"The :name field is required when none of {', '.join(params)} are present."
|
|
132
|
-
|
|
133
|
-
class ProhibitedIfRule(ValidationRule):
|
|
66
|
+
class ProhibitedIfRule(ProhibitedRule):
|
|
134
67
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
135
68
|
if len(params) < 2:
|
|
136
69
|
return False
|
|
@@ -141,12 +74,9 @@ class ProhibitedIfRule(ValidationRule):
|
|
|
141
74
|
if actual_value != other_value:
|
|
142
75
|
return True
|
|
143
76
|
|
|
144
|
-
return
|
|
77
|
+
return super().validate(field, value, params)
|
|
145
78
|
|
|
146
|
-
|
|
147
|
-
return f"The :name field is prohibited when {params[0]} is {params[1]}."
|
|
148
|
-
|
|
149
|
-
class ProhibitedUnlessRule(ValidationRule):
|
|
79
|
+
class ProhibitedUnlessRule(ProhibitedRule):
|
|
150
80
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
151
81
|
if len(params) < 2:
|
|
152
82
|
return False
|
|
@@ -157,176 +87,79 @@ class ProhibitedUnlessRule(ValidationRule):
|
|
|
157
87
|
if actual_value == other_value:
|
|
158
88
|
return True
|
|
159
89
|
|
|
160
|
-
return
|
|
90
|
+
return super().validate(field, value, params)
|
|
161
91
|
|
|
162
|
-
|
|
163
|
-
return f"The :name field is prohibited unless {params[0]} is {params[1]}."
|
|
164
|
-
|
|
165
|
-
class FilledIfRule(ValidationRule):
|
|
92
|
+
class PresentIfRule(PresentRule):
|
|
166
93
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
167
94
|
if len(params) < 2:
|
|
168
95
|
return False
|
|
169
|
-
|
|
170
96
|
other_field, other_value = params[0], params[1]
|
|
171
|
-
actual_value = self.get_field_value(other_field, '')
|
|
172
97
|
|
|
173
|
-
if
|
|
174
|
-
return
|
|
175
|
-
|
|
176
|
-
return value not in ('', None)
|
|
177
|
-
|
|
178
|
-
def message(self, field: str, params: List[str]) -> str:
|
|
179
|
-
return f"The :name field must be filled when {params[0]} is {params[1]}."
|
|
180
|
-
|
|
181
|
-
class RegexRule(ValidationRule):
|
|
182
|
-
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
183
|
-
if not params or not isinstance(value, str):
|
|
184
|
-
return False
|
|
185
|
-
try:
|
|
186
|
-
return bool(re.fullmatch(params[0], value))
|
|
187
|
-
except re.error:
|
|
188
|
-
return False
|
|
189
|
-
|
|
190
|
-
def message(self, field: str, params: List[str]) -> str:
|
|
191
|
-
return f"The :name format is invalid."
|
|
192
|
-
|
|
193
|
-
class NotRegexRule(ValidationRule):
|
|
194
|
-
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
195
|
-
if not params or not isinstance(value, str):
|
|
196
|
-
return True
|
|
197
|
-
print(not bool(re.search(params[0], value)))
|
|
198
|
-
try:
|
|
199
|
-
return not bool(re.search(params[0], value))
|
|
200
|
-
except re.error:
|
|
201
|
-
return True
|
|
202
|
-
|
|
203
|
-
def message(self, field: str, params: List[str]) -> str:
|
|
204
|
-
return f"The :name format is invalid."
|
|
205
|
-
|
|
206
|
-
class InRule(ValidationRule):
|
|
207
|
-
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
208
|
-
allowed_values = self._parse_option_values(field, params)
|
|
209
|
-
return (str(value) in allowed_values or value in allowed_values)
|
|
210
|
-
|
|
211
|
-
def message(self, field: str, params: List[str]) -> str:
|
|
212
|
-
allowed_values = self._parse_option_values(field, params)
|
|
213
|
-
return f"The selected :name must be in : {', '.join(map(str, allowed_values))}"
|
|
214
|
-
|
|
215
|
-
class NotInRule(ValidationRule):
|
|
216
|
-
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
217
|
-
not_allowed_values = self._parse_option_values(field, params)
|
|
218
|
-
return str(value) not in not_allowed_values
|
|
219
|
-
|
|
220
|
-
def message(self, field: str, params: List[str]) -> str:
|
|
221
|
-
not_allowed_values = self._parse_option_values(field, params)
|
|
222
|
-
return f"The selected :name must be not in : {', '.join(map(str, not_allowed_values))}"
|
|
98
|
+
if self.get_field_value(other_field, None) == other_value:
|
|
99
|
+
return super().validate(field, value, params)
|
|
100
|
+
return True
|
|
223
101
|
|
|
224
|
-
class
|
|
225
|
-
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
226
|
-
allowed_values = self._parse_option_values(field, params)
|
|
227
|
-
return (str(value) in allowed_values or value in allowed_values)
|
|
228
|
-
|
|
229
|
-
def message(self, field: str, params: List[str]) -> str:
|
|
230
|
-
allowed_values = self._parse_option_values(field, params)
|
|
231
|
-
return f"The :name must be one of: {', '.join(map(str, allowed_values))}"
|
|
232
|
-
|
|
233
|
-
class UniqueRule(ValidationRule):
|
|
102
|
+
class PresentUnlessRule(PresentRule):
|
|
234
103
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
235
|
-
if
|
|
104
|
+
if len(params) < 2:
|
|
236
105
|
return False
|
|
237
|
-
|
|
238
|
-
table = params[0]
|
|
239
|
-
column = field if len(params) == 1 else params[1]
|
|
106
|
+
other_field, other_value = params[0], params[1]
|
|
240
107
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
ignore_id = None
|
|
244
|
-
if len(params) > 2 and params[2].startswith('ignore:'):
|
|
245
|
-
ignore_field = params[2].split(':')[1]
|
|
246
|
-
ignore_id = self.get_field_value(ignore_field)
|
|
247
|
-
return self.validator.db_manager.is_unique(table, column, value, ignore_id)
|
|
248
|
-
except Exception as e:
|
|
249
|
-
print(f"Database error in UniqueRule: {e}")
|
|
250
|
-
return False
|
|
251
|
-
|
|
252
|
-
def message(self, field: str, params: List[str]) -> str:
|
|
253
|
-
return f"The :name has already been taken."
|
|
254
|
-
|
|
255
|
-
class ExistsRule(ValidationRule):
|
|
256
|
-
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
257
|
-
if not params or not hasattr(self.validator, 'db_manager') or not self.validator.db_manager:
|
|
258
|
-
return False
|
|
259
|
-
|
|
260
|
-
table = params[0]
|
|
261
|
-
column = field if len(params) == 1 else params[1]
|
|
108
|
+
if self.get_field_value(other_field, None) != other_value:
|
|
109
|
+
return super().validate(field, value, params)
|
|
262
110
|
|
|
263
|
-
|
|
264
|
-
return self.validator.db_manager.exists(table, column, value)
|
|
265
|
-
except Exception as e:
|
|
266
|
-
print(f"Database error in ExistsRule: {e}")
|
|
267
|
-
return False
|
|
268
|
-
|
|
269
|
-
def message(self, field: str, params: List[str]) -> str:
|
|
270
|
-
return f"The selected :name is invalid."
|
|
271
|
-
|
|
272
|
-
class ConfirmedRule(ValidationRule):
|
|
273
|
-
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
274
|
-
confirmation_field = f"{field}_confirmation"
|
|
111
|
+
return True
|
|
275
112
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
def message(self, field: str, params: List[str]) -> str:
|
|
279
|
-
return f"The :name confirmation does not match."
|
|
280
|
-
|
|
281
|
-
class SameRule(ValidationRule):
|
|
113
|
+
class MissingIfRule(MissingRule):
|
|
282
114
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
283
|
-
if
|
|
115
|
+
if len(params) < 2:
|
|
284
116
|
return False
|
|
285
|
-
|
|
117
|
+
other_field, other_value = params[0], params[1]
|
|
118
|
+
|
|
119
|
+
if self.get_field_value(other_field, None) == other_value:
|
|
120
|
+
return super().validate(field, value, params)
|
|
121
|
+
|
|
122
|
+
return True
|
|
286
123
|
|
|
287
|
-
|
|
288
|
-
return f"The :name and {params[0]} must match."
|
|
289
|
-
|
|
290
|
-
class DifferentRule(ValidationRule):
|
|
124
|
+
class MissingUnlessRule(MissingRule):
|
|
291
125
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
292
|
-
if
|
|
126
|
+
if len(params) < 2:
|
|
293
127
|
return False
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
return f"The :name and {params[0]} must be different."
|
|
128
|
+
other_field, other_value = params[0], params[1]
|
|
129
|
+
if self.get_field_value(other_field, None) != other_value:
|
|
130
|
+
return super().validate(field, value, params)
|
|
298
131
|
|
|
299
|
-
|
|
300
|
-
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
301
|
-
if isinstance(value, str):
|
|
302
|
-
return value.lower() in ['yes', 'on', '1', 'true']
|
|
303
|
-
if isinstance(value, int):
|
|
304
|
-
return value == 1
|
|
305
|
-
if isinstance(value, bool):
|
|
306
|
-
return value
|
|
307
|
-
return False
|
|
132
|
+
return True
|
|
308
133
|
|
|
309
|
-
|
|
310
|
-
return f"The :name must be accepted."
|
|
311
|
-
|
|
312
|
-
class DeclinedRule(ValidationRule):
|
|
134
|
+
class ExcludeIfRule(ExcludeRule):
|
|
313
135
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
136
|
+
conditions = [(f.strip(), v.strip()) for f, v in zip(params[::2], params[1::2])]
|
|
137
|
+
|
|
138
|
+
all_conditions_met = all(
|
|
139
|
+
self.get_field_value(f) == v
|
|
140
|
+
for f, v in conditions
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
if all_conditions_met:
|
|
144
|
+
return super().validate(field, value, params)
|
|
145
|
+
return True
|
|
321
146
|
|
|
322
147
|
def message(self, field: str, params: List[str]) -> str:
|
|
323
|
-
return f"The :
|
|
324
|
-
|
|
148
|
+
return f"The :attribute field is excluded when {params[0]} is {params[1]}."
|
|
325
149
|
|
|
326
|
-
class
|
|
150
|
+
class ExcludeUnlessRule(ExcludeRule):
|
|
327
151
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
328
|
-
|
|
152
|
+
conditions = [(f.strip(), v.strip()) for f, v in zip(params[::2], params[1::2])]
|
|
153
|
+
|
|
154
|
+
all_conditions_met = all(
|
|
155
|
+
self.get_field_value(f) == v
|
|
156
|
+
for f, v in conditions
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
if not all_conditions_met:
|
|
160
|
+
return super().validate(field, value, params)
|
|
161
|
+
|
|
329
162
|
return True
|
|
330
|
-
|
|
163
|
+
|
|
331
164
|
def message(self, field: str, params: List[str]) -> str:
|
|
332
|
-
return ""
|
|
165
|
+
return f"The :attribute field is excluded unless {params[0]} is {params[1]}."
|
validator/rules/date.py
CHANGED
|
@@ -15,7 +15,7 @@ class DateRule(ValidationRule):
|
|
|
15
15
|
return False
|
|
16
16
|
|
|
17
17
|
def message(self, field: str, params: List[str]) -> str:
|
|
18
|
-
return f"The :
|
|
18
|
+
return f"The :attribute is not a valid date."
|
|
19
19
|
|
|
20
20
|
class DateEqualsRule(ValidationRule):
|
|
21
21
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -35,7 +35,7 @@ class DateEqualsRule(ValidationRule):
|
|
|
35
35
|
return False
|
|
36
36
|
|
|
37
37
|
def message(self, field: str, params: List[str]) -> str:
|
|
38
|
-
return f"The :
|
|
38
|
+
return f"The :attribute must be equal to {params[0]}."
|
|
39
39
|
|
|
40
40
|
class AfterRule(ValidationRule):
|
|
41
41
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -61,7 +61,7 @@ class AfterRule(ValidationRule):
|
|
|
61
61
|
return False
|
|
62
62
|
|
|
63
63
|
def message(self, field: str, params: List[str]) -> str:
|
|
64
|
-
return f"The :
|
|
64
|
+
return f"The :attribute must be after {params[0]}"
|
|
65
65
|
|
|
66
66
|
class AfterOrEqualRule(ValidationRule):
|
|
67
67
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -85,7 +85,7 @@ class AfterOrEqualRule(ValidationRule):
|
|
|
85
85
|
return False
|
|
86
86
|
|
|
87
87
|
def message(self, field: str, params: List[str]) -> str:
|
|
88
|
-
return f"The :
|
|
88
|
+
return f"The :attribute must be after or equal to {params[0]}"
|
|
89
89
|
|
|
90
90
|
class BeforeRule(ValidationRule):
|
|
91
91
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -111,7 +111,7 @@ class BeforeRule(ValidationRule):
|
|
|
111
111
|
return False
|
|
112
112
|
|
|
113
113
|
def message(self, field: str, params: List[str]) -> str:
|
|
114
|
-
return f"The :
|
|
114
|
+
return f"The :attribute must be before {params[0]}"
|
|
115
115
|
|
|
116
116
|
class BeforeOrEqualRule(ValidationRule):
|
|
117
117
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -137,7 +137,7 @@ class BeforeOrEqualRule(ValidationRule):
|
|
|
137
137
|
return False
|
|
138
138
|
|
|
139
139
|
def message(self, field: str, params: List[str]) -> str:
|
|
140
|
-
return f"The :
|
|
140
|
+
return f"The :attribute must be before or equal to {params[0]}"
|
|
141
141
|
|
|
142
142
|
class DateFormatRule(ValidationRule):
|
|
143
143
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -151,4 +151,4 @@ class DateFormatRule(ValidationRule):
|
|
|
151
151
|
return False
|
|
152
152
|
|
|
153
153
|
def message(self, field: str, params: List[str]) -> str:
|
|
154
|
-
return f"The :
|
|
154
|
+
return f"The :attribute must match the format {params[0]}"
|
validator/rules/files.py
CHANGED
|
@@ -28,7 +28,7 @@ class FileRule(ValidationRule):
|
|
|
28
28
|
return False
|
|
29
29
|
|
|
30
30
|
def message(self, field: str, params: List[str]) -> str:
|
|
31
|
-
return f"The
|
|
31
|
+
return f"The :attribute must be a valid file"
|
|
32
32
|
|
|
33
33
|
class DimensionsRule(ValidationRule):
|
|
34
34
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -99,7 +99,7 @@ class DimensionsRule(ValidationRule):
|
|
|
99
99
|
if max_rules:
|
|
100
100
|
messages.append(f"maximum {max_rules[0][4:]}")
|
|
101
101
|
|
|
102
|
-
return f"Image
|
|
102
|
+
return f"Image :attribute dimensions must be {' and '.join(messages)}"
|
|
103
103
|
|
|
104
104
|
class ExtensionsRule(ValidationRule):
|
|
105
105
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -118,7 +118,7 @@ class ExtensionsRule(ValidationRule):
|
|
|
118
118
|
return ext in [e.lower().strip() for e in params]
|
|
119
119
|
|
|
120
120
|
def message(self, field: str, params: List[str]) -> str:
|
|
121
|
-
return f"File
|
|
121
|
+
return f"File :attribute must have one of these extensions: {', '.join(params)}"
|
|
122
122
|
|
|
123
123
|
class ImageRule(ValidationRule):
|
|
124
124
|
VALID_EXTENSIONS = {'jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'}
|
|
@@ -146,7 +146,7 @@ class ImageRule(ValidationRule):
|
|
|
146
146
|
return True
|
|
147
147
|
|
|
148
148
|
def message(self, field: str, params: List[str]) -> str:
|
|
149
|
-
return f"The
|
|
149
|
+
return f"The :attribute must be a valid image file (JPEG, PNG, GIF, BMP, or WebP)"
|
|
150
150
|
|
|
151
151
|
class MimeTypesRule(ValidationRule):
|
|
152
152
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -164,4 +164,4 @@ class MimeTypesRule(ValidationRule):
|
|
|
164
164
|
return False
|
|
165
165
|
|
|
166
166
|
def message(self, field: str, params: List[str]) -> str:
|
|
167
|
-
return f"File
|
|
167
|
+
return f"File :attribute must be one of these types: {', '.join(params)}"
|
validator/rules/format.py
CHANGED
|
@@ -17,7 +17,7 @@ class EmailRule(ValidationRule):
|
|
|
17
17
|
return bool(re.match(r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$", value))
|
|
18
18
|
|
|
19
19
|
def message(self, field: str, params: List[str]) -> str:
|
|
20
|
-
return f"The :
|
|
20
|
+
return f"The :attribute must be a valid email address."
|
|
21
21
|
|
|
22
22
|
class UrlRule(ValidationRule):
|
|
23
23
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -32,7 +32,7 @@ class UrlRule(ValidationRule):
|
|
|
32
32
|
))
|
|
33
33
|
|
|
34
34
|
def message(self, field: str, params: List[str]) -> str:
|
|
35
|
-
return f"The :
|
|
35
|
+
return f"The :attribute must be a valid URL."
|
|
36
36
|
|
|
37
37
|
class JsonRule(ValidationRule):
|
|
38
38
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -45,7 +45,7 @@ class JsonRule(ValidationRule):
|
|
|
45
45
|
return False
|
|
46
46
|
|
|
47
47
|
def message(self, field: str, params: List[str]) -> str:
|
|
48
|
-
return f"The :
|
|
48
|
+
return f"The :attribute must be a valid JSON string."
|
|
49
49
|
|
|
50
50
|
class UuidRule(ValidationRule):
|
|
51
51
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -58,7 +58,7 @@ class UuidRule(ValidationRule):
|
|
|
58
58
|
return False
|
|
59
59
|
|
|
60
60
|
def message(self, field: str, params: List[str]) -> str:
|
|
61
|
-
return f"The :
|
|
61
|
+
return f"The :attribute must be a valid UUID."
|
|
62
62
|
|
|
63
63
|
class UlidRule(ValidationRule):
|
|
64
64
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -67,7 +67,7 @@ class UlidRule(ValidationRule):
|
|
|
67
67
|
return bool(re.match(r'^[0-9A-HJKMNP-TV-Z]{26}$', value))
|
|
68
68
|
|
|
69
69
|
def message(self, field: str, params: List[str]) -> str:
|
|
70
|
-
return f"The :
|
|
70
|
+
return f"The :attribute must be a valid ULID."
|
|
71
71
|
|
|
72
72
|
class IpRule(ValidationRule):
|
|
73
73
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -80,7 +80,7 @@ class IpRule(ValidationRule):
|
|
|
80
80
|
return False
|
|
81
81
|
|
|
82
82
|
def message(self, field: str, params: List[str]) -> str:
|
|
83
|
-
return f"The :
|
|
83
|
+
return f"The :attribute must be a valid IP address."
|
|
84
84
|
|
|
85
85
|
class TimezoneRule(ValidationRule):
|
|
86
86
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -93,7 +93,7 @@ class TimezoneRule(ValidationRule):
|
|
|
93
93
|
return False
|
|
94
94
|
|
|
95
95
|
def message(self, field: str, params: List[str]) -> str:
|
|
96
|
-
return f"The :
|
|
96
|
+
return f"The :attribute must be a valid timezone."
|
|
97
97
|
|
|
98
98
|
class HexRule(ValidationRule):
|
|
99
99
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -102,4 +102,4 @@ class HexRule(ValidationRule):
|
|
|
102
102
|
return bool(re.match(r'^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$', value))
|
|
103
103
|
|
|
104
104
|
def message(self, field: str, params: List[str]) -> str:
|
|
105
|
-
return f"The :
|
|
105
|
+
return f"The :attribute must be a valid hexadecimal color code."
|
validator/rules/string.py
CHANGED
|
@@ -6,54 +6,47 @@ import re
|
|
|
6
6
|
# STRING VALIDATION RULES
|
|
7
7
|
# =============================================
|
|
8
8
|
|
|
9
|
-
class StringRule(ValidationRule):
|
|
10
|
-
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
11
|
-
return isinstance(value, str)
|
|
12
|
-
|
|
13
|
-
def message(self, field: str, params: List[str]) -> str:
|
|
14
|
-
return f"The :name must be a string."
|
|
15
|
-
|
|
16
9
|
class AlphaRule(ValidationRule):
|
|
17
10
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
18
11
|
return isinstance(value, str) and value.isalpha()
|
|
19
12
|
|
|
20
13
|
def message(self, field: str, params: List[str]) -> str:
|
|
21
|
-
return f"The :
|
|
14
|
+
return f"The :attribute may only contain letters."
|
|
22
15
|
|
|
23
16
|
class AlphaDashRule(ValidationRule):
|
|
24
17
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
25
18
|
return isinstance(value, str) and bool(re.match(r'^[a-zA-Z0-9_-]+$', value))
|
|
26
19
|
|
|
27
20
|
def message(self, field: str, params: List[str]) -> str:
|
|
28
|
-
return f"The :
|
|
21
|
+
return f"The :attribute may only contain letters, numbers, dashes and underscores."
|
|
29
22
|
|
|
30
23
|
class AlphaNumRule(ValidationRule):
|
|
31
24
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
32
25
|
return isinstance(value, str) and value.isalnum()
|
|
33
26
|
|
|
34
27
|
def message(self, field: str, params: List[str]) -> str:
|
|
35
|
-
return f"The :
|
|
28
|
+
return f"The :attribute may only contain letters and numbers."
|
|
36
29
|
|
|
37
30
|
class UppercaseRule(ValidationRule):
|
|
38
31
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
39
32
|
return isinstance(value, str) and value == value.upper()
|
|
40
33
|
|
|
41
34
|
def message(self, field: str, params: List[str]) -> str:
|
|
42
|
-
return f"The :
|
|
35
|
+
return f"The :attribute must be uppercase."
|
|
43
36
|
|
|
44
37
|
class LowercaseRule(ValidationRule):
|
|
45
38
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
46
39
|
return isinstance(value, str) and value == value.lower()
|
|
47
40
|
|
|
48
41
|
def message(self, field: str, params: List[str]) -> str:
|
|
49
|
-
return f"The :
|
|
42
|
+
return f"The :attribute must be lowercase."
|
|
50
43
|
|
|
51
44
|
class AsciiRule(ValidationRule):
|
|
52
45
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
53
46
|
return isinstance(value, str) and all(ord(c) < 128 for c in value)
|
|
54
47
|
|
|
55
48
|
def message(self, field: str, params: List[str]) -> str:
|
|
56
|
-
return f"The :
|
|
49
|
+
return f"The :attribute must only contain ASCII characters."
|
|
57
50
|
|
|
58
51
|
class StartsWithRule(ValidationRule):
|
|
59
52
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -62,7 +55,7 @@ class StartsWithRule(ValidationRule):
|
|
|
62
55
|
return any(value.startswith(p) for p in params)
|
|
63
56
|
|
|
64
57
|
def message(self, field: str, params: List[str]) -> str:
|
|
65
|
-
return f"The :
|
|
58
|
+
return f"The :attribute must start with one of the following: {', '.join(params)}."
|
|
66
59
|
|
|
67
60
|
class EndsWithRule(ValidationRule):
|
|
68
61
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -71,4 +64,4 @@ class EndsWithRule(ValidationRule):
|
|
|
71
64
|
return any(value.endswith(p) for p in params)
|
|
72
65
|
|
|
73
66
|
def message(self, field: str, params: List[str]) -> str:
|
|
74
|
-
return f"The :
|
|
67
|
+
return f"The :attribute must end with one of the following: {', '.join(params)}."
|
validator/rules/type.py
CHANGED
|
@@ -6,6 +6,13 @@ from datetime import datetime
|
|
|
6
6
|
# TYPE DATA VALIDATION RULES
|
|
7
7
|
# =============================================
|
|
8
8
|
|
|
9
|
+
class StringRule(ValidationRule):
|
|
10
|
+
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
11
|
+
return isinstance(value, str)
|
|
12
|
+
|
|
13
|
+
def message(self, field: str, params: List[str]) -> str:
|
|
14
|
+
return f"The :attribute must be a string."
|
|
15
|
+
|
|
9
16
|
class NumericRule(ValidationRule):
|
|
10
17
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
11
18
|
if isinstance(value, (int, float)):
|
|
@@ -15,7 +22,7 @@ class NumericRule(ValidationRule):
|
|
|
15
22
|
return value.replace('.', '', 1).isdigit()
|
|
16
23
|
|
|
17
24
|
def message(self, field: str, params: List[str]) -> str:
|
|
18
|
-
return f"The :
|
|
25
|
+
return f"The :attribute must be a number."
|
|
19
26
|
|
|
20
27
|
class IntegerRule(ValidationRule):
|
|
21
28
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -26,7 +33,7 @@ class IntegerRule(ValidationRule):
|
|
|
26
33
|
return value.isdigit()
|
|
27
34
|
|
|
28
35
|
def message(self, field: str, params: List[str]) -> str:
|
|
29
|
-
return f"The :
|
|
36
|
+
return f"The :attribute must be an integer."
|
|
30
37
|
|
|
31
38
|
class BooleanRule(ValidationRule):
|
|
32
39
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -39,4 +46,4 @@ class BooleanRule(ValidationRule):
|
|
|
39
46
|
return False
|
|
40
47
|
|
|
41
48
|
def message(self, field: str, params: List[str]) -> str:
|
|
42
|
-
return f"The :
|
|
49
|
+
return f"The :attribute field must be true or false."
|