trafaret — Validation atoms definition

exception trafaret.DataError(error=None, name=None, value=<object object>, trafaret=None, code=None)

Error with data preserve error can be a message or None if error raised in childs data can be anything

as_dict(value=False)

Use to_struct if need consistency

class trafaret.Trafaret

Base class for trafarets, provides only one method for trafaret validation failure reporting

check(value, context=None)

Common logic. In subclasses you need to implement check_value or check_and_return.

is_valid(value)

Allows to check value and get bool, is value valid or not.

class trafaret.Call(fn)
>>> def validator(value):
...     if value != "foo":
...         return DataError("I want only foo!")
...     return 'foo'
...
>>> trafaret = Call(validator)
>>> trafaret
<Call(validator)>
>>> trafaret.check("foo")
'foo'
>>> extract_error(trafaret, "bar")
'I want only foo!'
class trafaret.Or(*trafarets)
>>> nullString = Or(String, Null)
>>> nullString
<Or(<String>, <Null>)>
>>> nullString.check(None)
>>> nullString.check("test")
'test'
>>> extract_error(nullString, 1)
{0: 'value is not a string', 1: 'value should be None'}
>>> nullString.is_valid(None)
True
>>> nullString.is_valid("test")
True
>>> nullString.is_valid(1)
False
class trafaret.And(trafaret, other)

Will work over trafarets sequentially

class trafaret.Forward
>>> node = Forward()
>>> node << Dict(name=String, children=List[node])
>>> node
<Forward(<Dict(children=<List(<recur>)>, name=<String>)>)>
>>> node.check({"name": "foo", "children": []}) == {'children': [], 'name': 'foo'}
True
>>> extract_error(node, {"name": "foo", "children": [1]})
{'children': {0: 'value is not a dict'}}
>>> node.check({"name": "foo", "children": [                         {"name": "bar", "children": []}                      ]}) == {'children': [{'children': [], 'name': 'bar'}], 'name': 'foo'}
True
>>> empty_node = Forward()
>>> empty_node
<Forward(None)>
>>> extract_error(empty_node, 'something')
'trafaret not set yet'
class trafaret.Any
>>> Any()
<Any>
>>> (Any() >> ignore).check(object())
class trafaret.Null
>>> Null()
<Null>
>>> Null().check(None)
>>> extract_error(Null(), 1)
'value should be None'
>>> Null().is_valid(None)
True
>>> Null().is_valid(1)
False
class trafaret.Iterable(trafaret, min_length=0, max_length=None)
>>> List(Int)
<List(<Int>)>
>>> List(Int, min_length=1)
<List(min_length=1 | <Int>)>
>>> List(Int, min_length=1, max_length=10)
<List(min_length=1, max_length=10 | <Int>)>
>>> extract_error(List(Int), 1)
'value is not a list'
>>> List(Int).check([1, 2, 3])
[1, 2, 3]
>>> List(String).check(["foo", "bar", "spam"])
['foo', 'bar', 'spam']
>>> extract_error(List(Int), [1, 2, 1 + 3j])
{2: 'value is not int'}
>>> List(Int, min_length=1).check([1, 2, 3])
[1, 2, 3]
>>> extract_error(List(Int, min_length=1), [])
'list length is less than 1'
>>> List(Int, max_length=2).check([1, 2])
[1, 2]
>>> extract_error(List(Int, max_length=2), [1, 2, 3])
'list length is greater than 2'
>>> extract_error(List(Int), ["a"])
{0: "value can't be converted to int"}
>>> List(Int).is_valid([1, 2, 3])
True
>>> List(Int).is_valid(1)
False
class trafaret.List(trafaret, min_length=0, max_length=None)
class trafaret.Key(name, default=<object object>, optional=False, to_name=None, trafaret=None)

Helper class for Dict.

It gets name, and provides method extract(data) that extract key value from data through mapping get method. Key __call__ method yields (key name, result or DataError, [touched keys]) triples.

You can redefine get_data(data, default) method in subclassed Key if you want to use something other then .get(...) method.

Like this for the aiohttp MultiDict:

class MDKey(t.Key):
    def get_data(self, data, default):
        return data.getall(self.name, default)
class trafaret.Dict(*args, **trafarets)

Dict is a most complex trafaret that going with this library. The main difference from other common validation libs is that Dict trafaret does not know anything about actual keys. Every key that Dict works with knows itself how to get value from given mapping and if this will be one value or two or multi values.

