safeshield 1.5.1__py3-none-any.whl → 1.5.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: safeshield
3
- Version: 1.5.1
3
+ Version: 1.5.2
4
4
  Summary: Library for Help Validation Control
5
5
  Home-page: https://github.com/WunsunTarniho/py-guard
6
6
  Author: Wunsun Tarniho
@@ -0,0 +1,31 @@
1
+ validator/__init__.py,sha256=udxDzUicPfxBOAQvzsnl3pHur9VUppKbWMgg35hpiww,244
2
+ validator/exceptions.py,sha256=y2v7CaXmeGFHWcnigtLl4U-sFta_jMiXkGKXWIIVglY,366
3
+ validator/factory.py,sha256=SJ2iJmTnFS-4ccH-gzZl_7CAW7Z6YJkZbMImu-po80w,1163
4
+ validator/core/__init__.py,sha256=ZcqlXJSk03i_CVzmIN-nVe1UOyvwwO5jhbEj7f62Y_o,59
5
+ validator/core/validator.py,sha256=bqy1cF7ArLfigeKKQd94PcQGcAhncta4CkgbN2FZZAw,12669
6
+ validator/database/__init__.py,sha256=O-cB6-MhNapJ3iwe5jvifbMfr1dPjXLtEdfNTKIu0hc,171
7
+ validator/database/detector.py,sha256=Vac7oVL26GjU6expGo01-6mgUtXqldr-jirzpYokZBM,9597
8
+ validator/database/manager.py,sha256=XJM_I0WaWfZWV710duAc32p1gtiP2or-MAj75WPw1oM,6478
9
+ validator/rules/__init__.py,sha256=z3Vk3R5CRgjeqyDWZxdofD2tBMTgdyYVuFmo1mKOTj4,830
10
+ validator/rules/array.py,sha256=7xwdXnthWZNDbD4lONgqtOf44OOQq1J6XexYm6BXea4,3512
11
+ validator/rules/base.py,sha256=yhxQdGiiM-wY7VtRH-KRU-_wmw7RVJnmJcmayO1EqBk,5870
12
+ validator/rules/basic.py,sha256=8k-REzsSyknhNuw0vPKMxtovvJBVlyZDihXXVznRQpM,6420
13
+ validator/rules/boolean.py,sha256=UuSO9BdBMR5l6sB3dgZqoqOVjqu47yjFrmJ7xylTVKs,5452
14
+ validator/rules/comparison.py,sha256=BnufmgCkSqzUjSFWvlsKN8auOCKTBs7Pxy5i9rwSQs8,15564
15
+ validator/rules/date.py,sha256=k27U3e08OPZoXyEX0Yj86ZfjCUuhLy4eBmqYbyc4Jn4,7292
16
+ validator/rules/files.py,sha256=3Q0KoadDKqNIiVlBR7b5b-XBs4gOg3ZFu7wU7SrdqWQ,12280
17
+ validator/rules/format.py,sha256=u_BhPQwW30JYHwZIjHD0ZX449csgTPPCJOeoXaQr4M4,7361
18
+ validator/rules/numeric.py,sha256=UgawwV_ZKiJ3Dano32UrSBC6Qe69zbiL69OyMDo91yY,8699
19
+ validator/rules/string.py,sha256=3wgrqAO4V97ZPMc97mwDV6vsNvs6oyJs-ciqQX-FLBs,6268
20
+ validator/rules/utilities.py,sha256=BaErsE0TPt1u342aOuSBkjh0CMD2Sq7ZwiBqM8j0GLo,16910
21
+ validator/services/__init__.py,sha256=zzKTmqL7v4niFGWHJBfWLqgJ0iTaW_69OzYZN8uInzQ,210
22
+ validator/services/rule_conflict.py,sha256=T3IhWLmZsRUccJ4oFO-OKRjrc5Xt7r71kktxjjj2IA8,9505
23
+ validator/services/rule_error_handler.py,sha256=l4jA6WtTRBNGytVA_nSwJpbix_viNWhqlwKcxIKXzcY,2325
24
+ validator/services/rule_preparer.py,sha256=7HSMuSGGgaYWv8dt_m7pL5MQkJcTwFBH9gfmCZwzt8U,5284
25
+ validator/utils/__init__.py,sha256=Yzo-xv285Be-a233M4duDdYtscuHiuBbPSX_C8yViJI,20
26
+ validator/utils/string.py,sha256=0YACzeEaWNEOR9_7O9A8D1ItIbtWfOJ8IfrzcB8VMYA,515
27
+ safeshield-1.5.2.dist-info/LICENSE,sha256=qugtRyKckyaks6hd2xyxOFSOYM6au1N80pMXuMTPvC4,1090
28
+ safeshield-1.5.2.dist-info/METADATA,sha256=SLg1vFMs-BhT0jNEh7zi2dLSEi5Ps_eN_7WquguKIOc,2313
29
+ safeshield-1.5.2.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
30
+ safeshield-1.5.2.dist-info/top_level.txt,sha256=iUtV3dlHOIiMfLuY4pruY00lFni8JzOkQ3Nh1II19OE,10
31
+ safeshield-1.5.2.dist-info/RECORD,,
@@ -12,7 +12,7 @@ from collections.abc import Mapping
12
12
  class Validator:
