def class_field_mini_lambda(value):
    from mini_lambda import InputVar, Len
    from valid8 import validate_field
    from valid8.validation_lib import instance_of
    from valid8.validation_lib.mini_lambda_ import Instance_of

    # just for fun: we create our custom mini_lambda variable named 't'
    t = InputVar('t', tuple)

    @validate_field(
        't',
        instance_of(tuple),
        Len(t) == 2,
        # the first element is a float between 0 and 1
        Instance_of(t[0], Real),
        (0 <= t[0]) & (t[0] <= 1),
        # the 2d element is a lowercase string of len 3
        Instance_of(t[1], str),
        Len(t[1]) == 3,
        t[1].islower())
    class Foo:
        def __init__(self, t):
            self.s = t

    Foo(value)
def test_evaluator_complex_1():
    """ A complex case with a combination of Repr, Len, and comparisons """

    s = InputVar('s', str)

    reasonable_string = Repr((2 <= Len(s)) & (Len(s) < 3))
    reasonable_string = reasonable_string.as_function()

    assert reasonable_string('r') == 'False'
def test_validate_mini_lambda():
    """ Tests that mini_lambda works with @validate_io """

    from mini_lambda import Len, s, x, Int

    @validate_io(name=(0 < Len(s)) & (Len(s) <= 10),
                 age=(x > 0) & (Int(x) == x))
    def hello_world(name, age):
        print('Hello, ' + name + ' your age is ' + str(age))

    hello_world('john', 20)
def test_evaluator_sized():
    """ Sized Container Object: tests that len() raises the appropriate error but that the equivalent Len() works """

    s = InputVar('s', str)

    with pytest.raises(FunctionDefinitionError):
        len(s)

    string_length = Len(s)
    string_length = string_length.as_function()

    assert string_length('tho') == 3
Beispiel #5
0
def test_readme_index_usage_function():
    """ Tests that the examples provided in the index page under Usage examples/Function are correct """

    from mini_lambda import s, Len
    from valid8 import validate_arg
    from valid8.validation_lib import instance_of

    @validate_arg('name',
                  instance_of(str),
                  Len(s) > 0,
                  help_msg='name should be a non-empty string')
    def build_house(name, surface=None):
        print('Building house... DONE !')
        return name, surface

    build_house('sweet home', 200)

    with pytest.raises(InputValidationError) as exc_info:
        build_house('', 200)  # name is invalid
    e = exc_info.value
    assert str(e) == "name should be a non-empty string. " \
                     "Error validating input [name=''] for function [build_house]. " \
                     "At least one validation function failed for value ''. " \
                     "Successes: [\"instance_of_%r\"] / Failures: {'len(s) > 0': 'Returned False.'}." \
                     "" % str

    from mini_lambda import s, x, l, Len
    from valid8 import validate_arg, validate_out
    from valid8.validation_lib import instance_of, is_multiple_of

    @validate_arg('name',
                  instance_of(str),
                  Len(s) > 0,
                  help_msg='name should be a non-empty string')
    @validate_arg(
        'surface', (x >= 0) & (x < 10000),
        is_multiple_of(100),
        help_msg='Surface should be a multiple of 100 between 0 and 10000.')
    @validate_out(instance_of(tuple), Len(l) == 2)
    def build_house(name, surface=None):
        print('Building house... DONE !')
        return name, surface

    build_house('sweet home')
    build_house('sweet home', None)  # No error !

    with pytest.raises(TypeError):
        is_multiple_of(100)(None)

    with pytest.raises(TypeError):
        (Len(s) > 0).evaluate(None)
 class House:
     @validate_arg('name', Len(s) > 0,
                   error_type=InvalidName)
     @validate_arg('surface', (x >= 0) & (x < 10000), is_multiple_of(100),
                   error_type=InvalidSurface)
     def __init__(self, name: str, surface: Integral = None):
         pass
def test_readme_index_combining_autoclass():
    """ Tests that the examples provided in the index page under Combining/autoclass are correct """

    from autoclass import autoclass
    from mini_lambda import s, x, Len
    from valid8 import validate_field, ClassFieldValidationError
    from valid8.validation_lib import instance_of, is_multiple_of

    class InvalidNameError(ClassFieldValidationError):
        help_msg = 'name should be a non-empty string'

    class InvalidSurfaceError(ClassFieldValidationError):
        help_msg = 'Surface should be a multiple of 100 between 0 and 10000.'

    @validate_field('name',
                    instance_of(str),
                    Len(s) > 0,
                    error_type=InvalidNameError)
    @validate_field('surface', (x >= 0) & (x < 10000),
                    is_multiple_of(100),
                    error_type=InvalidSurfaceError)
    @autoclass
    class House(object):
        def __init__(self, name, surface=None):
            pass

    h = House('sweet home', 200)

    h.surface = None  # Valid (surface is nonable by signature)

    with pytest.raises(InvalidNameError):
        h.name = ''  # InvalidNameError

    with pytest.raises(InvalidSurfaceError):
        h.surface = 10000  # InvalidSurfaceError
