safeshield 1.6.1__tar.gz → 1.6.3__tar.gz

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.
Files changed (38) hide show
  1. safeshield-1.6.3/MANIFEST.in +1 -0
  2. {safeshield-1.6.1 → safeshield-1.6.3}/PKG-INFO +37 -11
  3. {safeshield-1.6.1 → safeshield-1.6.3}/README.md +14 -9
  4. safeshield-1.6.3/requirements.txt +12 -0
  5. {safeshield-1.6.1 → safeshield-1.6.3}/safeshield.egg-info/PKG-INFO +37 -11
  6. {safeshield-1.6.1 → safeshield-1.6.3}/safeshield.egg-info/SOURCES.txt +2 -0
  7. {safeshield-1.6.1 → safeshield-1.6.3}/setup.py +5 -2
  8. {safeshield-1.6.1 → safeshield-1.6.3}/validator/core/validator.py +4 -1
  9. {safeshield-1.6.1 → safeshield-1.6.3}/validator/database/manager.py +2 -15
  10. {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/base.py +0 -3
  11. {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/boolean.py +2 -2
  12. {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/utilities.py +9 -6
  13. {safeshield-1.6.1 → safeshield-1.6.3}/LICENSE +0 -0
  14. {safeshield-1.6.1 → safeshield-1.6.3}/safeshield.egg-info/dependency_links.txt +0 -0
  15. {safeshield-1.6.1 → safeshield-1.6.3}/safeshield.egg-info/requires.txt +0 -0
  16. {safeshield-1.6.1 → safeshield-1.6.3}/safeshield.egg-info/top_level.txt +0 -0
  17. {safeshield-1.6.1 → safeshield-1.6.3}/setup.cfg +0 -0
  18. {safeshield-1.6.1 → safeshield-1.6.3}/validator/__init__.py +0 -0
  19. {safeshield-1.6.1 → safeshield-1.6.3}/validator/core/__init__.py +0 -0
  20. {safeshield-1.6.1 → safeshield-1.6.3}/validator/database/__init__.py +0 -0
  21. {safeshield-1.6.1 → safeshield-1.6.3}/validator/database/detector.py +0 -0
  22. {safeshield-1.6.1 → safeshield-1.6.3}/validator/exceptions.py +0 -0
  23. {safeshield-1.6.1 → safeshield-1.6.3}/validator/factory.py +0 -0
  24. {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/__init__.py +0 -0
  25. {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/array.py +0 -0
  26. {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/basic.py +0 -0
  27. {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/comparison.py +0 -0
  28. {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/date.py +0 -0
  29. {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/files.py +0 -0
  30. {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/format.py +0 -0
  31. {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/numeric.py +0 -0
  32. {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/string.py +0 -0
  33. {safeshield-1.6.1 → safeshield-1.6.3}/validator/services/__init__.py +0 -0
  34. {safeshield-1.6.1 → safeshield-1.6.3}/validator/services/rule_conflict.py +0 -0
  35. {safeshield-1.6.1 → safeshield-1.6.3}/validator/services/rule_error_handler.py +0 -0
  36. {safeshield-1.6.1 → safeshield-1.6.3}/validator/services/rule_preparer.py +0 -0
  37. {safeshield-1.6.1 → safeshield-1.6.3}/validator/utils/__init__.py +0 -0
  38. {safeshield-1.6.1 → safeshield-1.6.3}/validator/utils/string.py +0 -0
@@ -0,0 +1 @@
1
+ include requirements.txt
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: safeshield
3
- Version: 1.6.1
3
+ Version: 1.6.3
4
4
  Summary: Library for Help Validation Control
5
5
  Home-page: https://github.com/WunsunTarniho/py-guard
6
6
  Author: Wunsun Tarniho
@@ -16,6 +16,27 @@ Classifier: Topic :: Security
16
16
  Requires-Python: >=3.10
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
+ Requires-Dist: mysql-connector-python==8.0.33
20
+ Requires-Dist: Pillow==11.2.1
21
+ Requires-Dist: psycopg2-binary==2.9.9
22
+ Requires-Dist: python-dotenv==1.1.1
23
+ Requires-Dist: python_dateutil==2.9.0.post0
24
+ Requires-Dist: setuptools==63.2.0
25
+ Requires-Dist: SQLAlchemy==2.0.41
26
+ Requires-Dist: Werkzeug==1.0.1
27
+ Requires-Dist: dnspython==2.4.2
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
19
40
 
20
41
  # Safe Shield
21
42
  Safe Shield is a robust Python library designed to validating HTTP requests and input data.
@@ -143,7 +164,10 @@ validator.validate()
143
164
 
144
165
  """
145
166
  validator.has_errors -> True
146
- validator.errors -> {"name": ["The name field is required.", "The name must be a string"]}
167
+ validator.errors:
168
+ {
169
+ "name": ["The name field is required.", "The name must be a string"]
170
+ }
147
171
  """
148
172
  ```
149
173
 
@@ -181,10 +205,11 @@ validator.validate()
181
205
 
182
206
  """
183
207
  validator.has_errors -> True
184
- validator.errors -> {
185
- "user.contact.email": ["The email must be a valid email with valid DNS records."],
186
- "orders.0.price": ["The price must be a number"]
187
- }
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
+ }
188
213
  """
189
214
  ```
190
215
 
@@ -207,9 +232,10 @@ validator.validate()
207
232
 
208
233
  """
209
234
  validator.has_errors -> True
210
- validator.errors -> {
211
- "user.contact.email": ["This email is invalid"],
212
- "orders.0.price": ["The price must be a number"]
213
- }
235
+ validator.errors:
236
+ {
237
+ "user.contact.email": ["This email is invalid"],
238
+ "orders.0.price": ["The price must be a number"]
239
+ }
214
240
  """
215
241
  ```
@@ -124,7 +124,10 @@ validator.validate()
124
124
 
125
125
  """
126
126
  validator.has_errors -> True
127
- validator.errors -> {"name": ["The name field is required.", "The name must be a string"]}
127
+ validator.errors:
128
+ {
129
+ "name": ["The name field is required.", "The name must be a string"]
130
+ }
128
131
  """
129
132
  ```
130
133
 
@@ -162,10 +165,11 @@ validator.validate()
162
165
 
163
166
  """
164
167
  validator.has_errors -> True
165
- validator.errors -> {
166
- "user.contact.email": ["The email must be a valid email with valid DNS records."],
167
- "orders.0.price": ["The price must be a number"]
168
- }
168
+ validator.errors:
169
+ {
170
+ "user.contact.email": ["The email must be a valid email with valid DNS records."],
171
+ "orders.0.price": ["The price must be a number"]
172
+ }
169
173
  """
170
174
  ```
171
175
 
@@ -188,9 +192,10 @@ validator.validate()
188
192
 
189
193
  """
190
194
  validator.has_errors -> True
191
- validator.errors -> {
192
- "user.contact.email": ["This email is invalid"],
193
- "orders.0.price": ["The price must be a number"]
194
- }
195
+ validator.errors:
196
+ {
197
+ "user.contact.email": ["This email is invalid"],
198
+ "orders.0.price": ["The price must be a number"]
199
+ }
195
200
  """
196
201
  ```
@@ -0,0 +1,12 @@
1
+ # Django==5.2
2
+ # Flask==3.1.1
3
+ mysql-connector-python==8.0.33
4
+ Pillow==11.2.1
5
+ psycopg2-binary==2.9.9
6
+ python-dotenv==1.1.1
7
+ python_dateutil==2.9.0.post0
8
+ setuptools==63.2.0
9
+ SQLAlchemy==2.0.41
10
+ Werkzeug==1.0.1
11
+ dnspython==2.4.2
12
+ idna==3.4
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: safeshield
3
- Version: 1.6.1
3
+ Version: 1.6.3
4
4
  Summary: Library for Help Validation Control
5
5
  Home-page: https://github.com/WunsunTarniho/py-guard
6
6
  Author: Wunsun Tarniho
@@ -16,6 +16,27 @@ Classifier: Topic :: Security
16
16
  Requires-Python: >=3.10
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
+ Requires-Dist: mysql-connector-python==8.0.33
20
+ Requires-Dist: Pillow==11.2.1
21
+ Requires-Dist: psycopg2-binary==2.9.9
22
+ Requires-Dist: python-dotenv==1.1.1
23
+ Requires-Dist: python_dateutil==2.9.0.post0
24
+ Requires-Dist: setuptools==63.2.0
25
+ Requires-Dist: SQLAlchemy==2.0.41
26
+ Requires-Dist: Werkzeug==1.0.1
27
+ Requires-Dist: dnspython==2.4.2
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
19
40
 
20
41
  # Safe Shield
21
42
  Safe Shield is a robust Python library designed to validating HTTP requests and input data.
@@ -143,7 +164,10 @@ validator.validate()
143
164
 
144
165
  """
145
166
  validator.has_errors -> True
146
- validator.errors -> {"name": ["The name field is required.", "The name must be a string"]}
167
+ validator.errors:
168
+ {
169
+ "name": ["The name field is required.", "The name must be a string"]
170
+ }
147
171
  """
148
172
  ```
149
173
 
@@ -181,10 +205,11 @@ validator.validate()
181
205
 
182
206
  """
183
207
  validator.has_errors -> True
184
- validator.errors -> {
185
- "user.contact.email": ["The email must be a valid email with valid DNS records."],
186
- "orders.0.price": ["The price must be a number"]
187
- }
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
+ }
188
213
  """
189
214
  ```
190
215
 
@@ -207,9 +232,10 @@ validator.validate()
207
232
 
208
233
  """
209
234
  validator.has_errors -> True
210
- validator.errors -> {
211
- "user.contact.email": ["This email is invalid"],
212
- "orders.0.price": ["The price must be a number"]
213
- }
235
+ validator.errors:
236
+ {
237
+ "user.contact.email": ["This email is invalid"],
238
+ "orders.0.price": ["The price must be a number"]
239
+ }
214
240
  """
215
241
  ```
@@ -1,5 +1,7 @@
1
1
  LICENSE
2
+ MANIFEST.in
2
3
  README.md
4
+ requirements.txt
3
5
  setup.py
4
6
  safeshield.egg-info/PKG-INFO
5
7
  safeshield.egg-info/SOURCES.txt
@@ -1,13 +1,16 @@
1
1
  from setuptools import setup, find_packages
2
2
  import os
3
3
 
4
+ current_dir = os.path.dirname(__file__) # Folder dimana setup.py berada
5
+ requirements_path = os.path.join(current_dir, 'requirements.txt')
6
+
4
7
  def get_requirements():
5
- with open('requirements.txt') as f:
8
+ with open(requirements_path) as f:
6
9
  return [line.strip() for line in f.readlines() if line.strip()]
7
10
 
8
11
  setup(
9
12
  name="safeshield",
10
- version="1.6.1",
13
+ version="1.6.3",
11
14
  packages=find_packages(),
12
15
  install_requires=get_requirements(),
13
16
  author="Wunsun Tarniho",
@@ -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(field, combined_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"""
@@ -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
- if '.' in column:
115
- parts = column.split('.')
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
 
@@ -99,9 +99,6 @@ class Rule(ABC):
99
99
 
100
100
  attributes = []
101
101
 
102
- if isinstance(fields, bool):
103
- return None
104
-
105
102
  for field in fields:
106
103
  if field in self.validator.custom_attributes:
107
104
  attributes.append(self.validator.custom_attributes[field])
@@ -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 = 1
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 = 1
102
+ _count_parameter = 2
103
103
 
104
104
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
105
105
  condition_met = False
@@ -4,7 +4,7 @@ from .basic import *
4
4
  from .boolean import AcceptedRule, DeclinedRule
5
5
 
6
6
  class RequiredIfRule(RequiredRule):
7
- _count_parameter = 2
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
- if any(f in self.validator.data for f in params):
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
- if all(f in self.validator.data for f in params):
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 = 2
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 = 2
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 = 2
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