Metadata-Version: 1.1
Name: chainable-validators
Version: 0.3
Summary: Python data validation framework that uses chainable validator
Home-page: https://github.com/Outernet-Project/chainable-validators
Author: Outernet Inc
Author-email: apps@outernet.is
License: GPLv3
Description: ====================
        Chainable Validators
        ====================
        
        This package contains a set of simple functions to facilitate creation of
        chainable validator methods for developing data validation schemata.
        
        Although it provides a few validation function, it's main purpose is
        extensibility.
        
        Installing
        ==========
        
        The PyPI package name is ``chainable-validators``. You can install the package
        using ``pip`` or ``easy_install``::
        
            pip install chainable-validators
        
            easy_install chainable-validators
        
        Basic concepts
        ==============
        
        The basis of all validation are chainable validators (validation functions) and
        the validation chains which are created using ``make_chain()`` calls.
        
        The chainable validators are found in the ``validators.validators`` module. For
        convenience, they can be imported directly from the ``validators`` package::
        
            >>> from validators import required, istype, gte
        
        The chainable validators can be used stand-alone or as part of a chain. For
        standalone usage, pass the value to the validator. ::
        
            >>> required(None)
            Traceback (most recent call last):
            ...
            ValueError: required value missing
        
        Some validators are parametric. They are first invoked with a parameter, and
        the return value is then used as a chainable validator. ::
        
            >>> isint = istype(int)
            >>> isint('foo')
            Traceback (most recent call last):
            ...
            ValueError: not int
        
        To build a chain of desired validators, we first compile a list of chainable
        validators::
        
            >>> from validators import make_chain
            >>> fns = [required, istype(int), gte(2)]
            >>> chain = make_chain(fns)
            >>> chain(None)
            Traceback (most recent call last):
            ...
            ValueError: required value missing
            >>> chain('1')
            Traceback (most recent call last):
            ...
            ValueError: not int
            >>> chain(1)
            Traceback (most recent call last):
            ...
            ValueError: value too small
            >>> chain(3)
            3
        
        The validators in the chain are invoked in order until the last one is called,
        or ``ValueError`` or ``validators.ReturnEarly`` is raised. When no exceptions
        are raised, the return value of the last chainable validator is returned. In
        case ``ReturnEarly`` is raised, it is not propagated to the chain's caller, but
        instead the original value is returned.
        
        List of built-in validators
        ===========================
        
        The following is a list of built-in vaidators.
        
        Validators can be parametric or simple. Simple validators can be used directly.
        Parametric validators take an argument and return a chainable validator
        functions.
        
        In the list below, if you encounter a validator that looks like ``foo(bar)``,
        it's a parametric validator.
        
        - ``optional(default=None)`` - interrupts validation chain if value is None or
          a user-supplied default value
        - ``required`` - rejects None
        - ``nonemtpy`` - rejects empty sequences (string, list, dict)
        - ``boolean`` - reject non-boolean values (other than True, False, 1, and 0)
        - ``istype(t)`` - rejects values that are not of type ``t``
        - ``isin(collection)`` - rejects values that are not in ``collection``
          (collection is a sequence such as string, list, or dict)
        - ``gte(num)`` - rejects values that are not greater than or equal to ``num``
        - ``lte(num)`` - rejects values that are not less than or equal to ``num``
        - ``match(regex)`` - rejects values that do not match the ``regex`` object
          (``regex`` object is a valid ``re.RegExp`` instance or object with a
          ``match()`` method)
        - ``url`` - rejects values that are not URLs
        - ``timestamp(fmt)`` - rejects values that cannot be converted to ``datetime``
          using ``datetime.strptime()`` and given format string
        
        Helper functions
        ================
        
        There are a few helper functions that help you modify the behavior or one or
        more functions in the chain.
        
        - ``OR(*fns)`` - rejects value if and only if all of the functions passed to it
          fail to validate, otherwise passes
        - ``NOT(fn)`` - reverses the behavior of ``fn``
        
        For example::
        
            >>> my_chain = [foo, OR(bar, baz), NOT(fam)]
        
        This chain will validate using ``foo`` first, then either ``bar`` or ``baz``
        (whichever passes), then ``fam``, reversing the results of ``fam`` (if it
        raises, then the validation will succeed and vice versa).
        
        Spec validator
        ==============
        
        Another helper function, that is not mentioned in the previous section, is
        ``spec_validator()`` factory function. It takes a spec, which is a dict mapping
        key/attribute names to chains and returns a validator function that validates
        objects.
        
        Let's take a look at an example, and then explain things as we go::
        
            >>> import re
            >>> from validator import *
            >>> spec = {
            ...     'foo': [required, istype(int)],
            ...     'bar': [optional, match(re.compile(r'te.*')],
            ...     'baz': [optional, boolean]
            ... }
        
        Each key in spec represents the key we expect to find in the object. The key
        could be a dictionary key, list/tuple index, or an object attribute. It could
        also be an arbitrary value based on which the value will be extracted.
        
        The way keys map to values is defined by a key function which can be passed
        using the ``key`` argument. This function must accept a spec key name and
        return a function that returns the value given an object. The default key
        function is ``operator.itemgetter``. For example, if we have an object that as
        attributes we want to validate, we could create the validator like so::
        
            >>> import operator
            >>> attr_validator = spec_validator(spec, key=operator.attrgetter)
        
        Each key maps to an iterable which represents the validator chain. Chains are
        applied to values matching the key.
        
        The ``spec_validator()`` function returns a validator function. ::
        
            >>> validator = spec_validator(spec)
        
        When passed the object to be validated, the validator function returns a dict
        which maps keys to any ``ValueError`` exceptions raised by the individual
        chains. If data is valid, the dict is empty. ::
        
            >>> data = {'foo': 1, 'bar': 'test', 'baz': None}
            >>> validator(data)
            {}
            >>> data['foo'] = None
            >>> validator(data)
            {'foo': ValueError('required value is missing')}
        
        Thanks to this behavior, you can test whether object is valid, by testing if
        the returned dict is empty.
        
        Writing your own validators
        ===========================
        
        It is possible to write your own validators. To write a simple chainable
        validator, use the ``validators.chain.chainable`` decorator. ::
        
            >>> from validators import chainable
            >>> @chainable
            ... def my_validator(s):
            ...     if not s.startswith('foo'):
            ...         raise ValueError('does not start with foo')
            ...     return s
            ... 
            >>> my_validator('foobar')
            'foobar'
            >>> my_validator('barfoo')
            Traceback (most recent call last):
            ...
            ValueError: does not start with foo
        
        To write a parametric validator, define the chainable validator in a closure::
        
            >>> def my_parametric(start):
            ...     @chainable
            ...     def validator(s):
            ...         if not s.startswith(start):
            ...             raise ValueError('does not sart with {}'.format(start))
            ...         return s
            ...     return validator
            ... 
            >>> validator = my_parametric('baz')
            >>> validator('bazfoo')
            'bazfoo'
            >>> validator('foo')
            Traceback (most recent call last):
            ...
            ValueError: does not sart with baz
        
        Now you can use these validators in chains like other validators.
        
        Reporting bugs
        ==============
        
        Please report any bugs or feature requests to the `issue tracker`_.
        
        .. _issue tracker: https://github.com/Outernet-Project/chainable-validators/issues
        
Keywords: validation,framework,method chaining
Platform: UNKNOWN
Classifier: Development Status :: 3 - Alpha
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3.4
Classifier: Topic :: Utilities