Beispiel #8
0
    class House(object):

        @validate_arg('name', instance_of(str), Len(s) > 0,
                      error_type=InvalidNameError)
        @validate_arg('surface', (x >= 0) & (x < 10000), is_multiple_of(100),
                      error_type=InvalidSurfaceError)
        def __init__(self, name, surface=None):
            pass
def test_evaluator_sized_compared():
    """ Tests that Len(s) > 2 works as well as (2 <= Len(s)) & (Len(s) < 3)"""

    s = InputVar('s', str)

    big_string = Len(s) > 2
    big_string = big_string.as_function()

    assert big_string('tho')
    assert not big_string('r')

    reasonable_string = L((2 <= Len(s)) & (Len(s) < 3))
    # reasonable_string = reasonable_string.as_function()

    assert reasonable_string('th')
    assert not reasonable_string('r')
    assert not reasonable_string('rats')
Beispiel #10
0
def ex2_pep484(value):
    from mini_lambda import s, Len

    @typechecked
    @validate_arg('s', Len(s) > 0, s.islower())
    def my_function(s: str):  # <- type hint in signature
        pass

    my_function(value)
Beispiel #11
0
def test_testing():
    """ """
    from mini_lambda import s, Len
    from valid8 import assert_valid, Validator
    from valid8.validation_lib import instance_of

    name = 'sweet_home'

    assert_valid('name',
                 name,
                 instance_of(str),
                 Len(s) > 0,
                 help_msg='name should be a non-empty string')

    v = Validator(instance_of(str),
                  Len(s) > 0,
                  help_msg='name should be a non-empty string')
    v.assert_valid('name', name)
Beispiel #12
0
def function_input_mini_lambda(value):
    from mini_lambda import s, Len
    from valid8 import validate_arg
    from valid8.validation_lib import instance_of

    @validate_arg('s', instance_of(str), Len(s) > 0, s.islower())
    def my_function(s):
        pass

    my_function(value)
Beispiel #13
0
def class_field_mini_lambda(value):
    from mini_lambda import s, Len
    from valid8 import validate_field
    from valid8.validation_lib import instance_of

    @validate_field('s', instance_of(str), Len(s) > 0, s.islower())
    class Foo:
        def __init__(self, s):
            self.s = s

    Foo(value)
def function_input_mini_lambda(value):
    from mini_lambda import InputVar, Len
    from valid8 import validate_arg
    from valid8.validation_lib import instance_of
    from valid8.validation_lib.mini_lambda_ import Instance_of

    # just for fun: we create our custom mini_lambda variable named 't'
    t = InputVar('t', tuple)

    @validate_arg(
        't',
        instance_of(tuple),
        Len(t) == 2,
        # the first element is a float between 0 and 1
        Instance_of(t[0], Real),
        (0 <= t[0]) & (t[0] <= 1),
        # the 2d element is a lowercase string of len 3
        Instance_of(t[1], str),
        Len(t[1]) == 3,
        t[1].islower())
    def my_function(t):
        pass

    my_function(value)
Beispiel #15
0
def ex3_pep484(value):
    from mini_lambda import InputVar, Len

    # we need a mini_lambda variable named 't'
    t = InputVar('t', tuple)

    @typechecked
    @validate_arg(
        't',  # the first element is a float between 0 and 1
        (0 <= t[0]) & (t[0] <= 1),
        # the 2d element is a lowercase string of len 3
        Len(t[1]) == 3,
        t[1].islower())
    def my_function(t: Tuple[Real, str]):
        pass

    my_function(value)
