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

1from django.core.exceptions import ValidationError 

2from django.utils.deconstruct import deconstructible 

3from django.utils.translation import gettext_lazy as _ 

4 

5 

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 } 

26 

27 def select_error_message(self): 

28 build_tuple = ( 

29 self.lower, 

30 self.lower_inclusive, 

31 self.upper, 

32 self.upper_inclusive, 

33 ) 

34 

35 msg = "" 

36 

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 

58 

59 return msg % {"lower": self.lower, "upper": self.upper} 

60 

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 

72 

73 self.error_message = self.select_error_message() 

74 

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) 

83 

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)