So Dict cannot make any assumptions about whats going on other then contract with a key implementation. And we need to note, that any callable can be key, not only Key subclasses. So we need to look at the key contract:

key_instance(data: Mapping) -> Sequence[
    name_to_store,
    result or DataError,
    Sequence[touched keys],
]

It is a bit complex, so let me explain it to you. Every key instance get this data that Dict trying to check. Then key will return one or multiple results and it is common for key to be generator.

Every result is three component tuple
1. Key for the result dict. For standard Key it is result key in case of successful check or original key name if there was an error 2. Result if keys trafaret check was successful or DataError instance otherwise 3. An iterable with all keys of original mapping that this key touched

With this tricky interface key in our lib can do anything you can imagine. Like work with MultiDicts, compare keys, get subdicts and check them independently from main one.

Why we need this third extra iterable with touched names? Because our Dict can check that all keys were consumed and what to do with extras.

Arguments:

  • Dict accepts keys as *args
  • if first argument to Dict is a dict then its keys will be merged with args keys and this dict values must be trafarets. If key of this dict is a str, then Dict will create Key instance with this key as Key name and value as its trafaret. If key is a Key instance then Dict will call this key set_trafaret method.

allow_extra argument can be a list of keys, or ‘*’ for any, that will be checked against allow_extra_trafaret or Any.

ignore_extra argument can be a list of keys, or ‘*’ for any, that will be ignored.

allow_extra(*names, **kw)

multi arguments that represents attribute names or *. Will allow unconsumed by other keys attributes for given names or all if includes *. Also you can pass trafaret keyword argument to set Trafaret instance for this extra args, or it will be Any. Method creates Dict clone.

ignore_extra(*names)

multi arguments that represents attribute names or *. Will ignore unconsumed by other keys attribute names for given names or all if includes *. Method creates Dict clone.

merge(other)

Extends one Dict with other Dict Key`s or Key`s list, or dict instance supposed for Dict

class trafaret.Enum(*variants)
>>> trafaret = Enum("foo", "bar", 1) >> ignore
>>> trafaret
<Enum('foo', 'bar', 1)>
>>> trafaret.check("foo")
>>> trafaret.check(1)
>>> extract_error(trafaret, 2)
"value doesn't match any variant"
>>> trafaret.is_valid(1)
True
>>> trafaret.is_valid(2)
False
class trafaret.Tuple(*args)

Tuple checker can be used to check fixed tuples, like (Int, Int, String).

>>> t = Tuple(Int, Int, String)
>>> t.check([3, 4, '5'])
(3, 4, '5')
>>> extract_error(t, [3, 4, 5])
{2: 'value is not a string'}
>>> t
<Tuple(<Int>, <Int>, <String>)>
class trafaret.Atom(value)
>>> Atom('atom').check('atom')
'atom'
>>> extract_error(Atom('atom'), 'molecule')
"value is not exactly 'atom'"
>>> Atom('atom').is_valid('atom')
True
>>> Atom('atom').is_valid('molecule')
False
class trafaret.String(allow_blank=False, min_length=None, max_length=None)
>>> String()
<String>
>>> String(allow_blank=True)
<String(blank)>
>>> String().check("foo")
'foo'
>>> extract_error(String(), "")
'blank value is not allowed'
>>> String(allow_blank=True).check("")
''
>>> extract_error(String(), 1)
'value is not a string'
>>> String(min_length=2, max_length=3).check('123')
'123'
>>> extract_error(String(min_length=2, max_length=6), '1')
'String is shorter than 2 characters'
>>> extract_error(String(min_length=2, max_length=6), '1234567')
'String is longer than 6 characters'
>>> String(min_length=2, max_length=6, allow_blank=True)
Traceback (most recent call last):
...
AssertionError: Either allow_blank or min_length should be specified, not both
>>> String(min_length=0, max_length=6, allow_blank=True).check('123')
'123'
>>> String().is_valid("foo")
True
>>> String().is_valid("")
False
>>> String().is_valid(1)
False
str_type

alias of __builtin__.unicode

class trafaret.Date(format='%Y-%m-%d')

Checks that value is a datetime.date & datetime.datetime instances or a string that is convertable to datetime.date object.

