safeshield 1.2.2__py3-none-any.whl → 1.4.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.
@@ -0,0 +1,188 @@
1
+ from .base import Rule
2
+ from typing import Any, Dict, List, Optional, Set, Union, Tuple, Type
3
+ import decimal
4
+
5
+ class NumericRule(Rule):
6
+ def validate(self, field: str, value: Any, params: List[str]) -> bool:
7
+ if isinstance(value, (int, float)):
8
+ return True
9
+ if not isinstance(value, str):
10
+ return False
11
+ return value.replace('.', '', 1).isdigit()
12
+
13
+ def message(self, field: str, params: List[str]) -> str:
14
+ return f"The :attribute must be a number."
15
+
16
+ class IntegerRule(Rule):
17
+ def validate(self, field: str, value: Any, params: List[str]) -> bool:
18
+ if isinstance(value, int):
19
+ return True
20
+ if not isinstance(value, str):
21
+ return False
22
+ return value.isdigit()
23
+
24
+ def message(self, field: str, params: List[str]) -> str:
25
+ return f"The :attribute must be an integer."
26
+
27
+ class DigitsRule(Rule):
28
+ def validate(self, field: str, value: Any, params: List[str]) -> bool:
29
+ if not params or not isinstance(value, str):
30
+ return False
31
+
32
+ try:
33
+ digits = int(params[0])
34
+ except ValueError:
35
+ return False
36
+
37
+ return value.isdigit() and len(value) == digits
38
+
39
+ def message(self, field: str, params: List[str]) -> str:
40
+ return f"The :attribute must be {params[0]} digits."
41
+
42
+ class DigitsBetweenRule(Rule):
43
+ def validate(self, field: str, value: Any, params: List[str]) -> bool:
44
+ if len(params) < 2 or not isinstance(value, str):
45
+ return False
46
+
47
+ try:
48
+ min_digits = int(params[0])
49
+ max_digits = int(params[1])
50
+ except ValueError:
51
+ return False
52
+
53
+ return value.isdigit() and min_digits <= len(value) <= max_digits
54
+
55
+ def message(self, field: str, params: List[str]) -> str:
56
+ return f"The :attribute must be between {params[0]} and {params[1]} digits."
57
+
58
+ class DecimalRule(Rule):
59
+ def validate(self, field: str, value: Any, params: List[str]) -> bool:
60
+ try:
61
+ decimal.Decimal(str(value))
62
+ return True
63
+ except (decimal.InvalidOperation, TypeError, ValueError):
64
+ return False
65
+
66
+ def message(self, field: str, params: List[str]) -> str:
67
+ return "The :attribute must be a decimal number."
68
+
69
+ class GreaterThanRule(Rule):
70
+ _name = 'gt'
71
+
72
+ def validate(self, field: str, value: Any, params: List[str]) -> bool:
73
+ if len(params) < 1:
74
+ return False
75
+
76
+ try:
77
+ threshold = decimal.Decimal(params[0])
78
+ numeric_value = decimal.Decimal(str(value))
79
+ return numeric_value > threshold
80
+ except (decimal.InvalidOperation, TypeError, ValueError):
81
+ return False
82
+
83
+ def message(self, field: str, params: List[str]) -> str:
84
+ return f"The :attribute must be greater than {params[0]}."
85
+
86
+ class GreaterThanOrEqualRule(Rule):
87
+ _name = 'gte'
88
+
89
+ def validate(self, field: str, value: Any, params: List[str]) -> bool:
90
+ if len(params) < 1:
91
+ return False
92
+
93
+ try:
94
+ threshold = decimal.Decimal(params[0])
95
+ numeric_value = decimal.Decimal(str(value))
96
+ return numeric_value >= threshold
97
+ except (decimal.InvalidOperation, TypeError, ValueError):
98
+ return False
99
+
100
+ def message(self, field: str, params: List[str]) -> str:
101
+ return f"The :attribute must be greater than or equal to {params[0]}."
102
+
103
+ class LessThanRule(Rule):
104
+ _name = 'lt'
105
+
106
+ def validate(self, field: str, value: Any, params: List[str]) -> bool:
107
+ if len(params) < 1:
108
+ return False
109
+
110
+ try:
111
+ threshold = decimal.Decimal(params[0])
112
+ numeric_value = decimal.Decimal(str(value))
113
+ return numeric_value < threshold
114
+ except (decimal.InvalidOperation, TypeError, ValueError):
115
+ return False
116
+
117
+ def message(self, field: str, params: List[str]) -> str:
118
+ return f"The :attribute must be less than {params[0]}."
119
+
120
+ class LessThanOrEqualRule(Rule):
121
+ _name = 'lte'
122
+
123
+ def validate(self, field: str, value: Any, params: List[str]) -> bool:
124
+ if len(params) < 1:
125
+ return False
126
+
127
+ try:
128
+ threshold = decimal.Decimal(params[0])
129
+ numeric_value = decimal.Decimal(str(value))
130
+ return numeric_value <= threshold
131
+ except (decimal.InvalidOperation, TypeError, ValueError):
132
+ return False
133
+
134
+ def message(self, field: str, params: List[str]) -> str:
135
+ return f"The :attribute must be less than or equal to {params[0]}."
136
+
137
+ class MaxDigitsRule(Rule):
138
+ def validate(self, field: str, value: Any, params: List[str]) -> bool:
139
+ if len(params) < 1:
140
+ return False
141
+
142
+ try:
143
+ max_digits = int(params[0])
144
+ numeric_value = decimal.Decimal(str(value))
145
+ str_value = str(numeric_value).replace("-", "")
146
+ if '.' in str_value:
147
+ str_value = str_value.replace(".", "")
148
+ return len(str_value) <= max_digits
149
+ except (decimal.InvalidOperation, TypeError, ValueError):
150
+ return False
151
+
152
+ def message(self, field: str, params: List[str]) -> str:
153
+ return f"The :attribute must not exceed {params[0]} digits."
154
+
155
+ class MinDigitsRule(Rule):
156
+ def validate(self, field: str, value: Any, params: List[str]) -> bool:
157
+ if len(params) < 1:
158
+ return False
159
+
160
+ try:
161
+ min_digits = int(params[0])
162
+ numeric_value = decimal.Decimal(str(value))
163
+ str_value = str(numeric_value).replace("-", "")
164
+ if '.' in str_value:
165
+ str_value = str_value.replace(".", "")
166
+ return len(str_value) >= min_digits
167
+ except (decimal.InvalidOperation, TypeError, ValueError):
168
+ return False
169
+
170
+ def message(self, field: str, params: List[str]) -> str:
171
+ return f"The :attribute must have at least {params[0]} digits."
172
+
173
+ class MultipleOfRule(Rule):
174
+ def validate(self, field: str, value: Any, params: List[str]) -> bool:
175
+ if not params:
176
+ return False
177
+
178
+ try:
179
+ divisor = float(params[0])
180
+ if divisor == 0:
181
+ return False
182
+ num = float(value)
183
+ return num % divisor == 0
184
+ except (ValueError, TypeError):
185
+ return False
186
+
187
+ def message(self, field: str, params: List[str]) -> str:
188
+ return f"The :attribute must be a multiple of {params[0]}."
validator/rules/string.py CHANGED
@@ -1,4 +1,4 @@
1
- from .base import ValidationRule
1
+ from .base import Rule
2
2
  from typing import Any, Dict, List, Optional, Set, Union, Tuple, Type
