Package: chainable-validators
This package contains a set of simple functions to facilitate creation of
chainable validator methods for developing data validation schemata.Although it provides a few validation function, it’s main purpose is
extensibility.InstallingThe PyPI package name ischainable-validators. You can install the package
usingpiporeasy_install:pip install chainable-validators

easy_install chainable-validatorsBasic conceptsThe basis of all validation are chainable validators (validation functions) and
the validation chains which are created usingmake_chain()calls.The chainable validators are found in thevalidators.validatorsmodule. For
convenience, they can be imported directly from thevalidatorspackage:>>> from validators import required, istype, gteThe chainable validators can be used stand-alone or as part of a chain. For
standalone usage, pass the value to the validator.>>> required(None)
Traceback (most recent call last):
...
ValueError: required value missingSome validators are parametric. They are first invoked with a parameter, and
the return value is then used as a chainable validator.>>> isint = istype(int)
>>> isint('foo')
Traceback (most recent call last):
...
ValueError: not intTo build a chain of desired validators, we first compile a list of chainable
validators:>>> from validators import make_chain
>>> fns = [required, istype(int), gte(2)]
>>> chain = make_chain(fns)
>>> chain(None)
Traceback (most recent call last):
...
ValueError: required value missing
>>> chain('1')
Traceback (most recent call last):
...
ValueError: not int
>>> chain(1)
Traceback (most recent call last):
...
ValueError: value too small
>>> chain(3)
3The validators in the chain are invoked in order until the last one is called,
orValueErrororvalidators.ReturnEarlyis raised. When no exceptions
are raised, the return value of the last chainable validator is returned. In
caseReturnEarlyis raised, it is not propagated to the chain’s caller, but
instead the original value is returned.List of built-in validatorsThe following is a list of built-in vaidators.Validators can be parametric or simple. Simple validators can be used directly.
Parametric validators take an argument and return a chainable validator
functions.In the list below, if you encounter a validator that looks likefoo(bar),
it’s a parametric validator.optional(default=None)- interrupts validation chain if value is None or
a user-supplied default valuerequired- rejects Nonenonemtpy- rejects empty sequences (string, list, dict)boolean- reject non-boolean values (other than True, False, 1, and 0)istype(t)- rejects values that are not of typetisin(collection)- rejects values that are not incollection(collection is a sequence such as string, list, or dict)gte(num)- rejects values that are not greater than or equal tonumlte(num)- rejects values that are not less than or equal tonummatch(regex)- rejects values that do not match theregexobject
(regexobject is a validre.RegExpinstance or object with amatch()method)url- rejects values that are not URLstimestamp(fmt)- rejects values that cannot be converted todatetimeusingdatetime.strptime()and given format stringHelper functionsThere are a few helper functions that help you modify the behavior or one or
more functions in the chain.OR(*fns)- rejects value if and only if all of the functions passed to it
fail to validate, otherwise passesNOT(fn)- reverses the behavior offnFor example:>>> my_chain = [foo, OR(bar, baz), NOT(fam)]This chain will validate usingfoofirst, then eitherbarorbaz(whichever passes), thenfam, reversing the results offam(if it
raises, then the validation will succeed and vice versa).Spec validatorAnother helper function, that is not mentioned in the previous section, isspec_validator()factory function. It takes a spec, which is a dict mapping
key/attribute names to chains and returns a validator function that validates
objects.Let’s take a look at an example, and then explain things as we go:>>> import re
>>> from validator import *
>>> spec = {
...     'foo': [required, istype(int)],
...     'bar': [optional, match(re.compile(r'te.*')],
...     'baz': [optional, boolean]
... }Each key in spec represents the key we expect to find in the object. The key
could be a dictionary key, list/tuple index, or an object attribute. It could
also be an arbitrary value based on which the value will be extracted.The way keys map to values is defined by a key function which can be passed
using thekeyargument. This function must accept a spec key name and
return a function that returns the value given an object. The default key
function isoperator.itemgetter. For example, if we have an object that as
attributes we want to validate, we could create the validator like so:>>> import operator
>>> attr_validator = spec_validator(spec, key=operator.attrgetter)Each key maps to an iterable which represents the validator chain. Chains are
applied to values matching the key.Thespec_validator()function returns a validator function.>>> validator = spec_validator(spec)When passed the object to be validated, the validator function returns a dict
which maps keys to anyValueErrorexceptions raised by the individual
chains. If data is valid, the dict is empty.>>> data = {'foo': 1, 'bar': 'test', 'baz': None}
>>> validator(data)
{}
>>> data['foo'] = None
>>> validator(data)
{'foo': ValueError('required value is missing')}Thanks to this behavior, you can test whether object is valid, by testing if
the returned dict is empty.Writing your own validatorsIt is possible to write your own validators. To write a simple chainable
validator, use thevalidators.chain.chainabledecorator.>>> from validators import chainable
>>> @chainable
... def my_validator(s):
...     if not s.startswith('foo'):
...         raise ValueError('does not start with foo')
...     return s
...
>>> my_validator('foobar')
'foobar'
>>> my_validator('barfoo')
Traceback (most recent call last):
...
ValueError: does not start with fooTo write a parametric validator, define the chainable validator in a closure:>>> def my_parametric(start):
...     @chainable
...     def validator(s):
...         if not s.startswith(start):
...             raise ValueError('does not sart with {}'.format(start))
...         return s
...     return validator
...
>>> validator = my_parametric('baz')
>>> validator('bazfoo')
'bazfoo'
>>> validator('foo')
Traceback (most recent call last):
...
ValueError: does not sart with bazNow you can use these validators in chains like other validators.Reporting bugsPlease report any bugs or feature requests to theissue tracker.