summaryrefslogtreecommitdiff
path: root/day9/task5_vue/backend/database/validators.py
blob: 4df0fd62f6bacc562e36f0e9bcb5cd7fa1ca7b5f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
from abc import ABC, abstractmethod
import re


class ValidationError(Exception):
    pass


class Validator(ABC):
    @staticmethod
    @abstractmethod
    def validate(value, field_object):
        pass


class ValidateNull(Validator):
    @staticmethod
    def validate(value, field_object):
        if value is None and not field_object.nullable:
            raise ValidationError('Value cannot be NULL')


class ValidateType(Validator):
    @staticmethod
    def validate(value, field_object):
        if field_object.nullable and value is None:
            return
        if not isinstance(value, field_object.data_type):
            raise ValidationError('Value is of wrong type')


class ValidateLength(Validator):
    @staticmethod
    def validate(value, field_object):
        if hasattr(field_object, 'is_variable_length') and not field_object.is_variable_length:
            if len(str(value)) < field_object.max_length:
                raise ValidationError('Value has too few characters')

        if len(str(value)) > field_object.max_length:
            raise ValidationError('Value has too many characters')


class ValidateTime(Validator):
    @staticmethod
    def validate(value, field_object):
        if not isinstance(value, str):
            return

        match = re.fullmatch(r'(\d\d):(\d\d):(\d\d)', value)
        if not match:
            raise ValidationError('Wrong time format')
        else:
            hour, minute, second = map(int, match.groups())
            if hour not in range(0, 24):
                raise ValidationError('Wrong hour value')

            if minute not in range(0, 60):
                raise ValidationError('Wrong minute value')

            if second not in range(0, 60):
                raise ValidationError('Wrong second value')


class ValidateDate(Validator):
    @staticmethod
    def validate(value, field_object):
        if not isinstance(value, str):
            return

        match = re.fullmatch(r'(\d\d\d\d)-(\d\d)-(\d\d)', value)
        if not match:
            raise ValidationError('Wrong date format')
        else:
            year, month, day = map(int, match.groups())
            if year < 0:
                raise ValidationError('Wrong year value')

            if month not in range(1, 12 + 1):
                raise ValidationError('Wrong month value')

            if month == 2:
                if year % 4 == 0 and year % 100 != 0 or year % 400 == 0:
                    febr_range = range(1, 29 + 1)
                else:
                    febr_range = range(1, 28 + 1)
                if day not in febr_range:
                    raise ValidationError('Wrong day value')
            else:
                days_count = {
                    1: 31, 3: 31, 4: 30, 5: 31,
                    6: 30, 7: 31, 8: 31, 9: 30,
                    10: 31, 11: 30, 12: 31
                }.get(month)
                if day not in range(1, days_count + 1):
                    raise ValidationError('Wrong day value')


class ValidateDatetime(Validator):
    @staticmethod
    def validate(value, field_object):
        if not isinstance(value, str):
            return

        datetime = value.split()
        if len(datetime) != 2:
            raise ValidationError('Wrong datetime format')
        else:
            ValidateDate.validate(datetime[0], {})
            ValidateTime.validate(datetime[1], {})