File: usage.rst

package info (click to toggle)
python-cerberus 1.3.7-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 7,532 kB
  • sloc: python: 5,239; makefile: 130
file content (266 lines) | stat: -rw-r--r-- 7,286 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
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
Cerberus Usage
==============

Basic Usage
-----------
You define a validation schema and pass it to an instance of the
:class:`~cerberus.Validator` class:

.. doctest::

    >>> schema = {'name': {'type': 'string'}}
    >>> v = Validator(schema)

Then you simply invoke the :meth:`~cerberus.Validator.validate` to validate
a dictionary against the schema. If validation succeeds, ``True`` is returned:

.. testsetup::

    schema = {'name': {'type': 'string'}}
    v = Validator(schema)
    document = {'name': 'john doe'}

.. doctest::

    >>> document = {'name': 'john doe'}
    >>> v.validate(document)
    True

Alternatively, you can pass both the dictionary and the schema to the
:meth:`~cerberus.Validator.validate` method:

.. doctest::

    >>> v = Validator()
    >>> v.validate(document, schema)
    True

Which can be handy if your schema is changing through the life of the
instance.

Details about validation schemas are covered in :doc:`schemas`.
See :doc:`validation-rules` and :doc:`normalization-rules` for an extensive
documentation of all supported rules.

Unlike other validation tools, Cerberus will not halt and raise an exception on
the first validation issue. The whole document will always be processed, and
``False`` will be returned if validation failed.  You can then access the
:attr:`~cerberus.Validator.errors` property to obtain a list of issues. See
:doc:`Errors & Error Handling <errors>` for different output options.

.. doctest::

    >>> schema = {'name': {'type': 'string'}, 'age': {'type': 'integer', 'min': 10}}
    >>> document = {'name': 'Little Joe', 'age': 5}
    >>> v.validate(document, schema)
    False
    >>> v.errors
    {'age': ['min value is 10']}

A :exc:`~cerberus.DocumentError` is raised when the document is not a mapping.

The Validator class and its instances are callable, allowing for the following
shorthand syntax:

.. doctest::

    >>> document = {'name': 'john doe'}
    >>> v(document)
    True

.. versionadded:: 0.4.1


.. _allowing-the-unknown:

Allowing the Unknown
--------------------
By default only keys defined in the schema are allowed:

.. doctest::

    >>> schema = {'name': {'type': 'string', 'maxlength': 10}}
    >>> v.validate({'name': 'john', 'sex': 'M'}, schema)
    False
    >>> v.errors
    {'sex': ['unknown field']}

However, you can allow unknown document keys pairs by either setting
``allow_unknown`` to ``True``:

.. doctest::

    >>> v.schema = {}
    >>> v.allow_unknown = True
    >>> v.validate({'name': 'john', 'sex': 'M'})
    True

Or you can set ``allow_unknown`` to a validation schema, in which case
unknown fields will be validated against it:

.. doctest::

    >>> v.schema = {}
    >>> v.allow_unknown = {'type': 'string'}
    >>> v.validate({'an_unknown_field': 'john'})
    True
    >>> v.validate({'an_unknown_field': 1})
    False
    >>> v.errors
    {'an_unknown_field': ['must be of string type']}

``allow_unknown`` can also be set at initialization:

.. doctest::

    >>> v = Validator({}, allow_unknown=True)
    >>> v.validate({'name': 'john', 'sex': 'M'})
    True
    >>> v.allow_unknown = False
    >>> v.validate({'name': 'john', 'sex': 'M'})
    False

``allow_unknown`` can also be set as rule to configure a validator for a nested
mapping that is checked against the :ref:`schema <schema_dict-rule>` rule:

.. doctest::

    >>> v = Validator()
    >>> v.allow_unknown
    False

    >>> schema = {
    ...   'name': {'type': 'string'},
    ...   'a_dict': {
    ...     'type': 'dict',
    ...     'allow_unknown': True,  # this overrides the behaviour for
    ...     'schema': {             # the validation of this definition
    ...       'address': {'type': 'string'}
    ...     }
    ...   }
    ... }

    >>> v.validate({'name': 'john',
    ...             'a_dict': {'an_unknown_field': 'is allowed'}},
    ...            schema)
    True

    >>> # this fails as allow_unknown is still False for the parent document.
    >>> v.validate({'name': 'john',
    ...             'an_unknown_field': 'is not allowed',
    ...             'a_dict':{'an_unknown_field': 'is allowed'}},
    ...            schema)
    False

    >>> v.errors
    {'an_unknown_field': ['unknown field']}

.. versionchanged:: 0.9
   ``allow_unknown`` can also be set for nested dict fields.

.. versionchanged:: 0.8
   ``allow_unknown`` can also be set to a validation schema.


.. _requiring-all:

Requiring all
-------------

By default any keys defined in the schema are not required.
However, you can require all document keys pairs by setting
``require_all`` to ``True`` at validator initialization (``v = Validator(…, require_all=True)``)
or change it latter via attribute access (``v.require_all = True``).
``require_all`` can also be set :ref:`as rule <require_all>` to configure a
validator for a subdocument that is checked against the
:ref:`schema <schema_dict-rule>` rule:

.. doctest::

    >>> v = Validator()
    >>> v.require_all
    False

    >>> schema = {
    ...   'name': {'type': 'string'},
    ...   'a_dict': {
    ...     'type': 'dict',
    ...     'require_all': True,
    ...     'schema': {
    ...       'address': {'type': 'string'}
    ...     }
    ...   }
    ... }

    >>> v.validate({'name': 'foo', 'a_dict': {}}, schema)
    False
    >>> v.errors
    {'a_dict': [{'address': ['required field']}]}

    >>> v.validate({'a_dict': {'address': 'foobar'}}, schema)
    True

.. versionadded:: 1.3

Fetching Processed Documents
----------------------------

The normalization and coercion are performed on the copy of the original
document and the result document is available via ``document``-property.

.. doctest::

   >>> v.schema = {'amount': {'type': 'integer', 'coerce': int}}
   >>> v.validate({'amount': '1'})
   True
   >>> v.document
   {'amount': 1}

Beside the ``document``-property a ``Validator``-instance has shorthand methods
to process a document and fetch its processed result.

`validated` Method
~~~~~~~~~~~~~~~~~~
There's a wrapper-method :meth:`~cerberus.Validator.validated` that returns the
validated document. If the document didn't validate :obj:`None` is returned,
unless you call the method with the keyword argument ``always_return_document``
set to ``True``.
It can be useful for flows like this:

.. testsetup::

    documents = ()

.. testcode::

    v = Validator(schema)
    valid_documents = [x for x in [v.validated(y) for y in documents]
                       if x is not None]

If a coercion callable or method raises an exception then the exception will
be caught and the validation with fail.

.. versionadded:: 0.9

`normalized` Method
~~~~~~~~~~~~~~~~~~~
Similarly, the :meth:`~cerberus.Validator.normalized` method returns a
normalized copy of a document without validating it:

.. doctest::

    >>> schema = {'amount': {'coerce': int}}
    >>> document = {'model': 'consumerism', 'amount': '1'}
    >>> normalized_document = v.normalized(document, schema)
    >>> type(normalized_document['amount'])
    <class 'int'>

.. versionadded:: 1.0


Warnings
--------

Warnings, such as about deprecations or likely causes of trouble, are issued
through the Python standard library's :mod:`warnings` module. The logging
module can be configured to catch these :func:`logging.captureWarnings`.