Trafaret

repository·master·Indexed 41 days ago

https://github.com/deepwalker/trafaret

A Python library for data validation and transformation designed for handling foreign data and configurations. It supports synchronous and asynchronous (aiohttp) workflows, providing a type-safe approach to validate and convert data structures using checkers like Dict, String, Float, and ToBool. It includes utilities for handling nested keys via trafaret.constructor and detailed error reporting through DataError.

Tokens
8.9K
Snippets
33
Records
37
Agent score
51%

What's inside Trafaret

  1. Overview of Trafaret

    master
    Trafaret is a transformation and validation library designed to work with foreign data and configurations. It allows you to define rigid rules to check data and transform it into the desired format. It supports contexts and is compatible with aiohttp via asynchronous checking. Key features include a shortcut syntax for building complex validators and the ability to generate Trafarets from JSON (via trafaret_schema).
  2. Resolve camelCase/snake_case conflicts using t.Key

    master

    To bridge the gap between JavaScript's camelCase and Python's snake_case, use t.Key within a t.Dict. This allows you to define the expected input key while renaming it to a preferred internal key during the .check() process.

    You can use the >> operator or the to_name argument.

    # Using the >> operator
    t.Dict({t.Key('userNameFirst') >> 'first_name': t.String})
    
    # Using the to_name argument
    t.Dict({t.Key('userNameFirst', to_name='first_name'): t.String})
  3. Combine checkers using Or (|)

    master

    You can combine multiple checkers so that the input is considered valid if any one of the checkers succeeds. The most common way to do this is using the bitwise OR operator |.

    # Using the | operator
    (t.Int | t.String).check('five')
    
    # Using the Or function
    Or(t.Int, t.String).check('1')
  4. Get started with Trafaret

    master

    Trafaret is a validation library that supports converting data structures during the validation process. You can define complex validators using built-in types like t.Int or t.Dict and combine them using the & operator. The & operator allows you to chain a validator with another trafaret or with a function to perform post-validation transformations (e.g., converting a dictionary of integers into a datetime.datetime object).

    To validate data, use the .check(data) method. If validation fails, it raises a t.DataError, which can be converted to a dictionary representation using e.as_dict() to identify specific missing or invalid fields.

    import datetime
    import trafaret as t
    
    # Define a validator that checks for year, month, and day, then converts to datetime
    date = t.Dict(year=t.Int, month=t.Int, day=t.Int) & (lambda d: datetime.datetime(**d))
    
    def validate_date(data):
        try:
            return date.check(data), False
        except t.DataError as e:
            return False, e.as_dict()
    
    # Example: Missing field
    print(validate_date({'year': 2012, 'month': 1}))
    # (False, {'day': 'is required'})
    
    # Example: Successful validation and conversion
    print(validate_date({'year': 2012, 'month': 1, 'day': 12}))
    # (datetime.datetime(2012, 1, 12, 0, 0), False)
  5. Handle web form data types with StrBool and custom converters

    master

    When receiving data from web forms, values are often sent as strings (e.g., "True" or "1, 2, 3"). Trafaret can automatically convert these into correct Python types using built-in types like t.StrBool or by passing a custom conversion function into a t.Dict or t.List definition.

    For example, you can use a custom function to split a comma-separated string into a list of strings.

    import trafaret as t
    
    def comma_to_list(text):
        """Convert string with words separated by comma to list."""
        return [
            s.strip() for s in text.split(',')
        ]
    
    create_book_chacker = t.Dict({
       'title': t.String,
       'authors': comma_to_list,
       'sold': t.StrBool,
    }) 
    
    # Example usage:
    # create_book_chacker.check({"title": 'Glue', 'authors': 'Welsh,', 'sold': 'True'})
    # Returns: {'title': 'Glue', 'authors': ['Welsh', ''], 'sold': True}
  6. Install trafaret from source

    master

    If you need to install from source, you can clone the repository or download the tarball. Once the source code is available locally, use setup.py to perform the installation.

    # Clone the repository
    $ git clone git://github.com/Deepwalker/trafaret
    
    # OR download the tarball
    $ curl -OL https://github.com/Deepwalker/trafaret/tarball/master
    
    # Install from the source directory
    $ python setup.py install
  7. Quickstart: Constructing validators with `construct()`

    master

    You can use trafaret.constructor.construct to quickly create a validator from a dictionary of types. This is useful for mapping keys to specific data types.

    Note: In version 2.0.2+, construct for int and float will automatically use ToInt and ToFloat respectively.

    from trafaret.constructor import construct
    validator = construct({'a': int, 'b': [str]})
    # Valid input
    print(validator({'a': 5, 'b': ['lorem', 'ipsum']}))
    # {'a': 5, 'b': ['lorem', 'ipsum']}
    
    # Invalid input raises DataError
    # validator({'a': 5, 'b': ['gorky', 9]})
  8. Implement a decorator for automatic validation error handling

    master

    In web frameworks like aiohttp, you can use a decorator to wrap handlers. This decorator catches t.DataError and automatically returns a JSON response containing the validation errors, preventing the need for repetitive try/except blocks in every handler.

    from functools import wraps
    import trafaret as t
    from aiohttp import web
    
    def with_error(fn):
        """
        Decorator for wrapping web handlers to represent 
        validation errors as JSON responses.
        """
        @wraps(fn)
        async def inner(*args, **kwargs):
            try:
                return await fn(*args, **kwargs)
            except t.DataError as e:
                return web.json_response({
                    'errors': e.as_dict(value=True)
                })
        return inner
    
    @with_error
    async def create_book(req):
        raw_data = await req.json()
        # If this fails, the decorator catches t.DataError
        data = create_book_chacker.check(raw_data)
        return web.json_response({"created": True})
  9. Transforming data with the `>>` operator

    master

    Trafaret allows you to chain a validator with a transformation function using the >> operator. This is useful for converting validated raw data (like a dictionary of date components) into a rich object (like a datetime object).

    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)
  10. Using Regex for validation and extraction

    master

    Use t.RegexpRaw to validate a string against a regular expression and then use the >> operator to extract specific groups from the match.

    import trafaret as t
    
    c = t.RegexpRaw(r'^name=(\w+)$') >> (lambda m: m.group(1))
    assert c.check('name=Jeff') == 'Jeff'
  11. Renaming dictionary keys during validation

    master

    You can use t.Key combined with the >> operator within a t.Dict to rename keys as the data is processed.

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