3
3
  import re
4
4
 
@@ -6,69 +6,121 @@ import re
6
6
  # STRING VALIDATION RULES
7
7
  # =============================================
8
8
 
9
- class StringRule(ValidationRule):
9
+ class StringRule(Rule):
10
10
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
11
11
  return isinstance(value, str)
12
12
 
13
13
  def message(self, field: str, params: List[str]) -> str:
14
- return f"The :name must be a string."
14
+ return f"The :attribute must be a string."
15
15
 
16
- class AlphaRule(ValidationRule):
16
+ class AlphaRule(Rule):
17
17
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
18
18
  return isinstance(value, str) and value.isalpha()
19
19
 
20
20
  def message(self, field: str, params: List[str]) -> str:
21
- return f"The :name may only contain letters."
21
+ return f"The :attribute may only contain letters."
22
22
 
23
- class AlphaDashRule(ValidationRule):
23
+ class AlphaDashRule(Rule):
24
24
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
25
25
  return isinstance(value, str) and bool(re.match(r'^[a-zA-Z0-9_-]+$', value))
26
26
 
27
27
  def message(self, field: str, params: List[str]) -> str:
28
- return f"The :name may only contain letters, numbers, dashes and underscores."
28
+ return f"The :attribute may only contain letters, numbers, dashes and underscores."
29
29
 
30
- class AlphaNumRule(ValidationRule):
30
+ class AlphaNumRule(Rule):
31
31
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
32
32
  return isinstance(value, str) and value.isalnum()