Beispiel #16
0
def test_readme_combining_enforce():
    # Imports - for type validation
    from numbers import Integral
    from typing import Tuple, Optional
    from enforce import runtime_validation, config
    config(dict(mode='covariant')
           )  # means that subclasses of required types are valid too
    from enforce.exceptions import RuntimeTypeError

    # Imports - for value validation
    from mini_lambda import s, x, Len
    from valid8 import validate_arg
    from valid8.validation_lib import is_multiple_of

    # Define our 2 applicative error types
    class InvalidNameError(InputValidationError):
        help_msg = 'name should be a non-empty string'

    class InvalidSurfaceError(InputValidationError):
        help_msg = 'Surface should be a multiple of 100 between 0 and 10000.'

    # Apply type + value validation
    @runtime_validation
    @validate_arg('name', Len(s) > 0, error_type=InvalidNameError)
    @validate_arg('surface', (x >= 0) & (x < 10000),
                  is_multiple_of(100),
                  error_type=InvalidSurfaceError)
    def build_house(
            name: str,
            surface: Optional[Integral] = None
    ) -> Tuple[str, Optional[Integral]]:
        print('Building house... DONE !')
        return name, surface

    build_house('sweet home', 200)
    build_house('sweet home')

    with pytest.raises(InvalidNameError):
        build_house('', 100)  # InvalidNameError

    with pytest.raises(InvalidSurfaceError):
        build_house('sweet home', 10000)  # InvalidSurfaceError

    with pytest.raises(RuntimeTypeError):
        build_house('test', 100.1)  # RuntimeTypeError
def test_validate_field_custom_type():
    """"""
    from valid8 import validate_field, ClassFieldValidationError
    from valid8.validation_lib import instance_of, is_multiple_of
    from mini_lambda import x, s, Len

    class InvalidNameError(ClassFieldValidationError):
        help_msg = 'name should be a non-empty string'

    class InvalidSurfaceError(ClassFieldValidationError):
        help_msg = 'Surface should be a multiple of 100 between 0 and 10000.'

    @validate_field('name', instance_of(str), Len(s) > 0,
                    error_type=InvalidNameError)
    @validate_field('surface', (x >= 0) & (x < 10000), is_multiple_of(100),
                    error_type=InvalidSurfaceError)
    class House(object):
        """Properties work only with new-style classes"""
        def __init__(self, name, surface=None):
            self.name = name
            self.surface = surface

        @property
        def surface(self):
            return self.__surface

        @surface.setter
        def surface(self, surface=None):
            self.__surface = surface

    h = House('sweet home')
    h.name = ''  # DOES NOT RAISE InvalidNameError

    with pytest.raises(InvalidNameError):
        h = House('')

    h.surface = 100
    with pytest.raises(InvalidSurfaceError):
        h.surface = 10000
Beispiel #18
0
def test_readme_index_usage_class_fields():
    """ Tests that the examples provided in the index page under Usage examples/class fields are correct"""

    from valid8 import validate_field, ClassFieldValidationError
    from valid8.validation_lib import instance_of, is_multiple_of
    from mini_lambda import x, s, Len

    @validate_field('name',
                    instance_of(str),
                    Len(s) > 0,
                    help_msg='name should be a non-empty string')
    @validate_field(
        'surface', (x >= 0) & (x < 10000),
        is_multiple_of(100),
        help_msg='Surface should be a multiple of 100 between 0 and 10000.')
    class House(object):
        def __init__(self, name, surface=None):
            self.name = name
            self.surface = surface

        @property
        def surface(self):
            return self.__surface

        @surface.setter
        def surface(self, surface=None):
            self.__surface = surface

    h = House('sweet home')
    h.name = ''  # DOES NOT RAISE InvalidNameError

    with pytest.raises(ClassFieldValidationError):
        h = House('')

    h.surface = 100
    with pytest.raises(ClassFieldValidationError):
        h.surface = 10000
def test_readme_index_combining_attrs():
    """ Tests that the examples provided in the index page under Combining/autoclass are correct """

    import attr
    from mini_lambda import s, x, Len
    from valid8 import validate_field, ClassFieldValidationError
    from valid8.validation_lib import instance_of, is_multiple_of

    class InvalidNameError(ClassFieldValidationError):
        help_msg = 'name should be a non-empty string'

    class InvalidSurfaceError(ClassFieldValidationError):
        help_msg = 'Surface should be a multiple of 100 between 0 and 10000.'

    @validate_field('name',
                    instance_of(str),
                    Len(s) > 0,
                    error_type=InvalidNameError)
    @validate_field('surface', (x >= 0) & (x < 10000),
                    is_multiple_of(100),
                    error_type=InvalidSurfaceError)
    @attr.s
    class House(object):
        name = attr.ib()
        surface = attr.ib(default=None)

    h = House(
        'sweet home')  # Valid (surface is nonable by generated signature)

    h.name = ''  # DOES NOT RAISE InvalidNameError (no setter!)

    with pytest.raises(InvalidNameError):
        House('', 10000)  # InvalidNameError

    with pytest.raises(InvalidSurfaceError):
        House('sweet home', 10000)  # InvalidSurfaceError
