File: validators.py

package info (click to toggle)
wtforms-components 0.11.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 352 kB
  • sloc: python: 1,582; makefile: 135; sh: 11
file content (180 lines) | stat: -rw-r--r-- 5,698 bytes parent folder | download
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
from validators import email
from wtforms import ValidationError
from wtforms.validators import StopValidation


class ControlStructure:
    """
    Base object for validator control structures
    """

    message = None

    def reraise(self, exc):
        if not self.message:
            raise exc
        else:
            raise type(exc)(self.message)


class Chain(ControlStructure):
    """
    Represents a chain of validators, useful when using multiple validators
    with If control structure.

    :param validators:
        list of validator objects
    :param message:
        custom validation error message, if this message is set and some of the
        child validators raise a ValidationError, an exception is being raised
        again with this custom message.
    """

    def __init__(self, validators, message=None):
        self.validators = validators
        if message:
            self.message = message

    def __call__(self, form, field):
        for validator in self.validators:
            try:
                validator(form, field)
            except ValidationError as exc:
                self.reraise(exc)
            except StopValidation as exc:
                self.reraise(exc)


class If(ControlStructure):
    """
    Conditional validator.

    :param condition: callable which takes two arguments form and field
    :param validator: encapsulated validator, this validator is validated
                      only if given condition returns true
    :param message: custom message, which overrides child validator's
                    validation error message
    """

    def __init__(self, condition, validator, message=None):
        self.condition = condition
        self.validator = validator

        if message:
            self.message = message

    def __call__(self, form, field):
        if self.condition(form, field):
            try:
                self.validator(form, field)
            except ValidationError as exc:
                self.reraise(exc)
            except StopValidation as exc:
                self.reraise(exc)


class BaseDateTimeRange:
    def __init__(self, min=None, max=None, format="%H:%M", message=None):
        self.min = min
        self.max = max
        self.format = format
        self.message = message

    def __call__(self, form, field):
        data = field.data
        min_ = self.min() if callable(self.min) else self.min
        max_ = self.max() if callable(self.max) else self.max
        if (
            data is None
            or (min_ is not None and data < min_)
            or (max_ is not None and data > max_)
        ):
            if self.message is None:
                if max_ is None:
                    self.message = field.gettext(self.greater_than_msg)
                elif min_ is None:
                    self.message = field.gettext(self.less_than_msg)
                else:
                    self.message = field.gettext(self.between_msg)

            raise ValidationError(
                self.message
                % dict(
                    field_label=field.label,
                    min=min_.strftime(self.format) if min_ else "",
                    max=max_.strftime(self.format) if max_ else "",
                )
            )


class TimeRange(BaseDateTimeRange):
    """
    Same as wtforms.validators.NumberRange but validates date.

    :param min:
        The minimum required value of the time. If not provided, minimum
        value will not be checked.
    :param max:
        The maximum value of the time. If not provided, maximum value
        will not be checked.
    :param message:
        Error message to raise in case of a validation error. Can be
        interpolated using `%(min)s` and `%(max)s` if desired. Useful defaults
        are provided depending on the existence of min and max.
    """

    greater_than_msg = "Time must be greater than %(min)s."

    less_than_msg = "Time must be less than %(max)s."

    between_msg = "Time must be between %(min)s and %(max)s."

    def __init__(self, min=None, max=None, format="%H:%M", message=None):
        super().__init__(min=min, max=max, format=format, message=message)


class DateRange(BaseDateTimeRange):
    """
    Same as wtforms.validators.NumberRange but validates date.

    :param min:
        The minimum required value of the date. If not provided, minimum
        value will not be checked.
    :param max:
        The maximum value of the date. If not provided, maximum value
        will not be checked.
    :param message:
        Error message to raise in case of a validation error. Can be
        interpolated using `%(min)s` and `%(max)s` if desired. Useful defaults
        are provided depending on the existence of min and max.
    """

    greater_than_msg = "Date must be equal to or later than %(min)s."

    less_than_msg = "Date must be equal to or earlier than %(max)s."

    between_msg = "Date must be between %(min)s and %(max)s."

    def __init__(self, min=None, max=None, format="%Y-%m-%d", message=None):
        super().__init__(min=min, max=max, format=format, message=message)


class Email:
    """
    Validates an email address.
    This validator is is stricter than the standard email
    validator included in WTForms.

    :param message:
        Error message to raise in case of a validation error.
    """

    def __init__(self, message=None):
        self.message = message

    def __call__(self, form, field):
        if not email(field.data):
            message = self.message
            if message is None:
                message = field.gettext("Invalid email address.")
            raise ValidationError(message)