#validict
Description
validict
is a Python module for comparing an unknown value to a desired template. It is intended for the top-level type to be a dict
, but should be flexible enough to deal with list
s or scalars (though if you're dealing at scalars, might I suggest running away from this and just using Python's isinstance
). Important: this library specifically does not treat tuple
s as template expectations but instead as a set of expectations for a given position in a template.
Usage
Install with pip.
shell~$ pip install validict
Using validict
is simple. First, declare your template:
from validict import validate
template = {
'name': str,
'age': int,
'pets': [
{
'name': str,
'kind': str
}
],
'parents': ([{'name': str}], int, None)
}
kid = {
'name': "Bart Simpson",
'age': 10,
'pets': [
{'name': "Santa's Little Helper", 'kind': "Dog"},
{'name': "Snowball II", 'kind': "Cat"}
],
'parents': [
{'name': "Homer Simpson"},
{'name': "Marge Simpson"}
]
}
validate(template, kid) # returns True
bad_kid = {
'name': "Nelson Muntz",
'age': 12
}
validate(template, bad_kid) # raises FailedValidationError
validate(template, bad_kid, quiet=True) # returns False
optional_kid = {
'name': "Milhouse Van Houten",
'age': 10,
'pets': [
{'name': "Lhasa Apso", 'kind': "Dog"}
],
'parents': None # Okay, not really, but for demonstration purposes...
}
validate(template, optional_kid) # returns True
You might be asking yourself -- or me -- "what the hell is this garbage?" Allow me to briefly explain, and you'll see that the template language is pretty simple.
-
We use plain, naked Python
type
s to indicate that the expected value for the given key should be an object of that type. So, if the passed-in dict has a value for'name'
that isn't astr
, validation fails. -
When we are expecting a
list
of elements, we only need to declare in our template one instance of that item, if thelist
's children are expected to be homogenous. Therefore,'pets'
is expected to be alist
ofdict
s, all containingstr
value for keys'name'
and'kind'
. -
We can use a
tuple
to declare that there may be multiple types of values, even including (but not demonstrated) further depth of structure. In the above, the value of'parents'
can be adict
with parents' names, anint
(perhaps representing the number of parents), orNone
(if you're Batman). -
Calling
validate
with the template and unvalidated value, positionally, will result either in a return value ofTrue
or a raise ofFailedValidationError
. -
Calling
validate
as above with the keyword parameterquiet=True
will returnFalse
instead of raisingFailedValidationError
on validation failure. -
Allowing a
None
type as adict
value or as a member of atuple
signifies that the value is optional. Using it in atuple
allows you to declare that the value can either be matching some type or otherwise can be nothing at all. -
(Undemonstrated) Your template can declare scalar values as well. So if all inputs must have some specific K/V pair, you can declare that.
Why do I want to use this?
If you're using a web framework like, say, Falcon and you wanted to set up a before hook to validate the body of the incoming HTTP request, the function in this method is for you. At least that's why it's for me.
Bonus!
There is an experimental (read: not heavily tested) function in this module called deep_merge
, which takes as its arguments two dictionaries. The second will be merged into the first, in a fashion such that keys are merged on every level instead of top-level key-values clobbering over all nested data.