We can add various constraints to parameters, such as "greater than" or "not equal to", which will be matched against the corresponding specified value. In case a constraint is infringed the framework will raise a ValueError.
from hanna import Configurable, Integer, String
from pyhocon import ConfigTree
class Movie(Configurable):
year = Integer() >= 2000 # Constrain to recent movies only.
movie = Movie(ConfigTree(year=1977)) # raises ValueError: "year" Too small (1977 < 2000)
movie = Movie(ConfigTree(year=2018)) # Fine.
Constraints can be declared by using any of the comparison operators (<, <=, >, >=, !=, ==).
Constraints are checked for after all have been applied.
Constraining meta characteristics
Constraints can as well refer to meta characteristics such as len or abs.
class Movie(Configurable):
title = String().len >= 10
movie = Movie(ConfigTree(title='Star Wars')) # raises ValueError: "title" Too short (9 < 10)
movie = Movie(ConfigTree(title='Star Wars: A New Hope')) # Fine.
Custom constraints
Finally we can add constraints manually by invoking the constrain method. This method accepts any callable with the convention that the callable shall return True if the constraint holds and False otherwise.
class Movie(Configurable):
title = String().constrain(lambda x: len(x.split()) >= 5) # Only titles with at least 5 words.
movie = Movie(ConfigTree(title='Star Wars')) # raises ValueError: "title"
movie = Movie(ConfigTree(title='Star Wars: A New Hope')) # Fine.
Custom error messages
The error message in the previous example is not really verbose since it only contains the name of the parameter which caused the exception. However we can provide a custom error message when declaring a constraint as an additional argument:
class Movie(Configurable):
title = String().constrain(lambda x: len(x.split()) >= 5,
'Not enough words')
movie = Movie(ConfigTree(title='Star Wars')) # raises ValueError: "title" Not enough words
Within the error message we can even refer to the underlying value which will then be displayed in the message:
class Movie(Configurable):
title = String().constrain(lambda x: len(x.split()) >= 5,
'Not enough words ({value} < 5)')
movie = Movie(ConfigTree(title='Star Wars')) # raises ValueError: "title" Not enough words (2 < 5)