13
13
  """Main validation class with proper abstractions"""
14
14
  PRIORITY_RULES = {
15
- 'bail', 'sometimes', 'exclude', 'exclude_unless', 'exclude_if', 'exclude_with', 'exclude_without', 'required', 'required_if', 'required_unless',
15
+ 'bail', 'sometimes', 'dynamic', 'exclude', 'exclude_unless', 'exclude_if', 'exclude_with', 'exclude_without', 'required', 'required_if', 'required_unless',
16
16
  'required_with', 'required_without'
17
17
  }
18
18
 
@@ -60,6 +60,7 @@ class Validator:
60
60
  ):
61
61
  self.data = data or {}
62
62
  self._raw_rules = rules or {}
63
+ self.prepared_rules = None
63
64
  self._stop_on_first_failure = False
64
65
  self._field_to_exclude = []
65
66
 
@@ -67,6 +68,7 @@ class Validator:
67
68
  # Initialize dependencies
68
69
  self.rule_preparer = RulePreparer(RuleFactory())
69
70
  self.error_handler = RuleErrorHandler(messages, custom_attributes)
71
+ self.custom_attributes = custom_attributes or {}
70
72
 
71
73
  # Database configuration
72
74
  self.db_config = db_config or DatabaseAutoDetector.detect()
@@ -79,17 +81,17 @@ class Validator:
79
81
 
80
82
  def validate(self) -> bool:
81
83
  """Validate the data against the rules"""
82
- prepared_rules = self.rule_preparer.prepare(self._raw_rules)
84
+ self.prepared_rules = self.rule_preparer.prepare(self._raw_rules)
83
85
  self.error_handler.errors.clear()
84
-
85
- validated = self._validate_rules(prepared_rules, priority_only=True)
86
+
87
+ validated = self._validate_rules(self.prepared_rules, priority_only=True)
86
88
 
87
89
  # First pass: priority rules
88
90
  if self.error_handler.has_errors and self._stop_on_first_failure:
89
91
  return False
90
-
92
+
91
93
  # Second pass: remaining rules
92
- self._validate_rules(prepared_rules, priority_only=False)
94
+ self._validate_rules(self.prepared_rules, priority_only=False)
93
95
 
94
96
  if self.error_handler.has_errors:
95
97
  return False
@@ -219,22 +221,18 @@ class Validator:
219
221
  return _check(self.data, parts)
220
222
 
221
223
  def _apply_rule(self, field: str, value: Any, rule: Rule) -> bool:
222
- try:
223
- rule.set_validator(self)
224
+ rule.set_validator(self)
224
225
 
225
- display_field = getattr(self, '_current_actual_path', field)
226
+ display_field = getattr(self, '_current_actual_path', field)
227
+ rule._require_parameter_count(getattr(rule, '_count_parameter', 0), getattr(rule, 'params', []), rule)
226
228
 
