Coverage for website/utils/validators.py: 32.14%
50 statements
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
1from django.core.exceptions import ValidationError
2from django.utils.deconstruct import deconstructible
3from django.utils.translation import gettext_lazy as _
6@deconstructible
7class RangeValueValidator:
8 messages = {
9 "upper_excl": _("Value must be smaller than %(upper)s."),
10 "upper_incl": _("Value may not exceed %(upper)s."),
11 "lower_excl": _("Value must be greater than %(lower)s."),
12 "lower_incl": _("Value must at least %(lower)s."),
13 "lower_excl_upper_excl": _(
14 "Value must be between %(lower)s and %(upper)s (not inclusive)."
15 ),
16 "lower_incl_upper_excl": _(
17 "Value must be at least %(lower)s and less than %(upper)s."
18 ),
19 "lower_excl_upper_incl": _(
20 "Value must be greater than %(lower)s and at most %(upper)s."
21 ),
22 "lower_incl_upper_incl": _(
23 "Value must be at least %(lower)s and at most %(upper)s."
24 ),
25 }
27 def select_error_message(self):
28 build_tuple = (
29 self.lower,
30 self.lower_inclusive,
31 self.upper,
32 self.upper_inclusive,
33 )
35 msg = ""
37 match build_tuple:
38 case (None, _, None, _): 38 ↛ 39line 38 didn't jump to line 39 because the pattern on line 38 never matched
39 return
40 case (None, _, _, False): 40 ↛ 41line 40 didn't jump to line 41 because the pattern on line 40 never matched
41 msg = self.messages["upper_excl"]
42 case (None, _, _, True): 42 ↛ 43line 42 didn't jump to line 43 because the pattern on line 42 never matched
43 msg = self.messages["upper_incl"]
44 case (_, False, None, _): 44 ↛ 46line 44 didn't jump to line 46 because the pattern on line 44 always matched
45 msg = self.messages["lower_excl"]
46 case (_, True, None, _):
47 msg = self.messages["lower_incl"]
48 case (_, False, _, False):
49 msg = self.messages["lower_excl_upper_excl"]
50 case (_, False, _, True):
51 msg = self.messages["lower_excl_upper_incl"]
52 case (_, True, _, False):
53 msg = self.messages["lower_incl_upper_excl"]
54 case (_, True, _, True):
55 msg = self.messages["lower_incl_upper_incl"]
56 case _:
57 return
59 return msg % {"lower": self.lower, "upper": self.upper}
61 def __init__(
62 self,
63 lower=None,
64 lower_inclusive: bool = False,
65 upper=None,
66 upper_inclusive: bool = False,
67 ):
68 self.lower = lower
69 self.lower_inclusive = lower_inclusive
70 self.upper = upper
71 self.upper_inclusive = upper_inclusive
73 self.error_message = self.select_error_message()
75 def __call__(self, value):
76 if self.lower is not None:
77 if self.lower_inclusive:
78 if value < self.lower:
79 raise ValidationError(self.error_message)
80 else:
81 if value <= self.lower:
82 raise ValidationError(self.error_message)
84 if self.upper is not None:
85 if self.upper_inclusive:
86 if value > self.upper:
87 raise ValidationError(self.error_message)
88 else:
89 if value >= self.upper:
90 raise ValidationError(self.error_message)