While this isn't the cleanest solution, it will certainly do what you want.
from cerberus import Validator, TypeDefinition
class MyValidator(Validator):
def __init__(self, *args, **kwargs):
# Add the tuple type
tuple_type = TypeDefinition("tuple", (tuple,), ())
Validator.types_mapping["tuple"] = tuple_type
# Call the Validator constructor
super(MyValidator, self).__init__(*args, **kwargs)
def _validate_is_int_two_tuple(self, is_int_two_tuple, field, value):
''' Test that the value is a 2-tuple of ints
The rule's arguments are validated against this schema:
{'type': 'boolean'}
'''
if is_int_two_tuple:
# Check the type
if type(value) != tuple:
self._error(field, "Must be of type 'tuple'")
# Check the length
if len(value) != 2:
self._error(field, "Tuple must have two elements")
# Check the element types
if type(value[0]) != int or type(value[1]) != int:
self._error(field, "Both tuple values must be of type 'int'")
data = {"mylist": [(1,1), (2,2), (3,3)]}
schema = {
"mylist": {
"type": "list",
"schema": {
"type": "tuple",
"is_int_two_tuple": True
}
}
}
v = MyValidator(schema)
print("Validated: {}".format(v.validate(data)))
print("Validation errors: {}".format(v.errors))
print("Normalized result: {}".format(v.normalized(data)))
So as bro-grammer pointed out, the custom data types will get you validation of the types, but that's it. From the schema that you provided, it looks like you also want to validate other features like the length of the tuple and the types of the elements in the tuple. Doing that requires more than just a simple TypeDefinition
for tuples.
Extending Validator to include a rule for this specific use-case isn't ideal, but it will do what you want. The more comprehensive solution would be to create a TupleValidator
subclass that has rules for validating length, element-types, order, etc. of tuples.