227
- if not rule.validate(field, value, getattr(rule, 'params', [])):
228
- msg = rule.message(display_field, getattr(rule, 'params', []))
229
- self.error_handler.add_error(display_field, rule.rule_name, getattr(rule, 'params', []), msg, value)
229
+ if not rule.validate(field, value, getattr(rule, 'params', [])):
230
+ msg = rule.message(display_field, getattr(rule, 'params', []))
231
+ self.error_handler.add_error(display_field, rule, getattr(rule, 'params', []), msg, value)
230
232
 
231
- return False
232
- else:
233
- return True
234
- except Exception as e:
235
- display_field = getattr(self, '_current_actual_path', field)
236
- self.error_handler.add_error(display_field, rule.rule_name, getattr(rule, 'params', []), str(e), value)
237
233
  return False
234
+ else:
235
+ return True
238
236
 
239
237
  def _get_nested_value(self, path: str) -> Any:
240
238
  parts = path.split('.')
validator/rules/array.py CHANGED
@@ -3,24 +3,30 @@ from typing import Any, Dict, List, Optional, Set, Union, Tuple, Type
3
3
 
4
4
  class ArrayRule(Rule):
5
5
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
6
- self._missing_keys = params
7
-
8
6
  if params:
9
7
  params = self._parse_option_values(self.rule_name, params)
10
8
  if not isinstance(value, dict):
11
9
  return False
12
-
10
+
13
11
  missing = [param for param in params if param not in value]
14
- self._missing_keys = missing
15
12
  return len(missing) == 0
16
13
 
17
14
  return isinstance(value, (list, tuple, set))
18
15
 
19
16
  def message(self, field: str, params: List[str]) -> str:
20
17
  if params:
21
- return f"The :attribute must contain the keys: {', '.join(self._missing_keys)}."
18
+ return f"The :attribute must contain the keys: :values."
22
19
  return f"The :attribute must be an array."
23
20
 
21
+ def replacements(self, field, value):
22
+ replacements = {
23
+ ':attribute': self._get_display_name(field),
24
+ ':input': value,
25
+ ':values': ', '.join(self._params)
26
+ }
27
+
28
+ return replacements
29
+
24
30
  class DistinctRule(Rule):
25
31
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
26
32
  if not isinstance(value, (list, tuple, set)):
@@ -48,23 +54,51 @@ class DistinctRule(Rule):
48
54
  return f"{base_msg} (case insensitive)"
49
55
  else:
50
56
  return f"{base_msg} (strict comparison)"
57
+
58
+ def replacements(self, field, value):
59
+ replacements = {
60
+ ':attribute': self._get_display_name(field),
61
+ ':input': value,
62
+ ':value': self._params[0] if self._params else None
63
+ }
64
+
65
+ return replacements
51
66
 
52
67
  class InArrayRule(Rule):
68
+ _count_parameter = 1
69
+
53
70
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
54
- if not params:
55
- return False
56
-
57
- return str(value) in params
71
+ return str(value) in self.get_field_value(params[0], [])
58
72
 
59
73
  def message(self, field: str, params: List[str]) -> str:
60
- return f"The :attribute must be one of: {', '.join(params)}"
74
+ return f"The :attribute must be one of: :values"
75
+
76
+ def replacements(self, field, value):
77
+ replacements = {
78
+ ':attribute': self._get_display_name(field),
79
+ ':input': value,
80
+ ':values': ', '.join(self.get_field_value(self._params[0], []))
81
+ }
82
+
83
+ return replacements
61
84
 
62
85
  class InArrayKeysRule(Rule):
86
+ _count_parameter = 1
87
+
63
88
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
64
- if not params or not isinstance(value, dict):
89
+ if not isinstance(value, dict):
65
90
  return False
66
91
 
67
92
  return any(key in value for key in params)
68
93
 
69
94
  def message(self, field: str, params: List[str]) -> str:
70
- return f"The :attribute must contain at least one of these keys: {', '.join(params)}"
95
+ return f"The :attribute must contain at least one of these keys: :values"
96
+
97
+ def replacements(self, field, value):
98
+ replacements = {
99
+ ':attribute': self._get_display_name(field),
100
+ ':input': value,
101
+ ':values': ', '.join(self._params)
102
+ }
103
+
104
+ return replacements
validator/rules/base.py CHANGED
@@ -8,20 +8,15 @@ class Rule(ABC):
8
8
  """Abstract base class for all validation rules"""