33
33
 
34
34
  def message(self, field: str, params: List[str]) -> str:
35
- return f"The :name may only contain letters and numbers."
35
+ return f"The :attribute may only contain letters and numbers."
36
36
 
37
- class UppercaseRule(ValidationRule):
37
+ class UppercaseRule(Rule):
38
38
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
39
39
  return isinstance(value, str) and value == value.upper()
40
40
 
41
41
  def message(self, field: str, params: List[str]) -> str:
42
- return f"The :name must be uppercase."
42
+ return f"The :attribute must be uppercase."
43
43
 
44
- class LowercaseRule(ValidationRule):
44
+ class LowercaseRule(Rule):
45
45
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
46
46
  return isinstance(value, str) and value == value.lower()
47
47
 
48
48
  def message(self, field: str, params: List[str]) -> str:
49
- return f"The :name must be lowercase."
49
+ return f"The :attribute must be lowercase."
50
50
 
51
- class AsciiRule(ValidationRule):
51
+ class AsciiRule(Rule):
52
52
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
53
53
  return isinstance(value, str) and all(ord(c) < 128 for c in value)
54
54
 
55
55
  def message(self, field: str, params: List[str]) -> str:
56
- return f"The :name must only contain ASCII characters."
56
+ return f"The :attribute must only contain ASCII characters."
57
57
 
58
- class StartsWithRule(ValidationRule):
58
+ class StartsWithRule(Rule):
59
59
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
60
60
  if not isinstance(value, str):
61
61
  return False
62
62
  return any(value.startswith(p) for p in params)
63
63
 
64
64
  def message(self, field: str, params: List[str]) -> str:
65
- return f"The :name must start with one of the following: {', '.join(params)}."
65
+ return f"The :attribute must start with one of the following: {', '.join(params)}."
66
+
67
+ class DoesntStartWithRule(Rule):
68
+ def validate(self, field: str, value: Any, params: List[str]) -> bool:
69
+ if not isinstance(value, str) or not params:
70
+ return False
71
+ return all(not value.startswith(prefix) for prefix in params)
72
+
73
+ def message(self, field: str, params: List[str]) -> str:
74
+ return f"The :attribute must not start with any of: {', '.join(params)}"
66
75
 
67
- class EndsWithRule(ValidationRule):
76
+ class EndsWithRule(Rule):
68
77
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
69
78
  if not isinstance(value, str):
70
79
  return False
71
80
  return any(value.endswith(p) for p in params)
72
81
 
73
82
  def message(self, field: str, params: List[str]) -> str:
74
- return f"The :name must end with one of the following: {', '.join(params)}."
83
+ return f"The :attribute must end with one of the following: {', '.join(params)}."
84
+
85
+ class DoesntEndWithRule(Rule):
86
+ def validate(self, field: str, value: Any, params: List[str]) -> bool:
87
+ if not isinstance(value, str) or not params:
88
+ return False
89
+ return all(not value.endswith(suffix) for suffix in params)
90
+
91
+ def message(self, field: str, params: List[str]) -> str:
92
+ return f"The :attribute must not end with any of: {', '.join(params)}"
93
+
94
+ class ConfirmedRule(Rule):
95
+ def validate(self, field: str, value: Any, params: List[str]) -> bool:
96
+ confirmation_field = f"{field}_confirmation"
97
+
98
+ return value == self.get_field_value(confirmation_field, '')
99
+
100
+ def message(self, field: str, params: List[str]) -> str:
101
+ return f"The :attribute confirmation does not match."
102
+
103
+ class RegexRule(Rule):
104
+ def validate(self, field: str, value: Any, params: List[str]) -> bool:
105
+ if not params or not isinstance(value, str):
106
+ return False
107
+ try:
108
+ return bool(re.fullmatch(params[0], value))
109
+ except re.error:
110
+ return False
111
+
112
+ def message(self, field: str, params: List[str]) -> str:
113
+ return f"The :attribute format is invalid."
114
+
115
+ class NotRegexRule(Rule):
116
+ def validate(self, field: str, value: Any, params: List[str]) -> bool:
117
+ if not params or not isinstance(value, str):
118
+ return True
119
+ print(not bool(re.search(params[0], value)))
120
+ try:
121
+ return not bool(re.search(params[0], value))
122
+ except re.error:
123
+ return True
124
+
125
+ def message(self, field: str, params: List[str]) -> str:
126
+ return f"The :attribute format is invalid."