def test_readme_examples_4():
    """ Tests that the example 4 provided in the documentation works (list of custom tuples) """

    l = [(1, 'ras'), (0.2, 'abc')]

    # ---- inline 1
    from valid8 import validate

    # first validate the main type
    validate('l', l, instance_of=list)

    for i, v in enumerate(l):
        # each item is a tuple of size 2
        validate('l[%s]' % i, l[i], instance_of=tuple, length=2)
        # the first element is a float between 0 and 1
        validate('l[%s][0]' % i,
                 l[i][0],
                 instance_of=Real,
                 min_value=0,
                 max_value=1)
        # the second element is a lowercase string of size 3
        validate('l[%s][1]' % i,
                 l[i][1],
                 instance_of=str,
                 length=3,
                 equals=l[i][1].lower())

    # ---- inline 2
    from valid8 import validator
    from valid8.validation_lib import instance_of

    l = [(1, 'ras'), (0.2, 'abc')]

    # all at once
    with validator('l', l, instance_of=list) as v:
        v.alid = all(
            # each item is a tuple of size 2
            instance_of(item, tuple) and len(item) == 2
            # the first element is a float between 0 and 1
            and instance_of(item[0], Real) and (0 <= item[0] <= 1)
            # the second element is a lowercase string of size 3
            and instance_of(item[1], str) and len(item[1]) == 3
            and item[1].islower() for item in l)

    # custom validation function
    def check_valid_tuple(tup):
        """ custom validation function - here in 'failure raiser' style (returning nothing) """

        # each item is a tuple of size 2
        if not isinstance(tup, tuple):
            raise TypeError('item should be a tuple')
        if len(tup) != 2:
            raise ValueError('tuple length should be 2')

        # the first element is a float between 0 and 1
        if not isinstance(tup[0], Real):
            raise TypeError('first element should be a Real')
        if not (0 <= tup[0] <= 1):
            raise ValueError('first element should be between 0 and 1')

        # the second element is a lowercase string of size 3
        if not isinstance(tup[1], str):
            raise TypeError('second element should be a string')
        if not (len(tup[1]) == 3 and tup[1].islower()):
            raise ValueError(
                'second element should be a lowercase string of length 3')

    from valid8 import validate, validation

    # first validate the main type
    validate('l', l, instance_of=list)

    # then validate (and use) the contents
    for i, v in enumerate(l):
        # each item is a valid tuple
        with validation('l[%s]' % i, l[i]):
            check_valid_tuple(l[i])

        # here you can actually USE the current item

    # ---- function input
    from valid8 import validate_arg, and_
    from valid8.validation_lib import instance_of, on_all_, on_each_, has_length, between

    @validate_arg(
        'l',
        instance_of(list),
        on_all_(
            instance_of(tuple),
            has_length(2),  # each item is a tuple of size 2
            on_each_(
                and_(instance_of(Real), between(
                    0, 1)),  # the first element is a float between 0 and 1
                and_(
                    instance_of(str), has_length(3)
                ),  # the 2d element is a string of len 3 BUT we cannot check lowercase
            )))
    def my_function(l):
        pass

    l = [(1, 'ras'), (0.2, 'aBc')]  # we cannot check lowercase
    my_function(l)

    # much better:
    from valid8 import validate_arg, ValidationFailure
    from valid8.validation_lib import instance_of, on_all_, HasWrongType, WrongLength, NotInRange

    def is_valid_tuple(t):
        """ Custom validation function. We could also provide a callable """

        # (a) each item is a tuple of size 2
        # --you can reuse an entire method from the built-in lib when it supports direct calling mode
        instance_of(t, tuple)
        # --otherwise you can reuse a failure class, there are many
        if len(t) != 2: raise WrongLength(t, ref_length=2)

        # (b) the first element is a float between 0 and 1
        if not isinstance(t[0], Real): raise HasWrongType(t[0], Real)
        if not (0 <= t[0] <= 1):
            raise NotInRange(t[0], min_value=0, max_value=1)

        # (c) the second element is a lowercase string of size 3
        instance_of(t[1], str)
        if len(t[1]) != 3: raise WrongLength(t[1], ref_length=3)
        # -- finally you can write custom ValidationFailure types
        if not t[1].islower():
            raise NotLowerCase(t[1])

    class NotLowerCase(ValidationFailure, ValueError):
        """ Example custom exception class used in custom validation function. `ValidationFailure` base class provides some
        mechanisms to easily build the help message (same mechanisms than ValidationError)"""
        help_msg = "Value is not a lowercase string: {wrong_value}"

    @validate_arg('l', instance_of(list), on_all_(is_valid_tuple))
    def my_function(l):
        pass

    l = [(1, 'ras'), (0.2, 'abc')]
    my_function(l)

    # ---- mini_lambda
    from valid8 import validate_arg
    from valid8.validation_lib import instance_of, on_all_

    # just for fun: we create our custom mini_lambda variable named 't'
    from mini_lambda import InputVar, Len, Isinstance
    t = InputVar('t', tuple)

    @validate_arg(
        'l',
        instance_of(list),
        on_all_(
            # each item is a tuple of size 2
            instance_of(tuple),
            Len(t) == 2,
            # the first element is a float between 0 and 1
            Isinstance(t[0], Real),
            (0 <= t[0]) & (t[0] <= 1),
            # the 2d element is a lowercase string of len 3
            Isinstance(t[1], str),
            Len(t[1]) == 3,
            t[1].islower()))
    def my_function(l):
        pass

    l = [(1, 'ras'), (0.2, 'abc')]
    my_function(l)