9
9
 
10
10
  _rule_classes: Dict[str, Type['Rule']] = {}
11
- _rule_cache: Dict[str, 'Rule'] = {}
12
11
 
13
12
  def __init__(self, *params: str):
14
13
  self._validator: Optional['Validator'] = None
15
14
  self._params: List[str] = list(params)
16
15
 
17
- def __init_subclass__(cls, name=None):
16
+ def __init_subclass__(cls):
18
17
  cls.rule_name = cls.pascal_to_snake(cls.__name__) if not hasattr(cls, '_name') else cls._name
19
18
  cls._register_rule_class()
20
19
  cls._generate_rule_methods()
21
-
22
- @classmethod
23
- def _register_rule_class(cls):
24
- cls._rule_classes[cls.rule_name] = cls
25
20
 
26
21
  @property
27
22
  def params(self):
@@ -33,6 +28,10 @@ class Rule(ABC):
33
28
  params.append(rule_set)
34
29
  return tuple(params)
35
30
 
31
+ @classmethod
32
+ def _register_rule_class(cls):
33
+ cls._rule_classes[cls.rule_name] = cls
34
+
36
35
  @classmethod
37
36
  def _generate_rule_methods(cls):
38
37
  for rule_name, rule_class in cls._rule_classes.items():
@@ -42,6 +41,14 @@ class Rule(ABC):
42
41
 
43
42
  setattr(cls.__class__, rule_name, method)
44
43
 
44
+ @classmethod
45
+ def _require_parameter_count(self, count, params, rule):
46
+ if getattr(rule, '_accept_closure', False) and (isinstance(params[0], bool) or callable(params[0])):
47
+ return
48
+
49
+ if count > len(params):
50
+ raise ValueError(f"Validation rule {rule.rule_name} requires at least {count} parameter")
51
+
45
52
  @params.setter
46
53
  def params(self, value: List[str]) -> None:
47
54
  self._params = value
@@ -81,6 +88,35 @@ class Rule(ABC):
81
88
  """Generate an error message if validation fails."""
82
89
  pass
83
90
 
91
+ def replacements(self, field, value) -> Dict[str, str]:
92
+ """Default replacements for all rules"""
93
+ return {':attribute': self._get_display_name(field), 'value': value }
94
+
95
+ def _get_display_name(self, fields: str) -> str:
96
+ single_input = isinstance(fields, str)
97
+ if single_input:
98
+ fields = [fields]
99
+
100
+ attributes = []
101
+
102
+ for field in fields:
103
+ if field in self.validator.custom_attributes:
104
+ attributes.append(self.validator.custom_attributes[field])
105
+ continue
106
+
107
+ parts = field.split('.')
108
+ base_name = parts[-1].replace('_', ' ').title()
109
+
110
+ for i in range(len(parts), 0, -1):
111
+ wildcard = '.'.join(parts[:i]) + '.*'
112
+ if wildcard in self.validator.custom_attributes:
113
+ attributes.append(self.validator.custom_attributes[wildcard])
114
+ break
115
+ else:
116
+ attributes.append(self.validator.custom_attributes.get(parts[-1], base_name))
117
+
118
+ return attributes[0] if single_input else attributes
119
+
84
120
  @property
85
121
  @abstractmethod
86
122
  def rule_name(self) -> str:
validator/rules/basic.py CHANGED
@@ -6,8 +6,10 @@ from typing import Any, Dict, List, Optional, Set, Union, Tuple, Type
6
6
  # =============================================
7
7
 
8
8
  class AnyOfRule(Rule):
9
+ _count_parameter = 1
10
+
9
11
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
10
- self._last_failed_rules = [] # Reset failed rules
12
+ self._last_failed_rules = []
11
13
 
12
14
  for i, rule_set in enumerate(params):
13
15
  if isinstance(rule_set, str):
@@ -56,6 +58,30 @@ class AnyOfRule(Rule):
56
58
  f"The :attribute must satisfy at least one of these conditions:\n" +
