RecordValidator¶
In many cases RecordValidator is more verbose than the Derived Validators, but
it comes with greater flexibility. It can handle any kind of Hashable key. Optional keys are
handled explicitly with KeyNotRequired, which returns Maybe values. The into parameter
can be any Callable with the correct type signature – dataclasses are convenient, but it could
just as well be an arbitrary function.
from dataclasses import dataclass
from koda import Maybe, Just
from koda_validate import (RecordValidator, StringValidator, not_blank, MaxLength,
Min, Max, IntValidator, KeyNotRequired, Invalid, Valid)
@dataclass
class Person:
name: str
age: Maybe[int]
person_validator = RecordValidator(
into=Person,
keys=(
("full name", StringValidator(not_blank, MaxLength(50))),
("age", KeyNotRequired(IntValidator(Min(0), Max(130)))),
),
)
match person_validator({"full name": "John Doe", "age": 30}):
case Valid(person):
match person.age:
case Just(age):
age_message = f"{age} years old"
case nothing:
age_message = "ageless"
print(f"{person.name} is {age_message}")
case Invalid(errs):
print(errs)
Output:
John Doe is 30 years old
Here’s a more complex example of mixing and matching different kinds of keys.
from dataclasses import dataclass
from koda import Maybe, Just
from koda_validate import (
RecordValidator, StringValidator, KeyNotRequired, IntValidator, Valid, ListValidator
)
@dataclass
class Person:
name: str
age: Maybe[int]
hobbies: list[str]
person_validator = RecordValidator(
into=Person,
keys=(
(1, StringValidator()),
(False, KeyNotRequired(IntValidator())),
(("abc", 123), ListValidator(StringValidator()))
),
)
assert person_validator({
1: "John Doe",
False: 30,
("abc", 123): ["reading", "cooking"]
}) == Valid(Person(
"John Doe",
Just(30),
["reading", "cooking"]
))
Caveats¶
The main caveats with RecordValidator are:
it works on a maximum of 16 keys
type checkers don’t always produce the most readable hints and errors for
RecordValidator, as it uses@overloads.the target of validation must be defined outside the
RecordValidator, and the order of arguments matters