1
===================================
2
Validation Schema with validate.py
3
===================================
5
--------------------------
6
Using the Validator class
7
--------------------------
10
:Authors: `Michael Foord`_, `Nicola Larosa`_, `Mark Andrews`_
11
:Version: Validate 0.2.1
13
:Homepage: `Validate Homepage`_
14
:License: `BSD License`_
15
:Support: `Mailing List`_
17
.. _Mailing List: http://lists.sourceforge.net/lists/listinfo/configobj-develop
18
.. _Michael Foord: fuzzyman@voidspace.org.uk
19
.. _Nicola Larosa: nico@teknico.net
20
.. _Mark Andrews: mark@la-la.com
22
.. _Validate Homepage: http://www.voidspace.org.uk/python/validate.html
23
.. _BSD License: http://www.voidspace.org.uk/python/license.shtml
26
.. contents:: Validate Manual
31
Validation is used to check that supplied values conform to a specification.
33
The value can be supplied as a string, e.g. from a config file. In this case
34
the check will also *convert* the value to the required type. This allows you
35
to add validation as a transparent layer to access data stored as strings. The
36
validation checks that the data is correct *and* converts it to the expected
39
Checks are also strings, and are easy to write. One generic system can be used
40
to validate information from different sources, via a single consistent
43
Checks look like function calls, and map to function calls. They can include
44
parameters and keyword arguments. These arguments are passed to the relevant
45
function by the ``Validator`` instance, along with the value being checked.
47
The syntax for checks also allows for specifying a default value. This default
48
value can be ``None``, no matter what the type of the check. This can be used
49
to indicate that a value was missing, and so holds no useful value.
51
Functions either return a new value, or raise an exception. See `Validator
52
Exceptions`_ for the low down on the exception classes that ``validate.py``
55
Some standard functions are provided, for basic data types; these come built
56
into every validator. Additional checks are easy to write: they can be provided
57
when the ``Validator`` is instantiated, or added afterwards.
59
Validate was primarily written to support ConfigObj_, but is designed to be
60
applicable to many other situations.
62
For support and bug reports please use the ConfigObj `Mailing List`_.
64
.. _ConfigObj: http://www.voidspace.org.uk/python/configobj.html
69
The current version is **0.2.1**, dated 16th December 2005.
71
You can get obtain validate in the following ways :
76
* validate.py_ from Voidspace
78
* configobj.zip from Voidspace - See the homepage of ConfigObj_ for the latest
79
version and download links.
81
This contains validate.py and `this document`_. (As well as ConfigObj_ and
82
the ConfigObj documentation).
84
* The latest development version can be obtained from the `Subversion Repository`_.
89
*configobj.zip* contains `this document`_ and full `API Docs`_, generated
90
automatically by EpyDoc_.
92
* You can view `this document`_ online as the `Validate Homepage`_.
94
* You can also browse the `API Docs`_ online.
99
Validate_ is also part of the Pythonutils_ set of modules. This contains
100
various other useful helper modules, and is required by many of the `Voidspace
103
.. _configobj.py: http://www.voidspace.org.uk/cgi-bin/voidspace/downman.py?file=configobj.py
104
.. _configobj.zip: http://www.voidspace.org.uk/cgi-bin/voidspace/downman.py?file=configobj-4.1.0.zip
105
.. _validate.py: http://www.voidspace.org.uk/cgi-bin/voidspace/downman.py?file=validate.py
106
.. _API Docs: http://www.voidspace.org.uk/python/configobj-api/
107
.. _Subversion Repository: http://svn.rest2web.python-hosting.com/branches/configobj4/
108
.. _Sourceforge: http://sourceforge.net/projects/configobj
109
.. _EpyDoc: http://epydoc.sourceforge.net
110
.. _pythonutils: http://www.voidspace.org.uk/python/pythonutils.html
111
.. _Voidspace Python Projects: http://www.voidspace.org.uk/python
112
.. _validate: http://www.voidspace.org.uk/python/validate.html
115
The standard functions
116
======================
118
The standard functions come built-in to every ``Validator`` instance. They work
119
with the following basic data types :
127
plus lists of these datatypes.
129
Adding additional checks is done through coding simple functions.
131
The full set of standard checks are :
133
:'integer': matches integer values (including negative). Takes optional 'min'
134
and 'max' arguments : ::
137
integer(3, 9) # any value from 3 to 9
138
integer(min=0) # any positive value
141
:'float': matches float values
142
Has the same parameters as the integer check.
144
:'bool': matches boolean values: ``True`` or ``False``.
145
Acceptable string values for True are : ::
149
Acceptable string values for False are : ::
153
Any other value raises an error.
155
:'string': matches any string. Takes optional keyword args 'min' and 'max' to
156
specify min and max length of string.
158
:'ip_addr': matches an Internet Protocol address, v.4, represented by a
159
dotted-quad string, i.e. '1.2.3.4'.
161
:'list': matches any list. Takes optional keyword args 'min', and 'max' to
162
specify min and max sizes of the list.
164
:'int_list': Matches a list of integers. Takes the same arguments as list.
166
:'float_list': Matches a list of floats. Takes the same arguments as list.
168
:'bool_list': Matches a list of boolean values. Takes the same arguments as
171
:'string_list': Matches a list of strings. Takes the same arguments as list.
173
:'ip_addr_list': Matches a list of IP addresses. Takes the same arguments as
176
:'mixed_list': Matches a list with different types in specific positions.
177
List size must match the number of arguments.
179
Each position can be one of : ::
181
int, str, bool, float, ip_addr
183
So to specify a list with two strings followed by two integers,
184
you write the check as : ::
186
mixed_list(str, str, int, int)
188
:'pass': matches everything: it never fails and the value is unchanged. It is
189
also the default if no check is specified.
191
:'option': matches any from a list of options.
192
You specify this test with : ::
194
option('option 1', 'option 2', 'option 3')
196
The following code will work without you having to specifically add the
203
from validate import Validator
206
newval1 = vtor.check('integer', value1)
207
newval2 = vtor.check('bool', value2)
214
Of course, if these checks fail they raise exceptions. So you should wrap
215
them in ``try...except`` blocks. Better still, use ConfigObj for a higher
222
Using ``Validator`` is very easy. It has one public attribute and one public
225
Shown below are the different steps in using ``Validator``.
227
The only additional thing you need to know, is about `Writing check
237
from validate import Validator
248
from validate import Validator
251
'check_name1': function1,
252
'check_name2': function2,
253
'check_name3': function3,
256
vtor = Validator(fdict)
260
The second method adds a set of your functions as soon as your validator is
261
created. They are stored in the ``vtor.functions`` dictionary. The 'key' you
262
give them in this dictionary is the name you use in your checks (not the
263
original function name).
265
Dictionary keys/functions you pass in can override the built-in ones if you
271
The code shown above, for adding functions on instantiation, has exactly the
272
same effect as the following code :
278
from validate import Validator
281
vtor.functions['check_name1'] = function1
282
vtor.functions['check_name2'] = function2
283
vtor.functions['check_name3'] = function3
287
``vtor.functions``is just a dictionary that maps names to functions, so we
288
could also have called ``vtor.functions.update(fdict)``.
293
As we've heard, the checks map to the names in the ``functions`` dictionary.
294
You've got a full list of `The standard functions`_ and the arguments they
297
If you're using ``Validator`` from ConfigObj, then your checks will look like
300
keyword = int_list(max=6)
302
but the check part will be identical .
307
If you're not using ``Validator`` from ConfigObj, then you'll need to call the
308
``check`` method yourself.
310
If the check fails then it will raise an exception, so you'll want to trap
311
that. Here's the basic example :
317
from validate import Validator, ValidateError
320
check = "integer(0, 9)"
323
newvalue = vtor.check(check, value)
324
except ValidateError:
325
print 'Check Failed.'
327
print 'Check passed.'
333
Although the value can be a string, if it represents a list it should
334
already have been turned into a list of strings.
340
Some values may not be available, and you may want to be able to specify a
341
default as part of the check.
343
You do this by passing the keyword ``missing=True`` to the ``check`` method, as
344
well as a ``default=value`` in the check. (Constructing these checks is done
345
automatically by ConfigObj: you only need to know about the ``default=value``
352
check1 = 'integer(default=50)'
353
check2 = 'option("val 1", "val 2", "val 3", default="val 1")'
355
assert vtor.check('', check1, missing=True) == 50
356
assert vtor.check('', check2, missing=True) == "val 1"
360
If you pass in ``missing=True`` to the check method, then the actual value is
361
ignored. If no default is specified in the check, a ``ValidateMissingValue``
362
exception is raised. If a default is specified then that is passed to the
365
If the check has ``default=None`` (case sensitive) then ``vtor.check`` will
366
*always* return ``None`` (the object). This makes it easy to tell your program
367
that this check contains no useful value when missing, i.e. the value is
368
optional, and may be omitted without harm.
374
It's possible that you would like your default value to be a list. It's even
375
possible that you will write your own check functions - and would like to pass
376
them keyword arguments as lists from within the check.
378
To avoid confusing syntax with commas and quotes you use a list constructor to
379
specify that keyword arguments are lists. This includes the ``default`` value.
380
This makes checks look something like : ::
382
checkname(default=list('val1', 'val2', 'val3'))
389
If you only use Validator through ConfigObj, it traps these Exceptions for
390
you. You will still need to know about them for writing your own check
393
``vtor.check`` indicates that the check has failed by raising an exception.
394
The appropriate error should be raised in the check function.
396
The base error class is ``ValidateError``. All errors (except for ``VdtParamError``)
397
raised are sub-classes of this.
399
If an unrecognised check is specified then ``VdtUnknownCheckError`` is
402
There are also ``VdtTypeError`` and ``VdtValueError``.
404
If incorrect parameters are passed to a check function then it will (or should)
405
raise ``VdtParamError``. As this indicates *programmer* error, rather than an error
406
in the value, it is a subclass of ``SyntaxError`` instead of ``ValidateError``.
410
This means it *won't* be caught by ConfigObj - but propagated instead.
412
If the value supplied is the wrong type, then the check should raise
413
``VdtTypeError``. e.g. the check requires the value to be an integer (or
414
representation of an integer) and something else was supplied.
416
If the value supplied is the right type, but an unacceptable value, then the
417
check should raise ``VdtValueError``. e.g. the check requires the value to
418
be an integer (or representation of an integer) less than ten and a higher
421
Both ``VdtTypeError`` and ``VdtValueError`` are initialised with the
422
incorrect value. In other words you raise them like this :
428
raise VdtTypeError(value)
430
raise VdtValueError(value)
434
``VdtValueError`` has the following subclasses, which should be raised if
435
they are more appropriate.
437
* ``VdtValueTooSmallError``
438
* ``VdtValueTooBigError``
439
* ``VdtValueTooShortError``
440
* ``VdtValueTooLongError``
442
Writing check functions
443
=======================
445
Writing check functions is easy.
447
The check function will receive the value as its first argument, followed by
448
any other parameters and keyword arguments.
450
If the check fails, it should raise a ``VdtTypeError`` or a
451
``VdtValueError`` (or an appropriate subclass).
453
All parameters and keyword arguments are *always* passed as strings. (Parsed
454
from the check string).
456
The value might be a string (or list of strings) and need
457
converting to the right type - alternatively it might already be a list of
458
integers. Our function needs to be able to handle either.
460
If the check passes then it should return the value (possibly converted to the
468
Here is an example function that requires a list of integers. Each integer
469
must be between 0 and 99.
471
It takes a single argument specifying the length of the list. (Which allows us
472
to use the same check in more than one place). If the length can't be converted
473
to an integer then we need to raise ``VdtParamError``.
475
Next we check that the value is a list. Anything else should raise a
476
``VdtTypeError``. The list should also have 'length' entries. If the list
477
has more or less entries then we will need to raise a
478
``VdtValueTooShortError`` or a ``VdtValueTooLongError``.
480
Then we need to check every entry in the list. Each entry should be an integer
481
between 0 and 99, or a string representation of an integer between 0 and 99.
482
Any other type is a ``VdtTypeError``, any other value is a
483
``VdtValueError`` (either too big, or too small).
489
def special_list(value, length):
491
Check that the supplied value is a list of integers,
492
with 'length' entries, and each entry between 0 and 99.
494
# length is supplied as a string
495
# we need to convert it to an integer
499
raise VdtParamError('length', length)
501
# Check the supplied value is a list
502
if not isinstance(value, list):
503
raise VdtTypeError(value)
505
# check the length of the list is correct
506
if len(value) > length:
507
raise VdtValueTooLongError(value)
508
elif len(value) < length:
509
raise VdtValueTooShortError(value)
511
# Next, check every member in the list
512
# converting strings as necessary
515
if not isinstance(entry, (str, unicode, int)):
516
# a value in the list
517
# is neither an integer nor a string
518
raise VdtTypeError(value)
519
elif isinstance(entry, (str, unicode)):
520
if not entry.isdigit():
521
raise VdtTypeError(value)
525
raise VdtValueTooSmallError(value)
527
raise VdtValueTooBigError(value)
530
# if we got this far, all is well
531
# return the new list
536
If you are only using validate from ConfigObj then the error type (*TooBig*,
537
*TooSmall*, etc) is lost - so you may only want to raise ``VdtValueError``.
541
If your function raises an exception that isn't a subclass of
542
``ValidateError``, then ConfigObj won't trap it. This means validation will
545
This is why our function starts by checking the type of the value. If we
546
are passed the wrong type (e.g. an integer rather than a list) we get a
547
``VdtTypeError`` rather than bombing out when we try to iterate over
550
If you are using validate in another circumstance you may want to create your
551
own subclasses of ``ValidateError``, that convey more specific information.
556
* A regex check function ?
557
* A timestamp check function ? (Using the ``parse`` function from ``DateUtil``).
558
* Allow triple quotes ? (getting a bit heavy for a regex)
565
Please file any bug reports to `Michael Foord`_ or the ConfigObj
568
If we could pull tuples out of arguments, it would be easier
569
to specify arguments for 'mixed_lists'.
574
2005/12/16 Version 0.2.1
575
-----------------------------
577
Fixed bug so we can handle keyword argument values with commas.
579
We now use a list constructor for passing list values to keyword arguments
580
(including ``default``) : ::
582
default=list("val", "val", "val")
584
Added the ``_test`` test. {sm;:-)}
586
Moved a function call outside a try...except block.
588
2005/08/18 Version 0.2.0
589
-----------------------------
591
Updated by `Michael Foord`_ and `Nicola Larosa`_
593
Does type conversion as well.
595
2005/02/01 Version 0.1.0
596
-----------------------------
598
Initial version developed by `Michael Foord`_
603
Rendering this document with docutils also needs the
604
textmacros module and the PySrc CSS stuff. See
605
http://www.voidspace.org.uk/python/firedrop2/textmacros.shtml
610
<a href="http://www.python.org">
611
<img src="images/powered_by_python.jpg" width="602" height="186" border="0" />
613
<a href="http://www.opensource.org">
614
<img src="images/osi-certified-120x100.gif" width="120" height="100" border="0" />
615
<br /><strong>Certified Open Source</strong>
618
<script type="text/javascript" language="JavaScript">var site="s16atlantibots"</script>
619
<script type="text/javascript" language="JavaScript1.2" src="http://s16.sitemeter.com/js/counter.js?site=s16atlantibots"></script>
621
<a href="http://s16.sitemeter.com/stats.asp?site=s16atlantibots">
622
<img src="http://s16.sitemeter.com/meter.asp?site=s16atlantibots" alt="Site Meter" border=0 />