57
59
  "\n".join(error_messages)
58
60
  )
61
+
62
+ class WhenRule(Rule):
63
+ _count_parameter = 1
64
+
65
+ def validate(self, field: str, value: Any, params: List[str]) -> bool:
66
+ rules = [rule for rule in self.validator.prepared_rules.get(field, []) if rule.rule_name != 'when']
67
+ rules = [new_rule for new_rule in self.validator.rule_preparer._generate_rule(field, self._select_rules(field))]
68
+ self.validator.prepared_rules[field] += rules
69
+
70
+ return True
71
+
72
+ def _select_rules(self, field: str) -> List[str]:
73
+ selected = None
74
+ for check_field, rules_map in self._params[0].items():
75
+ current_value = str(self.get_field_value(check_field)) if self.get_field_value(check_field) is not None else ''
76
+ for expected_value, rules in rules_map.items():
77
+ if current_value == expected_value or expected_value == '*':
78
+ selected = rules
79
+ break
80
+
81
+ return selected
82
+
83
+ def message(self, field: str, params: List[str]) -> str:
84
+ return ""
59
85
 
60
86
  class BailRule(Rule):
61
87
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
@@ -108,13 +134,29 @@ class MissingRule(Rule):
108
134
  return f"The :attribute field must be missing."
109
135
 
110
136
  class ProhibitsRule(Rule):
137
+ _count_parameter = 1
138
+
111
139
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
112
- if not params or value is None:
140
+ if value is None or value == '':
113
141
  return True
114
- return all(self.get_field_value(param, param) in (None, 'None') for param in params)
142
+
143
+ for param in params:
144
+ other_value = self.get_field_value(param, None)
145
+ if other_value in self.validator.data:
146
+ return False
147
+ return True
115
148
 
116
149
  def message(self, field: str, params: List[str]) -> str:
117
- return f"When :attribute is present, {', '.join(params)} must be absent."
150
+ return f"When :attribute is present, :others must be empty or absent."
151
+
152
+ def replacements(self, field, value):
153
+ replacements = {
154
+ ':attribute': self._get_display_name(field),
155
+ ':input': value,
156
+ ':others': ', '.join(self._get_display_name(self._params))
157
+ }
158
+
159
+ return replacements
118
160
 
119
161
  class SometimesRule(Rule):
120
162
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
@@ -6,7 +6,7 @@ class BooleanRule(Rule):
6
6
  if isinstance(value, bool):
7
7
  return True
8
8
  if isinstance(value, str):
9
- return value.lower() in ['true', 'false', '1', '0', 'yes', 'no', 'on', 'off']
9
+ return value.lower() in ['true', 'false', '1', '0', 'yes', 'no', 'on', 'off', 'False', 'True']
10
10
  if isinstance(value, int):
11
11
  return value in [0, 1]
12
12
  return False
@@ -45,6 +45,8 @@ class DeclinedRule(Rule):
45
45
  return f"The :attribute must be declined."
46
46
 
47
47
  class AcceptedIfRule(AcceptedRule):
48
+ _count_parameter = 2
49
+
48
50
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
49
51
  condition_met = False
50
52
 
@@ -53,54 +55,52 @@ class AcceptedIfRule(AcceptedRule):
53
55
  elif len(params) == 1 and isinstance(params[0], bool):
54
56
  condition_met = params[0]
55
57
  else:
56
- conditions = list(zip(params[::2], params[1::2]))
58
+ expected_value = self.get_field_value(params[0], None)
59
+ condition = params[1]
57
60
 
58
- for other_field, expected_value in conditions:
59
- if not other_field or expected_value is None:
60
- continue
61
-
62
- actual_value = self.get_field_value(other_field, '')
63
-
64
- if actual_value == expected_value:
65
- condition_met = True
66
- break
61
+ if expected_value == condition:
62
+ condition_met = True
67
63
 
68
64
  if condition_met:
69
65
  return super().validate(field, value, params)
70
66
 
71
67
  return True
72
68
 
