trafaret — Validation atoms definition

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

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

class trafaret.Trafaret

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

append(converter)

Appends new converter to list.

check(value, convert=True)

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

converter(value)

You can change converter with >> operator or append method

class trafaret.Any
>>> Any()
<Any>
>>> (Any() >> ignore).check(object())
class trafaret.String(allow_blank=False, regex=None, 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(regex='\w+').check('wqerwqer')
'wqerwqer'
>>> String(allow_blank=True, regex='\w+').check('')
''
>>> extract_error(String(regex='^\w+$'), 'wqe rwqer')
"value does not match pattern: '^\\\\w+$'"
>>> 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'
class trafaret.List(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"}
class trafaret.Dict(*args, **trafarets)
>>> trafaret = Dict(foo=Int, bar=String) >> ignore
>>> trafaret.check({"foo": 1, "bar": "spam"})
>>> extract_error(trafaret, {"foo": 1, "bar": 2})
{'bar': 'value is not a string'}
>>> extract_error(trafaret, {"foo": 1})
{'bar': 'is required'}
>>> extract_error(trafaret, {"foo": 1, "bar": "spam", "eggs": None})
{'eggs': 'eggs is not allowed key'}
>>> trafaret.allow_extra("eggs")
<Dict(extras=(eggs) | bar=<String>, foo=<Int>)>
>>> trafaret.check({"foo": 1, "bar": "spam", "eggs": None})
>>> trafaret.check({"foo": 1, "bar": "spam"})
>>> extract_error(trafaret, {"foo": 1, "bar": "spam", "ham": 100})
{'ham': 'ham is not allowed key'}
>>> trafaret.allow_extra("*")
<Dict(any, extras=(eggs) | bar=<String>, foo=<Int>)>
>>> trafaret.check({"foo": 1, "bar": "spam", "ham": 100})
>>> trafaret.check({"foo": 1, "bar": "spam", "ham": 100, "baz": None})
>>> extract_error(trafaret, {"foo": 1, "ham": 100, "baz": None})
{'bar': 'is required'}
>>> trafaret = Dict({Key('bar', optional=True): String}, foo=Int)
>>> trafaret.allow_extra("*")
<Dict(any | bar=<String>, foo=<Int>)>
>>> _dd(trafaret.check({"foo": 1, "ham": 100, "baz": None}))
"{'baz': None, 'foo': 1, 'ham': 100}"
>>> _dd(extract_error(trafaret, {"bar": 1, "ham": 100, "baz": None}))
"{'bar': 'value is not a string', 'foo': 'is required'}"
>>> extract_error(trafaret, {"foo": 1, "bar": 1, "ham": 100, "baz": None})
{'bar': 'value is not a string'}
>>> trafaret = Dict({Key('bar', default='nyanya') >> 'baz': String}, foo=Int)
>>> _dd(trafaret.check({'foo': 4}))
"{'baz': 'nyanya', 'foo': 4}"
>>> _ = trafaret.ignore_extra('fooz')
>>> _dd(trafaret.check({'foo': 4, 'fooz': 5}))
"{'baz': 'nyanya', 'foo': 4}"
>>> _ = trafaret.ignore_extra('*')
>>> _dd(trafaret.check({'foo': 4, 'foor': 5}))
"{'baz': 'nyanya', 'foo': 4}"
merge(other)

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

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'}
class trafaret.And(trafaret, other, disable_old_check_convert=False)

Will work over trafarets sequentially

class trafaret.Null
>>> Null()
<Null>
>>> Null().check(None)
>>> extract_error(Null(), 1)
'value should be None'
class trafaret.Float(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.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"
class trafaret.Callable
>>> (Callable() >> ignore).check(lambda: 1)
>>> extract_error(Callable(), 1)
'value is not callable'
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.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.Bool
>>> Bool()
<Bool>
>>> Bool().check(True)
True
>>> Bool().check(False)
False
>>> extract_error(Bool(), 1)
'value should be True or 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'
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)).

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:

fn(*args, **kwargs)
    guarded with <Dict(a=<String>, b=<Int>, c=<String>)>

    docstring

>>> 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.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, Maybe(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(data, default):
        return data.get_all(self.name, default)
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'"
class trafaret.Email(allow_blank=False)
>>> Email().check('someone@example.net')
'someone@example.net'
>>> extract_error(Email(),'someone@example') # try without domain-part
'value is not a valid email address'
>>> str(Email().check('someone@пример.рф')) # try with `idna` encoding
'someone@xn--e1afmkfd.xn--p1ai'
>>> (Email() >> (lambda m: m.groupdict()['domain'])).check('someone@example.net')
'example.net'
>>> extract_error(Email(), 'foo')
'value is not a valid email address'
>>> extract_error(Email(), 'f' * 10000 + '@correct.domain.edu')
'value is not a valid email address'
>>> extract_error(Email(), 'f' * 248 + '@x.edu') == 'f' * 248 + '@x.edu'
True
class trafaret.URL(allow_blank=False)
>>> URL().check('http://example.net/resource/?param=value#anchor')
'http://example.net/resource/?param=value#anchor'
>>> str(URL().check('http://пример.рф/resource/?param=value#anchor'))
'http://xn--e1afmkfd.xn--p1ai/resource/?param=value#anchor'