summaryrefslogtreecommitdiffstats
path: root/venv/lib/python3.9/site-packages/validators/utils.py
blob: 3044477be39fef03c5ec920f4d3ecaddfd077779 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import inspect
import itertools
from collections import OrderedDict

from decorator import decorator


class ValidationFailure(Exception):
    def __init__(self, func, args):
        self.func = func
        self.__dict__.update(args)

    def __repr__(self):
        return u'ValidationFailure(func={func}, args={args})'.format(
            func=self.func.__name__,
            args=dict(
                [(k, v) for (k, v) in self.__dict__.items() if k != 'func']
            )
        )

    def __str__(self):
        return repr(self)

    def __unicode__(self):
        return repr(self)

    def __bool__(self):
        return False

    def __nonzero__(self):
        return False


def func_args_as_dict(func, args, kwargs):
    """
    Return given function's positional and key value arguments as an ordered
    dictionary.
    """
    _getargspec = inspect.getfullargspec

    arg_names = list(
        OrderedDict.fromkeys(
            itertools.chain(
                _getargspec(func)[0],
                kwargs.keys()
            )
        )
    )
    return OrderedDict(
        list(zip(arg_names, args)) +
        list(kwargs.items())
    )


def validator(func, *args, **kwargs):
    """
    A decorator that makes given function validator.

    Whenever the given function is called and returns ``False`` value
    this decorator returns :class:`ValidationFailure` object.

    Example::

        >>> @validator
        ... def even(value):
        ...     return not (value % 2)

        >>> even(4)
        True

        >>> even(5)
        ValidationFailure(func=even, args={'value': 5})

    :param func: function to decorate
    :param args: positional function arguments
    :param kwargs: key value function arguments
    """
    def wrapper(func, *args, **kwargs):
        value = func(*args, **kwargs)
        if not value:
            return ValidationFailure(
                func, func_args_as_dict(func, args, kwargs)
            )
        return True
    return decorator(wrapper, func)