69
+ def replacements(self, field, value):
70
+ replacements = {
71
+ ':attribute': self._get_display_name(field),
72
+ ':input': value,
73
+ ':other': self._get_display_name(self._params[0]),
74
+ ':value': self._params[1],
75
+ }
76
+
77
+ return replacements
78
+
73
79
  class AcceptedUnlessRule(AcceptedRule):
80
+ _count_parameter = 2
81
+
74
82
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
75
- if len(params) < 2:
76
- return False
77
-
78
83
  other_field, other_value = params[0], params[1]
79
- actual_value = self.get_field_value(other_field, '')
84
+ actual_value = self.get_field_value(other_field, None)
80
85
 
81
86
  if actual_value == other_value:
82
87
  return True
83
88
 
84
89
  return super().validate(field, value, params)
85
90
 
86
- class AcceptedAllIfRule(AcceptedRule):
87
- def validate(self, field: str, value: Any, params: List[str]) -> bool:
88
- if len(params) < 2:
89
- return False
90
-
91
- conditions = [(f.strip(), v.strip()) for f, v in zip(params[::2], params[1::2])]
91
+ def replacements(self, field, value):
92
+ replacements = {
93
+ ':attribute': self._get_display_name(field),
94
+ ':input': value,
95
+ ':other': self._get_display_name(self._params[0]),
96
+ ':value': self._params[1],
97
+ }
92
98
 
93
- all_conditions_met = all(
94
- self.get_field_value(f) == v
95
- for f, v in conditions
96
- )
97
-
98
- if not all_conditions_met:
99
- return True
100
-
101
- return super().validate(field, value, params)
99
+ return replacements
102
100
 
103
101
  class DeclinedIfRule(DeclinedRule):
102
+ _count_parameter = 2
103
+
104
104
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
105
105
  condition_met = False
106
106
 
@@ -109,24 +109,30 @@ class DeclinedIfRule(DeclinedRule):
109
109
  elif len(params) == 1 and isinstance(params[0], bool):
110
110
  condition_met = params[0]
111
111
  else:
112
- conditions = list(zip(params[::2], params[1::2]))
112
+ expected_value = self.get_field_value(params[0], None)
113
+ condition = params[1]
114
+
115
+ if expected_value == condition:
116
+ condition_met = True
113
117
 
114
- for other_field, expected_value in conditions:
115
- if not other_field or expected_value is None:
116
- continue
117
-
118
- actual_value = self.get_field_value(other_field, '')
119
-
120
- if actual_value == expected_value:
121
- condition_met = True
122
- break
123
-
124
118
  if condition_met:
125
119
  return super().validate(field, value, params)
126
-
120
+
127
121
  return True
128
122
 
123
+ def replacements(self, field, value):
124
+ replacements = {
125
+ ':attribute': self._get_display_name(field),
126
+ ':input': value,
127
+ ':other': self._get_display_name(self._params[0]),
128
+ ':value': self._params[1],
129
+ }
130
+
131
+ return replacements
132
+
129
133
  class DeclinedUnlessRule(DeclinedRule):
134
+ _count_parameter = 2
135
+
130
136
  def validate(self, field: str, value: Any, params: List[str]) -> bool:
131
137
  if len(params) < 2:
132
138
  return False
@@ -139,19 +145,12 @@ class DeclinedUnlessRule(DeclinedRule):
139
145
 
140
146
  return super().validate(field, value, params)
141
147
 
142
- class DeclinedAllIfRule(DeclinedRule):
143
- def validate(self, field: str, value: Any, params: List[str]) -> bool:
144
- if len(params) < 2:
145
- return False
146
-
147
- conditions = [(f.strip(), v.strip()) for f, v in zip(params[::2], params[1::2])]
148
-
149
- all_conditions_met = all(
150
- self.get_field_value(f) == v
151
- for f, v in conditions
152
- )
148
+ def replacements(self, field, value):
149
+ replacements = {
150
+ ':attribute': self._get_display_name(field),
151
+ ':input': value,
152
+ ':other': self._get_display_name(self._params[0]),
153
+ ':value': self._params[1],
154
+ }
153
155
 
154
- if not all_conditions_met:
155
- return True
156
-
157
- return super().validate(field, value, params)
156
+ return replacements