safeshield 1.6.1__py3-none-any.whl → 1.6.4__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.6.1.dist-info → safeshield-1.6.4.dist-info}/METADATA +29 -13
- {safeshield-1.6.1.dist-info → safeshield-1.6.4.dist-info}/RECORD +10 -10
- {safeshield-1.6.1.dist-info → safeshield-1.6.4.dist-info}/WHEEL +1 -1
- validator/core/validator.py +4 -1
- validator/database/manager.py +2 -15
- validator/rules/base.py +0 -3
- validator/rules/boolean.py +2 -2
- validator/rules/utilities.py +9 -6
- {safeshield-1.6.1.dist-info → safeshield-1.6.4.dist-info/licenses}/LICENSE +0 -0
- {safeshield-1.6.1.dist-info → safeshield-1.6.4.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: safeshield
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.4
|
|
4
4
|
Summary: Library for Help Validation Control
|
|
5
5
|
Home-page: https://github.com/WunsunTarniho/py-guard
|
|
6
6
|
Author: Wunsun Tarniho
|
|
@@ -20,12 +20,23 @@ Requires-Dist: mysql-connector-python==8.0.33
|
|
|
20
20
|
Requires-Dist: Pillow==11.2.1
|
|
21
21
|
Requires-Dist: psycopg2-binary==2.9.9
|
|
22
22
|
Requires-Dist: python-dotenv==1.1.1
|
|
23
|
-
Requires-Dist:
|
|
24
|
-
Requires-Dist: setuptools==
|
|
23
|
+
Requires-Dist: python_dateutil==2.9.0.post0
|
|
24
|
+
Requires-Dist: setuptools==75.8.2
|
|
25
25
|
Requires-Dist: SQLAlchemy==2.0.41
|
|
26
26
|
Requires-Dist: Werkzeug==1.0.1
|
|
27
27
|
Requires-Dist: dnspython==2.4.2
|
|
28
28
|
Requires-Dist: idna==3.4
|
|
29
|
+
Dynamic: author
|
|
30
|
+
Dynamic: author-email
|
|
31
|
+
Dynamic: classifier
|
|
32
|
+
Dynamic: description
|
|
33
|
+
Dynamic: description-content-type
|
|
34
|
+
Dynamic: home-page
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
Dynamic: project-url
|
|
37
|
+
Dynamic: requires-dist
|
|
38
|
+
Dynamic: requires-python
|
|
39
|
+
Dynamic: summary
|
|
29
40
|
|
|
30
41
|
# Safe Shield
|
|
31
42
|
Safe Shield is a robust Python library designed to validating HTTP requests and input data.
|
|
@@ -153,7 +164,10 @@ validator.validate()
|
|
|
153
164
|
|
|
154
165
|
"""
|
|
155
166
|
validator.has_errors -> True
|
|
156
|
-
validator.errors
|
|
167
|
+
validator.errors:
|
|
168
|
+
{
|
|
169
|
+
"name": ["The name field is required.", "The name must be a string"]
|
|
170
|
+
}
|
|
157
171
|
"""
|
|
158
172
|
```
|
|
159
173
|
|
|
@@ -191,10 +205,11 @@ validator.validate()
|
|
|
191
205
|
|
|
192
206
|
"""
|
|
193
207
|
validator.has_errors -> True
|
|
194
|
-
validator.errors
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
208
|
+
validator.errors:
|
|
209
|
+
{
|
|
210
|
+
"user.contact.email": ["The email must be a valid email with valid DNS records."],
|
|
211
|
+
"orders.0.price": ["The price must be a number"]
|
|
212
|
+
}
|
|
198
213
|
"""
|
|
199
214
|
```
|
|
200
215
|
|
|
@@ -217,9 +232,10 @@ validator.validate()
|
|
|
217
232
|
|
|
218
233
|
"""
|
|
219
234
|
validator.has_errors -> True
|
|
220
|
-
validator.errors
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
235
|
+
validator.errors:
|
|
236
|
+
{
|
|
237
|
+
"user.contact.email": ["This email is invalid"],
|
|
238
|
+
"orders.0.price": ["The price must be a number"]
|
|
239
|
+
}
|
|
224
240
|
"""
|
|
225
241
|
```
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
+
safeshield-1.6.4.dist-info/licenses/LICENSE,sha256=YxHGBtuH0Vsy-KPvW2_afKE54XIrf1eipLF4v6kaybI,35276
|
|
1
2
|
validator/__init__.py,sha256=udxDzUicPfxBOAQvzsnl3pHur9VUppKbWMgg35hpiww,244
|
|
2
3
|
validator/exceptions.py,sha256=y2v7CaXmeGFHWcnigtLl4U-sFta_jMiXkGKXWIIVglY,366
|
|
3
4
|
validator/factory.py,sha256=SJ2iJmTnFS-4ccH-gzZl_7CAW7Z6YJkZbMImu-po80w,1163
|
|
4
5
|
validator/core/__init__.py,sha256=ZcqlXJSk03i_CVzmIN-nVe1UOyvwwO5jhbEj7f62Y_o,59
|
|
5
|
-
validator/core/validator.py,sha256=
|
|
6
|
+
validator/core/validator.py,sha256=cflLhGo_rS6Zh61X7lZfr0q-xR0bBHfylGudZ1uTn7o,12765
|
|
6
7
|
validator/database/__init__.py,sha256=O-cB6-MhNapJ3iwe5jvifbMfr1dPjXLtEdfNTKIu0hc,171
|
|
7
8
|
validator/database/detector.py,sha256=Vac7oVL26GjU6expGo01-6mgUtXqldr-jirzpYokZBM,9597
|
|
8
|
-
validator/database/manager.py,sha256=
|
|
9
|
+
validator/database/manager.py,sha256=XJM_I0WaWfZWV710duAc32p1gtiP2or-MAj75WPw1oM,6478
|
|
9
10
|
validator/rules/__init__.py,sha256=z3Vk3R5CRgjeqyDWZxdofD2tBMTgdyYVuFmo1mKOTj4,830
|
|
10
11
|
validator/rules/array.py,sha256=7xwdXnthWZNDbD4lONgqtOf44OOQq1J6XexYm6BXea4,3512
|
|
11
|
-
validator/rules/base.py,sha256=
|
|
12
|
+
validator/rules/base.py,sha256=yhxQdGiiM-wY7VtRH-KRU-_wmw7RVJnmJcmayO1EqBk,5870
|
|
12
13
|
validator/rules/basic.py,sha256=8k-REzsSyknhNuw0vPKMxtovvJBVlyZDihXXVznRQpM,6420
|
|
13
|
-
validator/rules/boolean.py,sha256=
|
|
14
|
+
validator/rules/boolean.py,sha256=UuSO9BdBMR5l6sB3dgZqoqOVjqu47yjFrmJ7xylTVKs,5452
|
|
14
15
|
validator/rules/comparison.py,sha256=BnufmgCkSqzUjSFWvlsKN8auOCKTBs7Pxy5i9rwSQs8,15564
|
|
15
16
|
validator/rules/date.py,sha256=k27U3e08OPZoXyEX0Yj86ZfjCUuhLy4eBmqYbyc4Jn4,7292
|
|
16
17
|
validator/rules/files.py,sha256=3Q0KoadDKqNIiVlBR7b5b-XBs4gOg3ZFu7wU7SrdqWQ,12280
|
|
17
18
|
validator/rules/format.py,sha256=u_BhPQwW30JYHwZIjHD0ZX449csgTPPCJOeoXaQr4M4,7361
|
|
18
19
|
validator/rules/numeric.py,sha256=UgawwV_ZKiJ3Dano32UrSBC6Qe69zbiL69OyMDo91yY,8699
|
|
19
20
|
validator/rules/string.py,sha256=3wgrqAO4V97ZPMc97mwDV6vsNvs6oyJs-ciqQX-FLBs,6268
|
|
20
|
-
validator/rules/utilities.py,sha256=
|
|
21
|
+
validator/rules/utilities.py,sha256=pwo-uhBKDkIV2ZcdVQDBFYMc5ICsKswL904AayBLeBg,17080
|
|
21
22
|
validator/services/__init__.py,sha256=zzKTmqL7v4niFGWHJBfWLqgJ0iTaW_69OzYZN8uInzQ,210
|
|
22
23
|
validator/services/rule_conflict.py,sha256=T3IhWLmZsRUccJ4oFO-OKRjrc5Xt7r71kktxjjj2IA8,9505
|
|
23
24
|
validator/services/rule_error_handler.py,sha256=l4jA6WtTRBNGytVA_nSwJpbix_viNWhqlwKcxIKXzcY,2325
|
|
24
25
|
validator/services/rule_preparer.py,sha256=7HSMuSGGgaYWv8dt_m7pL5MQkJcTwFBH9gfmCZwzt8U,5284
|
|
25
26
|
validator/utils/__init__.py,sha256=Yzo-xv285Be-a233M4duDdYtscuHiuBbPSX_C8yViJI,20
|
|
26
27
|
validator/utils/string.py,sha256=0YACzeEaWNEOR9_7O9A8D1ItIbtWfOJ8IfrzcB8VMYA,515
|
|
27
|
-
safeshield-1.6.
|
|
28
|
-
safeshield-1.6.
|
|
29
|
-
safeshield-1.6.
|
|
30
|
-
safeshield-1.6.
|
|
31
|
-
safeshield-1.6.1.dist-info/RECORD,,
|
|
28
|
+
safeshield-1.6.4.dist-info/METADATA,sha256=o4U6ffoKB60H_lc2k50jRS67BeECUuSHIgzRuKBR5hI,6664
|
|
29
|
+
safeshield-1.6.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
30
|
+
safeshield-1.6.4.dist-info/top_level.txt,sha256=iUtV3dlHOIiMfLuY4pruY00lFni8JzOkQ3Nh1II19OE,10
|
|
31
|
+
safeshield-1.6.4.dist-info/RECORD,,
|
validator/core/validator.py
CHANGED
|
@@ -282,7 +282,7 @@ class Validator:
|
|
|
282
282
|
combined_rules = existing_rules + new_rules
|
|
283
283
|
|
|
284
284
|
RuleConflictChecker.check_conflicts(combined_rules)
|
|
285
|
-
self._raw_rules[field] = self.rule_preparer._deduplicate_rules(
|
|
285
|
+
self._raw_rules[field] = self.rule_preparer._deduplicate_rules(combined_rules)
|
|
286
286
|
|
|
287
287
|
def set_stop_on_first_failure(self, value: bool) -> None:
|
|
288
288
|
"""Set whether to stop validation after first failure"""
|
|
@@ -293,6 +293,9 @@ class Validator:
|
|
|
293
293
|
"""Get current validation errors"""
|
|
294
294
|
return self.error_handler.errors
|
|
295
295
|
|
|
296
|
+
def get_errors(self):
|
|
297
|
+
return self.error_handler.errors or {}
|
|
298
|
+
|
|
296
299
|
@property
|
|
297
300
|
def has_errors(self) -> bool:
|
|
298
301
|
"""Check if there are any validation errors"""
|
validator/database/manager.py
CHANGED
|
@@ -111,21 +111,8 @@ class DatabaseManager:
|
|
|
111
111
|
return cursor.fetchall()
|
|
112
112
|
|
|
113
113
|
def exists(self, table: str, column: str, value: Any) -> bool:
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if len(parts) != 2:
|
|
117
|
-
raise ValueError("Foreign key reference should be in format 'foreign_key.column'")
|
|
118
|
-
|
|
119
|
-
foreign_key, related_column = parts
|
|
120
|
-
sql = f"""
|
|
121
|
-
SELECT 1 FROM {table} t
|
|
122
|
-
JOIN {foreign_key} r ON t.{foreign_key} = r.id
|
|
123
|
-
WHERE r.{related_column} = %s
|
|
124
|
-
LIMIT 1
|
|
125
|
-
"""
|
|
126
|
-
else:
|
|
127
|
-
sql = f"SELECT 1 FROM {table} WHERE {column} = %s LIMIT 1"
|
|
128
|
-
|
|
114
|
+
"""Optimized exists check with parameterized query"""
|
|
115
|
+
sql = f"SELECT 1 FROM {table} WHERE {column} = %s LIMIT 1"
|
|
129
116
|
result = self.query(sql, (value,))
|
|
130
117
|
return bool(result)
|
|
131
118
|
|
validator/rules/base.py
CHANGED
validator/rules/boolean.py
CHANGED
|
@@ -45,7 +45,7 @@ class DeclinedRule(Rule):
|
|
|
45
45
|
return f"The :attribute must be declined."
|
|
46
46
|
|
|
47
47
|
class AcceptedIfRule(AcceptedRule):
|
|
48
|
-
_count_parameter =
|
|
48
|
+
_count_parameter = 2
|
|
49
49
|
|
|
50
50
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
51
51
|
condition_met = False
|
|
@@ -99,7 +99,7 @@ class AcceptedUnlessRule(AcceptedRule):
|
|
|
99
99
|
return replacements
|
|
100
100
|
|
|
101
101
|
class DeclinedIfRule(DeclinedRule):
|
|
102
|
-
_count_parameter =
|
|
102
|
+
_count_parameter = 2
|
|
103
103
|
|
|
104
104
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
105
105
|
condition_met = False
|
validator/rules/utilities.py
CHANGED
|
@@ -4,7 +4,7 @@ from .basic import *
|
|
|
4
4
|
from .boolean import AcceptedRule, DeclinedRule
|
|
5
5
|
|
|
6
6
|
class RequiredIfRule(RequiredRule):
|
|
7
|
-
_count_parameter =
|
|
7
|
+
_count_parameter = 1
|
|
8
8
|
_accept_closure = True
|
|
9
9
|
|
|
10
10
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -67,7 +67,8 @@ class RequiredWithRule(RequiredRule):
|
|
|
67
67
|
_count_parameter = 1
|
|
68
68
|
|
|
69
69
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
70
|
-
|
|
70
|
+
condition = [f in self.validator.data and not self.is_empty(self.get_field_value(f)) for f in params]
|
|
71
|
+
if any(condition):
|
|
71
72
|
return super().validate(field, value, params)
|
|
72
73
|
return True
|
|
73
74
|
|
|
@@ -84,7 +85,9 @@ class RequiredWithAllRule(RequiredRule):
|
|
|
84
85
|
_count_parameter = 1
|
|
85
86
|
|
|
86
87
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
87
|
-
|
|
88
|
+
condition = [f in self.validator.data and not self.is_empty(self.get_field_value(f)) for f in params]
|
|
89
|
+
|
|
90
|
+
if all(condition):
|
|
88
91
|
return super().validate(field, value, params)
|
|
89
92
|
return True
|
|
90
93
|
|
|
@@ -170,7 +173,7 @@ class RequiredArrayKeysRule(Rule):
|
|
|
170
173
|
return replacements
|
|
171
174
|
|
|
172
175
|
class ProhibitedIfRule(ProhibitedRule):
|
|
173
|
-
_count_parameter =
|
|
176
|
+
_count_parameter = 1
|
|
174
177
|
_accept_closure = True
|
|
175
178
|
|
|
176
179
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -241,7 +244,7 @@ class ProhibitedIfDeclinedRule(ProhibitedRule, DeclinedRule):
|
|
|
241
244
|
return True
|
|
242
245
|
|
|
243
246
|
class PresentIfRule(PresentRule):
|
|
244
|
-
_count_parameter =
|
|
247
|
+
_count_parameter = 1
|
|
245
248
|
_accept_closure = True
|
|
246
249
|
|
|
247
250
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -431,7 +434,7 @@ class MissingWithAllRule(MissingRule):
|
|
|
431
434
|
return replacements
|
|
432
435
|
|
|
433
436
|
class ExcludeIfRule(ExcludeRule):
|
|
434
|
-
_count_parameter =
|
|
437
|
+
_count_parameter = 1
|
|
435
438
|
_accept_closure = True
|
|
436
439
|
|
|
437
440
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
File without changes
|
|
File without changes
|