Skip to content

Simple syntax for validation functions

We have seen in previous section that validation functions should either return True or None in case of success, that's the only requirement from valid8 standpoint. We also have seen that you can improve them by explicitly transforming them into custom failure raisers. In the next section we will see how to compose several validation functions together.

In this section we will show how to both compose several validation functions and augment them into failure raisers, using in a simple and compact syntax. All valid8 entry points except the context manager support this simple syntax.

using the simple syntax in the with validation context manager

To use this syntax with the with validation context manager, you can use an explicit and_() in the code block. and_ accepts the syntax.

1. One validation function

You can define a validation function by providing either a <callable>, or a tuple : (<callable>, <error_msg>), (<callable>, <failure_type>) or (<callable>, <error_msg>, <failure_type>).

  • <validation_func> should be a callable with one argument: f(val). It should return True or None in case of success. If it is a mini-lambda expression it will automatically be transformed into a function using mini_lambda.as_function. See ValidationCallable type hint.
  • <err_msg> should be a string, possibly using the template mechanism
  • <failure_type> should be a subclass of ValidationFailure

For example we can add a custom message to isfinite:

from valid8 import validate
from math import inf, isfinite

x = inf
validate('x', x, custom=(isfinite, 'x is not finite'))

yields

valid8.entry_points.ValidationError[ValueError]: \
  Error validating [x=inf]. InvalidValue: x is not finite. \ 
    Function [isfinite] returned [False] for value inf.

or if you prefer defining a reusable failure class:

from valid8 import validate, ValidationFailure
from math import inf, isfinite

class NotFinite(ValidationFailure):
    help_msg = "x is not finite"

x = inf
validate('x', x, custom=(isfinite, NotFinite))

yields

ValidationError[ValueError]: Error validating [x=inf]. 
  NotFinite: x is not finite. Function [isfinite] returned [False] for value inf.

This syntax also works in @validate_arg, @validate_out, @validate_ios, @validate_field, and in the composition operators such as and_().

2. Several validation functions

You can easily declare that several validators should be combined with an implicit and_ by providing a non-tuple iterable containing validation function definitions, in other words a list containing <callable>, tuples (<callable>, <error_msg>), (<callable>, <failure_type>) or (<callable>, <error_msg>, <failure_type>).

For example:

from valid8 import validate, ValidationFailure
from math import isfinite
from mini_lambda import i

class NotFinite(ValidationFailure):
    help_msg = "x is not finite"

x = 2
validate('x', x, custom=[(i ** 2 < 50, 'x should be fairly small'),
                         i % 3 == 0, 
                         (isfinite, NotFinite)])

yields

ValidationError[ValueError]: Error validating [x=2]. 
   At least one validation function failed for value 2. 
   Successes: ['i ** 2 < 50', 'isfinite'] / 
      Failures: {'i % 3 == 0': 'Returned False.'}.

Alternately you can provide a dictionary. In that case the key should be one of <callable>, <error_msg>, or <failure_type>, and the value should be one of them or a tuple of them.

For example:

from valid8 import validate, ValidationFailure
from math import isfinite
from mini_lambda import i

class NotFinite(ValidationFailure):
    help_msg = "x is not finite"

x = 2
validate('x', x, custom={'x should be fairly small': i ** 2 < 50,
                         'x should be a multiple of 3': i % 3 == 0,
                         'x should be finite': (isfinite, NotFinite)})

yields

ValidationError[ValueError]: Error validating [x=2]. 
   At least one validation function failed for value 2. 
   Successes: ['i ** 2 < 50', 'isfinite'] / 
   Failures: {'i % 3 == 0': 'InvalidValue: x should be a multiple of 3. 
                             Returned False.'}.

Here again, this syntax also works in @validate_arg, @validate_out, @validate_ios, @validate_field, and in the composition operators such as and_().