summaryrefslogtreecommitdiff
path: root/src/zope/schema/_bootstrapinterfaces.py
blob: 8bddae1f9ba4d0e5792177acaee5524a5e64528d (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
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
##############################################################################
#
# Copyright (c) 2002 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Bootstrap schema interfaces and exceptions
"""
from functools import total_ordering

import zope.interface
from zope.interface import Attribute
from zope.interface.interfaces import IInterface

from zope.schema._messageid import _

# pylint:disable=inherit-non-class,keyword-arg-before-vararg,
# pylint:disable=no-self-argument


class StopValidation(Exception):
    """Raised if the validation is completed early.

    Note that this exception should be always caught, since it is just
    a way for the validator to save time.
    """


@total_ordering
class ValidationError(zope.interface.Invalid):
    """Raised if the Validation process fails."""

    #: The field that raised the error, if known.
    field = None

    #: The value that failed validation.
    value = None

    def with_field_and_value(self, field, value):
        self.field = field
        self.value = value
        return self

    def doc(self):
        return self.__class__.__doc__

    def __lt__(self, other):
        # There's no particular reason we choose to sort this way,
        # it's just the way we used to do it with __cmp__.
        if not hasattr(other, 'args'):
            return True
        return self.args < other.args

    def __eq__(self, other):
        if not hasattr(other, 'args'):
            return False
        return self.args == other.args

    # XXX : This is probably inconsistent with __eq__, which is
    # a violation of the language spec.
    __hash__ = zope.interface.Invalid.__hash__  # python3

    def __repr__(self):  # pragma: no cover
        return '%s(%s)' % (
            self.__class__.__name__,
            ', '.join(repr(arg) for arg in self.args))


class RequiredMissing(ValidationError):
    __doc__ = _("""Required input is missing.""")


class WrongType(ValidationError):
    __doc__ = _("""Object is of wrong type.""")

    #: The type or tuple of types that was expected.
    #:
    #: .. versionadded:: 4.7.0
    expected_type = None

    def __init__(self, value=None, expected_type=None, name=None, *args):
        """
        WrongType(value, expected_type, name)

        .. versionchanged:: 4.7.0
           Added named arguments to the constructor and the `expected_type`
           field.
        """
        ValidationError.__init__(self, value, expected_type, name, *args)
        self.expected_type = expected_type
        self.value = value


class OutOfBounds(ValidationError):
    """
    A value was out of the allowed bounds.

    This is the common superclass for `OrderableOutOfBounds` and
    `LenOutOfBounds`, which in turn are the superclasses for `TooBig`
    and `TooSmall`, and `TooLong` and `TooShort`, respectively.

    .. versionadded:: 4.7.0
    """

    #: The value that was exceeded
    bound = None

    #: A constant for `violation_direction`.
    TOO_LARGE = type('TOO_LARGE', (), {'__slots__': ()})()

    #: A constant for `violation_direction`.
    TOO_SMALL = type('TOO_SMALL', (), {'__slots__': ()})()

    #: Whether the value was too large or
    #: not large enough. One of the values
    #: defined by the constants `TOO_LARGE`
    #: or `TOO_SMALL`
    violation_direction = None

    def __init__(self, value=None, bound=None, *args):
        """
        OutOfBounds(value, bound)
        """
        super(OutOfBounds, self).__init__(value, bound, *args)
        self.value = value
        self.bound = bound


class OrderableOutOfBounds(OutOfBounds):
    """
    A value was too big or too small in comparison to another value.

    .. versionadded:: 4.7.0
    """


class TooBig(OrderableOutOfBounds):
    __doc__ = _("""Value is too big""")

    violation_direction = OutOfBounds.TOO_LARGE


class TooSmall(OrderableOutOfBounds):
    __doc__ = _("""Value is too small""")

    violation_direction = OutOfBounds.TOO_SMALL


class LenOutOfBounds(OutOfBounds):
    """
    The length of the value was out of bounds.

    .. versionadded:: 4.7.0
    """


class TooLong(LenOutOfBounds):
    __doc__ = _("""Value is too long""")

    violation_direction = OutOfBounds.TOO_LARGE


class TooShort(LenOutOfBounds):
    __doc__ = _("""Value is too short""")

    violation_direction = OutOfBounds.TOO_SMALL


class InvalidValue(ValidationError):
    __doc__ = _("""Invalid value""")


class ConstraintNotSatisfied(ValidationError):
    __doc__ = _("""Constraint not satisfied""")


class NotAContainer(ValidationError):
    __doc__ = _("""Not a container""")


class NotAnIterator(ValidationError):
    __doc__ = _("""Not an iterator""")


class WrongContainedType(ValidationError):
    __doc__ = _("""Wrong contained type""")

    #: A collection of exceptions raised when validating
    #: the *value*.
    #:
    #: .. versionadded:: 4.7.0
    errors = ()

    def __init__(self, errors=None, name=None, *args):
        """
        WrongContainedType(errors, name)

        .. versionchanged:: 4.7.0
           Added named arguments to the constructor, and the `errors` property.
        """
        super(WrongContainedType, self).__init__(errors, name, *args)
        self.errors = errors


class SchemaNotCorrectlyImplemented(WrongContainedType):
    __doc__ = _("""An object failed schema or invariant validation.""")

    #: A dictionary mapping failed attribute names of the
    #: *value* to the underlying exception
    schema_errors = None

    #: A list of exceptions from validating the invariants
    #: of the schema.
    invariant_errors = ()

    def __init__(self, errors=None, name=None, schema_errors=None,
                 invariant_errors=(), *args):
        """
        SchemaNotCorrectlyImplemented(errors, name, schema_errors,
                                      invariant_errors)

        .. versionchanged:: 4.7.0
           Added named arguments to the constructor.
        """
        super(SchemaNotCorrectlyImplemented, self).__init__(
            errors, name, *args)
        self.schema_errors = schema_errors
        self.invariant_errors = invariant_errors


class SchemaNotFullyImplemented(ValidationError):
    __doc__ = _("""Schema not fully implemented""")


class SchemaNotProvided(ValidationError):
    __doc__ = _("""Schema not provided""")

    #: The interface that the *value* was supposed to provide,
    #: but does not.
    schema = None

    def __init__(self, schema=None, value=None, *args):
        """
        SchemaNotProvided(schema, value)

        .. versionchanged:: 4.7.0
           Added named arguments to the constructor and the `schema` property.
        """
        super(SchemaNotProvided, self).__init__(schema, value, *args)
        self.schema = schema
        self.value = value


class NotAnInterface(WrongType, SchemaNotProvided):
    """
    Object is not an interface.

    This is a `WrongType` exception for backwards compatibility with
    existing ``except`` clauses, but it is raised when
    ``IInterface.providedBy`` is not true, so it's also a
    `SchemaNotProvided`. The ``expected_type`` field is filled in as
    ``IInterface``; this is not actually a `type`, and
    ``isinstance(thing, IInterface)`` is always false.

    .. versionadded:: 4.7.0
    """

    expected_type = IInterface

    def __init__(self, value, name):
        super(NotAnInterface, self).__init__(value, IInterface, name)


class IFromUnicode(zope.interface.Interface):
    """Parse a unicode string to a value

    We will often adapt fields to this interface to support views and
    other applications that need to convert raw data as unicode
    values.
    """

    def fromUnicode(value):
        """Convert a unicode string to a value.
        """


class IFromBytes(zope.interface.Interface):
    """
    Parse a byte string to a value.

    If the string needs to be decoded, decoding is done using UTF-8.

    .. versionadded:: 4.8.0
    """

    def fromBytes(value):
        """Convert a byte string to a value.
        """


class IContextAwareDefaultFactory(zope.interface.Interface):
    """A default factory that requires a context.

    The context is the field context. If the field is not bound, context may
    be ``None``.
    """

    def __call__(context):
        """Returns a default value for the field."""


class IBeforeObjectAssignedEvent(zope.interface.Interface):
    """An object is going to be assigned to an attribute on another object.

    Subscribers to this event can change the object on this event to change
    what object is going to be assigned. This is useful, e.g. for wrapping
    or replacing objects before they get assigned to conform to application
    policy.
    """

    object = Attribute("The object that is going to be assigned.")

    name = Attribute("The name of the attribute under which the object "
                     "will be assigned.")

    context = Attribute("The context object where the object will be "
                        "assigned to.")


class IValidatable(zope.interface.Interface):
    # Internal interface, the base for IField, but used to prevent
    # import recursion. This should *not* be implemented by anything
    # other than IField.
    def validate(value):
        """Validate that the given value is a valid field value.

        Returns nothing but raises an error if the value is invalid.
        It checks everything specific to a Field and also checks
        with the additional constraint.
        """


class NO_VALUE(object):
    def __repr__(self):  # pragma: no cover
        return '<NO_VALUE>'


NO_VALUE = NO_VALUE()