>>> Date()
<Date %Y-%m-%d>
>>> Date('%y-%m-%d')
<Date %y-%m-%d>
>>> Date().check(date.today())
datetime.date(2019, 7, 25)
>>> Date().check(datetime.now())
datetime.datetime(2019, 10, 6, 14, 42, 52, 431348)
>>> Date().check("2019-07-25")
'2019, 7, 25'
>>> Date(format='%y-%m-%d').check('00-01-01')
'00-01-01'
>>> extract_error(Date(), "25-07-2019")
'value does not match format %Y-%m-%d'
>>> extract_error(Date(), 1564077758)
'value cannot be converted to date'
>>> Date().is_valid(date.today())
True
>>> Date().is_valid(1564077758)
False
class trafaret.ToDate(format='%Y-%m-%d')

Returns instance of datetime.date object if value is a string or datetime.date & datetime.datetime instances.

>>> ToDate().check(datetime.now())
datetime.date(2019, 10, 6)
>>> ToDate().check("2019-07-25")
datetime.date(2019, 7, 25)
>>> ToDate(format='%y-%m-%d').check('00-01-01')
datetime.date(2000, 1, 1)
class trafaret.DateTime(format='%Y-%m-%d %H:%M:%S')

Checks that value is a datetime.datetime instance or a string that is convertable to datetime.datetime object.

>>> DateTime()
<DateTime %Y-%m-%d %H:%M:%S>
>>> DateTime('%Y-%m-%d %H:%M')
<DateTime %Y-%m-%d %H:%M>
>>> DateTime().check(datetime.now())
datetime.datetime(2019, 7, 25, 21, 45, 37, 319284)
>>> DateTime('%Y-%m-%d %H:%M').check("2019-07-25 21:45")
'2019-07-25 21:45'
>>> extract_error(DateTime(), "2019-07-25")
'value does not match format %Y-%m-%d %H:%M:%S'
>>> extract_error(DateTime(), date.today())
'value cannot be converted to datetime'
>>> DateTime('%Y-%m-%d %H:%M').is_valid("2019-07-25 21:45")
True
>>> extract_error(DateTime(), "2019-07-25")
False
class trafaret.ToDateTime(format='%Y-%m-%d %H:%M:%S')

Returns instance of datetime.datetime object if value is a string or datetime.datetime instance.

>>> DateTime('%Y-%m-%d %H:%M').check("2019-07-25 21:45")
datetime.datetime(2019, 7, 25, 21, 45)
class trafaret.AnyString(allow_blank=False, min_length=None, max_length=None)
class trafaret.Bytes(allow_blank=False, min_length=None, max_length=None)
class trafaret.ToBytes(encoding='utf-8')

Get str and try to encode it with given encoding, utf-8 by default.

class trafaret.FromBytes(encoding='utf-8')

Get bytes and try to decode it with given encoding, utf-8 by default. It can be used like unicode_or_koi8r = String | FromBytes(encoding='koi8r')

class trafaret.Float(gte=None, lte=None, gt=None, lt=None)

Tests that value is a float or a string that is convertable to float.

>>> Float()
<Float>
>>> Float(gte=1)
<Float(gte=1)>
>>> Float(lte=10)
<Float(lte=10)>
>>> Float(gte=1, lte=10)
<Float(gte=1, lte=10)>
>>> Float().check(1.0)
1.0
>>> extract_error(Float(), 1 + 3j)
'value is not float'
>>> extract_error(Float(), 1)
1.0
>>> Float(gte=2).check(3.0)
3.0
>>> extract_error(Float(gte=2), 1.0)
'value is less than 2'
>>> Float(lte=10).check(5.0)
5.0
>>> extract_error(Float(lte=3), 5.0)
'value is greater than 3'
>>> Float().check("5.0")
5.0
value_type

alias of __builtin__.float

class trafaret.ToFloat(gte=None, lte=None, gt=None, lt=None)

Checks that value is a float. Or if value is a string converts this string to float

class trafaret.Int(gte=None, lte=None, gt=None, lt=None)
>>> Int()
<Int>
>>> Int().check(5)
5
>>> extract_error(Int(), 1.1)
'value is not int'
>>> extract_error(Int(), 1 + 1j)
'value is not int'
value_type

alias of __builtin__.int

class trafaret.ToInt(gte=None, lte=None, gt=None, lt=None)
class trafaret.ToDecimal(gte=None, lte=None, gt=None, lt=None)
value_type

alias of decimal.Decimal

