Welcome to Trafaret’s documentation!

Contents:

Introducing trafaret

Trafaret is validation library with support to convert data structures. Sample usage:

import datetime
import trafaret as t

date = t.Dict(year=t.Int, month=t.Int, day=t.Int) >> (lambda d: datetime.datetime(**d))
assert date.check({'year': 2012, 'month': 1, 'day': 12}) == datetime.datetime(2012, 1, 12)

t.Dict creates new dict structure validator with three t.Int elements. >> operation adds lambda function to the converters of given checker. Some checkers have default converter, but when you use >> or .append, you disable default converter with your own.

This does not mean that Int will not convert numbers to int, this mean that some checkers, like String with regular expression, have special converters applied to that can be overriden by your own.

Converters can be chained. You can raise DataError in converters.

Features

Trafaret has very handy features, read below some samples.

Regexp

RegexpRow can work with regular expressions, and this givs you real power:

>>> c = t.RegexpRow(r'^name=(\w+)$') >> (lambda m: m.groups()[0])
>>> c.check('name=Jeff')
'Jeff'

Some way you can use all re.Match power to extract from strings dicts and so on.

Dict and Key

Dict get dict with keys and checkers, like {'a': t.Int}. But instead of string key you can use Key class. And Key instance can rename given key name to something else:

>>> c = t.Dict({t.Key('uNJ') >> 'user_name': t.String})
>>> c.check({'uNJ': 'Adam'})
{'user_name': 'Adam'}

And we can do more with right converter:

>>> from trafaret.utils import fold
>>> c = t.Dict({t.Key('uNJ') >> 'user__name': t.String}) >> fold
>>> c.check({'uNJ': 'Adam'})
{'user': {'name': 'Adam'}}

We have some example of enhanced Key in extras:

>>> from trafaret.extras import KeysSubset
>>> cmp_pwds = lambda x: {'pwd': x['pwd'] if x.get('pwd') == x.get('pwd1') else DataError('Not equal')}
>>> d = Dict({KeysSubset('pwd', 'pwd1'): cmp_pwds, 'key1': String})
>>> d.check({'pwd': 'a', 'pwd1': 'a', 'key1': 'b'}).keys()
{'pwd': 'a', 'key1': 'b'}

DataError

Exception class that used in library. Exception hold errors in error attribute. For simple checkers it will be just a string. For nested structures it will be dict instance.

Trafaret

Base class for checkers. Use it to make new checkers. In derrived classes you need to implement _check or _check_val methods. _check_val must return value, _check must return None on success.

You can implement converter method if you want to convert value somehow, but want to make free for developer to apply his own converters to raw data. This used to return strings instead of Match object in String trafaret.

Subclassing

For your own trafaret creation you need to subclass Trafaret class and implement check_value or check_and_return methods. check_value can return nothing on success, check_and_return must return value. In case of failure you need to raise DataError. You can use self._failure shortcut function to do this. Check library code for samples.

Type

Checks that data is instance of given class. Just instantitate it with any class, like int, float, str. Sample:

>>> t.Type(int).check(4)
4

Any

Will match any element.

Or

Get other converters as args. This samples are equivalent:

>>> Or(t.Int, t.Null).check(None)
None
>>> (t.Int | t.Null).check(5)
5

Null

Value must be None.

Bool

Check if value is boolean:

>>> t.Bool().check(True)
True

Float

Check if value is float or can be converted to. Supports lte, gte, lt, gt parameters:

>>> t.Float(gt=3.5).check(4)
4

Int

Similar to Float, but checking for int:

>>> t.Int(gt=3).check(4)
4

Atom

Value must be exactly equal to Atom first arg:

>>> t.Atom('this_key_must_be_this').check('this_key_must_be_this')
'this_key_must_be_this'

This may be useful in Dict in pair with Or statements.

String, Email, URL

Basicaly just check that arg is string. Argument allow_blank indicates if string can be blank ot not. If you will provide regex param - will return re.Match object. Default converter will return match.group() result. You will get re.Match object in converter.

Email and URL just provide regular expressions and a bit of logic for IDNA domains. Default converters return email and domain, but you will get re.Match in converter.

So, some examples to make things clear:

>>> t.String().check('werwerwer')
'werwerwer'
>>> t.String(regex='^\s+$).check('   ')
'   '
>>> t.String(regex='^name=(\w+)$').check('name=Jeff')
'Jeff'

And one wild sample:

>>> todt = lambda  m: datetime(*[int(i) for i in m.groups()])
>>> (t.String(regex='^year=(\d+),month=(\d+),day=(\d+)$') >> todt).check('year=2011,month=07,day=23')
datetime.datetime(2011, 7, 23, 0, 0)

List

Just List of elements of one type. In converter you will get list of converted elements. Sample:

>>> t.List(t.Int).check(range(100))
[0, 1, 2, ... 99]
>>> t.extract_error(t.List(t.Int).check(['a']))
{0: 'value cant be converted to int'}

Dict

Dict include named params. You can use for keys plain strings and Key instances. In case you provide just string keys, they will converted to Key instances. Actual checking proceeded in Key instance.

Methods:

allow_extra(*names) : where names can be key names or * to allow any additional keys.

make_optional(*names) : where names can be key names or * to make all options optional.

ignore_extra(*names): where names are the names of the keys or * to exclude listed key names or all unspecified ones from the validation process and final result

merge(Dict|dict|[t.Key...]) : where argument can be other Dict, dict like provided to Dict, or list of Key``s. Also provided as ``__add__, so you can add Dict``s, like ``dict1 + dict2.

Key

Special class to create dict keys. Parameters are:

  • name - key name
  • default - default if key is not present
  • optional - if True allow to not provide arg
  • to_name - instead of key name will be returned this key
You can provide to_name with >> operation::
Key(‘javaStyleData’) >> ‘plain_cool_data’

It provides method __call__(self, 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(self, 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)

t.Dict({MDKey('users'): t.List(t.String)})

Moreover, instead of Key you can use any callable, say function:

def simple_key(value):
    yield 'simple', 'simple data', []

check_args = t.Dict(simple_key)

KeysSubset

Experimental feature, not stable API. Sometimes you need to make something with part of dict keys. So you can:

>>> join = (lambda d: {'name': ' '.join(d.values())})
>>> Dict({KeysSubset('name', 'last'): join}).check({'name': 'Adam', 'last': 'Smith'})
{'name': 'Smith Adam'}

As you can see you need to return dict from checker.

Error raise

In Dict you can just return error from checkers or converters, there is need not to raise them.

Mapping

Check both keys and values:

>>> trafaret = Mapping(String, Int)
>>> trafaret
<Mapping(<String> => <Int>)>
>>> trafaret.check({"foo": 1, "bar": 2})
{'foo': 1, 'bar': 2}

Enum

This checker check that value one from provided. Like::
>>> Enum(1, 2, 'error').check(2)
2

Callable

Check if data is callable.

Call

Take a function that will be called in check. Function must return value or DataError.

Forward

This checker is container for any checker, that you can provide later. To provide container use provide method or << operation:

>> node = Forward()
>> node << Dict(name=String, children=List[node])

guard

Decorator for function:

>>> @guard(a=String, b=Int, c=String)
... def fn(a, b, c="default"):
...     '''docstring'''
...     return (a, b, c)

GuardError

Derived from DataError.

Changelog

2017-05-12

  • removed entrypoint magic
  • 0.10.0

2017-03-25 0.9.0

  • added And trafaret and & shortcut operation.
  • change >> behaviour. From now on Trafaret does not use self.converters and use And trafaret instead
  • added RegxpRaw and Regexp trafarets. RegexpRaw returns re.Match object and Regexp returns match string.
  • deprecate String regex argument in favor to Regexp and RegexpRaw usage
  • Dict now takes allow_extra, allow_extra_trafaret and ignore_extra keyword arguments as preferred alternative to methods

0.8.1

  • added trafaret.constructor. Now you can use construct and C from this package.

2016-09-25

Added trafaret argument to DataError constructor and made _failure a method (rather than static method)

2016-08-03

Added Subclass trafaret.

2016-03-31

Fixed loading contrib modules, so now original contrib module loading exception will be raised on contrib Trafaret access. Added value option to internal _failure interface, and option value to DataError.as_dict method.

2016-03-18

Fixed Key default behaviour for Dict with allowed extra when names are the same in Key and in data source

2014-09-17

Fixed Email validator

2012-05-30

Renamed methods to check_value and check_and_return. Added Tuple trafaret.

2012-05-28

Fixed Dict(...).make_optional(...) method for a chaining support

2012-05-21

Updated KeysSubSet errors propagation - now you can return error either {‘a’: DataError(‘message’)}, or DataError({‘a’: ‘message’})

2012-05-16

Added __call__ alias to check.

2012-05-11

Added visitor module.

2012-05-10

Fixed Dict.allow_extra behaviour.

2012-04-12

Int will not convert not-rounded floats like 2.2

Dict have .ignore_extra method, similar to .allow_extra, but given keys will not included to result dict. If you will provide *, any extra will be ignored.

API docs

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'

trafaret.extras — structs for trafaret structures extended definition

class trafaret.extras.KeysSubset(*keys)

From checkers and converters dict must be returned. Some for errors.

>>> from . import extract_error, Mapping, String
>>> cmp_pwds = lambda x: {'pwd': x['pwd'] if x.get('pwd') == x.get('pwd1') else DataError('Not equal')}
>>> d = Dict({KeysSubset('pwd', 'pwd1'): cmp_pwds, 'key1': String})
>>> sorted(d.check({'pwd': 'a', 'pwd1': 'a', 'key1': 'b'}).keys())
['key1', 'pwd']
>>> extract_error(d.check, {'pwd': 'a', 'pwd1': 'c', 'key1': 'b'})
{'pwd': 'Not equal'}
>>> extract_error(d.check, {'pwd': 'a', 'pwd1': None, 'key1': 'b'})
{'pwd': 'Not equal'}
>>> get_values = (lambda d, keys: [d[k] for k in keys if k in d])
>>> join = (lambda d: {'name': ' '.join(get_values(d, ['name', 'last']))})
>>> Dict({KeysSubset('name', 'last'): join}).check({'name': 'Adam', 'last': 'Smith'})
{'name': 'Adam Smith'}
>>> Dict({KeysSubset(): Dict({'a': Any})}).check({'a': 3})
{'a': 3}

trafaret.utils — utils for unfolding netsted dict syntax

There will be small helpers to render forms with exist trafarets for DRY.

trafaret.utils.fold(data, prefix='', delimeter='__')
>>> _dd(fold({'a__a': 4}))
"{'a': {'a': 4}}"
>>> _dd(fold({'a__a': 4, 'a__b': 5}))
"{'a': {'a': 4, 'b': 5}}"
>>> _dd(fold({'a__1': 2, 'a__0': 1, 'a__2': 3}))
"{'a': [1, 2, 3]}"
>>> _dd(fold({'form__a__b': 5, 'form__a__a': 4}, 'form'))
"{'a': {'a': 4, 'b': 5}}"
>>> _dd(fold({'form__a__b': 5, 'form__a__a__0': 4, 'form__a__a__1': 7}, 'form'))
"{'a': {'a': [4, 7], 'b': 5}}"
>>> repr(fold({'form__1__b': 5, 'form__0__a__0': 4, 'form__0__a__1': 7}, 'form'))
"[{'a': [4, 7]}, {'b': 5}]"
trafaret.utils.unfold(data, prefix='', delimeter='__')
>>> _dd(unfold({'a': 4, 'b': 5}))
"{'a': 4, 'b': 5}"
>>> _dd(unfold({'a': [1, 2, 3]}))
"{'a__0': 1, 'a__1': 2, 'a__2': 3}"
>>> _dd(unfold({'a': {'a': 4, 'b': 5}}))
"{'a__a': 4, 'a__b': 5}"
>>> _dd(unfold({'a': {'a': 4, 'b': 5}}, 'form'))
"{'form__a__a': 4, 'form__a__b': 5}"

trafaret.visitor — methods to access object’s attribute/netsted key by path

This module is expirement. API and implementation are unstable. Supposed to use with Request object or something like that.

class trafaret.visitor.DeepKey(name, default=<object object>, optional=False, to_name=None, trafaret=None)

Lookup for attributes and items Path in name must be delimited by ..

>>> from trafaret import Int
>>> class A(object):
...     class B(object):
...         d = {'a': 'word'}
>>> dict((DeepKey('B.d.a') >> 'B_a').pop(A))
{'B_a': 'word'}
>>> dict((DeepKey('c.B.d.a') >> 'B_a').pop({'c': A}))
{'B_a': 'word'}
>>> dict((DeepKey('B.a') >> 'B_a').pop(A))
{'B.a': DataError(Unexistent key)}
>>> dict(DeepKey('c.B.d.a', to_name='B_a', trafaret=Int()).pop({'c': A}))
{'B_a': DataError(value can't be converted to int)}
class trafaret.visitor.Visitor(keys)

Check any object or mapping with DeepKey instances. This means that counts only existance and correctness of given paths. Visitor will not check for additional attributes etc.

trafaret.visitor.get_deep_attr(obj, keys)

Helper for DeepKey

trafaret.constructor — methods to access object’s attribute/netsted key by path

class trafaret.constructor.C

Start object. It has | and & operations defined that will use construct to it args

Use it like C & int & check_less_500

trafaret.constructor.construct(arg)

Shortcut syntax to define trafarets.

  • int, str, float and bool will return t.Int, t.String, t.Float and t.Bool
  • one element list will return t.List
  • tuple or list with several args will return t.Tuple
  • dict will return t.Dict. If key has ‘?’ at the and it will be optional and ‘?’ will be removed
  • any callable will be t.Call
  • otherwise it will be returned as is

construct is recursive and will try construct all lists, tuples and dicts args