Beispiel #21
0
 class House:
     @validate_arg('name', Len(s) > 0)
     @validate_arg('surface', (x >= 0) & (x < 10000), is_multiple_of(100))
     def __init__(self, name: str, surface: int = 100):
         pass
def test_doc_usage_syntax_2():
    """ Tests that the second example in doc/usage in the syntax section works """
    from mini_lambda import b, i, s, l, x
    from mini_lambda import Slice, Get, Not, In
    from mini_lambda import Iter, Repr, Format, Len, Int, Any, Log, DDecimal
    from math import log
    from decimal import Decimal

    # boolean logic
    with pytest.raises(FunctionDefinitionError):
        expr = (x > 1) and (x < 5)  # fails
    expr = (x > 1) & (x < 5)  # OK
    # iterating
    with pytest.raises(FunctionDefinitionError):
        expr = next(iter(s))  # fails
    expr = next(Iter(s))  # OK
    # calling with the variable as arg
    with pytest.raises(FunctionDefinitionError):
        expr = log(x)  # fails
    expr = Log(x)  # OK
    # constructing with the variable as arg
    with pytest.raises(TypeError):
        expr = Decimal(x)  # fails
    expr = DDecimal(x)  # OK
    # getting with the variable as the key
    with pytest.raises(FunctionDefinitionError):
        expr = {'a': 1}[s]  # fails
    expr = Get({'a': 1}, s)  # OK
    # slicing with the variable as index
    with pytest.raises(FunctionDefinitionError):
        expr = 'hello'[0:i]  # fails
    expr = Get('hello', Slice(0, i))  # OK
    # representing: Repr/Str/Bytes/Sizeof/Hash
    with pytest.raises(FunctionDefinitionError):
        expr = repr(l)  # fails
    expr = Repr(l)  # OK
    # formatting with the variable in the args
    with pytest.raises(FunctionDefinitionError):
        expr = '{} {}'.format(s, s)  # fails
    expr = Format('{} {}', s, s)  # OK
    # sizing
    with pytest.raises(FunctionDefinitionError):
        expr = len(l)  # fails
    expr = Len(l)  # OK
    # casting (Bool, Int, Float, Complex, Hex, Oct)
    with pytest.raises(FunctionDefinitionError):
        expr = int(s)  # fails
    expr = Int(s)  # OK
    # not
    with pytest.raises(FunctionDefinitionError):
        expr = not b  # fails
    expr = b.not_()  # OK
    expr = Not(b)  # OK
    # any/all
    with pytest.raises(FunctionDefinitionError):
        expr = any(l)  # fails
    expr = l.any_()  # OK
    expr = Any(l)  # OK
    # membership testing (variable as container)
    with pytest.raises(FunctionDefinitionError):
        expr = 'f' in l  # fails
    expr = l.contains('f')  # OK
    expr = In('f', l)  # OK
    # membership testing (variable as item)
    with pytest.raises(FunctionDefinitionError):
        expr = x in [1, 2]  # fails
    expr = x.is_in([1, 2])  # OK
    expr = In(x, [1, 2])  # OK

    with pytest.raises(FunctionDefinitionError):
        expr = 0 < x < 1  # chained comparisons (use parenthesis and & instead)

    with pytest.raises(FunctionDefinitionError):
        expr = [i for i in l
                ]  # list/tuple/set/dict comprehensions (no workaround)