class trafaret.Callable
>>> (Callable() >> ignore).check(lambda: 1)
>>> extract_error(Callable(), 1)
'value is not callable'
>>> (Callable() >> ignore).is_valid(lambda: 1)
True
>>> Callable().is_valid(1)
False
class trafaret.Bool
>>> Bool()
<Bool>
>>> Bool().check(True)
True
>>> Bool().check(False)
False
>>> extract_error(Bool(), 1)
'value should be True or False'
>>> Null().is_valid(True)
True
>>> Null().is_valid(False)
True
>>> Null().is_valid(1)
False
class trafaret.Type(type_)
>>> Type(int)
<Type(int)>
>>> Type[int]
<Type(int)>
>>> c = Type[int]
>>> c.check(1)
1
>>> extract_error(c, "foo")
'value is not int'
>>> c.is_valid("foo")
False
typing_checker()

isinstance(object, class-or-type-or-tuple) -> bool

Return whether an object is an instance of a class or of a subclass thereof. With a type as second argument, return whether that is the object’s type. The form using a tuple, isinstance(x, (A, B, …)), is a shortcut for isinstance(x, A) or isinstance(x, B) or … (etc.).

class trafaret.Subclass(type_)
>>> Subclass(type)
<Subclass(type)>
>>> Subclass[type]
<Subclass(type)>
>>> s = Subclass[type]
>>> s.check(type)
<type 'type'>
>>> extract_error(s, object)
'value is not subclass of type'
typing_checker()

issubclass(C, B) -> bool

Return whether class C is a subclass (i.e., a derived class) of class B. When using a tuple as the second argument issubclass(X, (A, B, …)), is a shortcut for issubclass(X, A) or issubclass(X, B) or … (etc.).

class trafaret.Mapping(key, value)

Mapping gets two trafarets as arguments, one for key and one for value, like Mapping(t.Int, t.List(t.Str)).

class trafaret.ToBool
>>> extract_error(ToBool(), 'aloha')
"value can't be converted to Bool"
>>> ToBool().check(1)
True
>>> ToBool().check(0)
False
>>> ToBool().check('y')
True
>>> ToBool().check('n')
False
>>> ToBool().check(None)
False
>>> ToBool().check('1')
True
>>> ToBool().check('0')
False
>>> ToBool().check('YeS')
True
>>> ToBool().check('No')
False
>>> ToBool().check(True)
True
>>> ToBool().check(False)
False
trafaret.DictKeys(keys)

Checks if dict has all given keys

Parameters:keys
trafaret.guard(trafaret=None, **kwargs)

Decorator for protecting function with trafarets

>>> @guard(a=String, b=Int, c=String)
... def fn(a, b, c="default"):
...     '''docstring'''
...     return (a, b, c)
...
>>> fn.__module__ = None
>>> help(fn)
Help on function fn:
<BLANKLINE>
fn(*args, **kwargs)
    guarded with <Dict(a=<String>, b=<Int>, c=<String>)>
<BLANKLINE>
    docstring
<BLANKLINE>
>>> fn("foo", 1)
('foo', 1, 'default')
>>> extract_error(fn, "foo", 1, 2)
{'c': 'value is not a string'}
>>> extract_error(fn, "foo")
{'b': 'is required'}
>>> g = guard(Dict())
>>> c = Forward()
>>> c << Dict(name=str, children=List[c])
>>> g = guard(c)
>>> g = guard(Int())
Traceback (most recent call last):
...
RuntimeError: trafaret should be instance of Dict or Forward
class trafaret.Regexp(regexp, re_flags=0)
class trafaret.RegexpRaw(regexp, re_flags=0)

Check if given string match given regexp

class trafaret.RegexpString(*args, **kwargs)
class trafaret.URLSafe(*args, **kwargs)
class trafaret.Hex(*args, **kwargs)
class trafaret.OnError(trafaret, message, code=None)
class trafaret.WithRepr(trafaret, representation)
trafaret.ensure_trafaret(trafaret)

Helper for complex trafarets, takes trafaret instance or class and returns trafaret instance

trafaret.extract_error(checker, *a, **kw)

Helper for tests - catch error and return it as dict

trafaret.ignore(val)

Stub to ignore value from trafaret Use it like:

>>> a = Int >> ignore
>>> a.check(7)
trafaret.catch(checker, *a, **kw)

Helper for tests - catch error and return it as dict

trafaret.catch_error(checker, *a, **kw)

Helper for tests - catch error and return it as dict