I'm definitely interested in a simple type-safe validator library, but that planned performance boost is pretty tempting.
- I haven't benchmarked this against pydantic... I guess I should!
- I would _hope_ that Koda Validate is at least competitive with Pydantic... because Koda Validate's main core improvement (IMO) is a consistent idea of what a validator is, validators in Koda Validate are actually much simpler than in Pydantic, meaning I would generally expect fewer instructions to be executed
- 3.11 (and 3.12) are both focused on performance. Both pydantic and Koda Validate might get some "free" performance boosts anyway (Thanks CPython devs!)
- it is typesafe without any plugins or type-hint hacks
- exceptions are not raised as part of validation
- there is a consistent, type-enforced notion of what a validator is
- it's explicit, no implicit type coercions
- it's meant to be easier to build complex validators by combining validators
- validators are meant to be easily inspectable, meaning you can create things like API schemas from them
- errors are json/yaml serializable, so if needed they can be passed over the wire directly (or modified, if desired)
One thing that occurs to me: I don't want to have to describe my data in two places. Like how in the first example the dataclass Person has all the information needed to define the person_validator.
I'm probably just going to use pydantic though.
It's difficult to imagine a way of doing this that's as flexible but done with, let's say, a dataclass definition -- without being hacky. For instance, how do you handle non-string keys? What about strings keys that don't conform to instance properties? What about optional keys (not values)? How are types determined? One of the tricky things with Pydantic, for instance, is the way type annotations are contorted to be used for validation.
Some of the tradeoffs Koda Validate chooses in favor of here are:
- you don't have to install a plugin for type safety
- you can define any kind of target `Callable`; function, dataclass, other class, etc, so in some ways you have more flexibility
- if you want to use your validation target (let's say a class) elsewhere, you don't need to run validation every time it's instantiated.
- consistency at a typelevel for the all validators; dict, list, str, etc. This allows easy combination of validators
But yeah, I acknowledge the desire have a simple dataclass-like object. There is the potential that an abstraction may be made on top of what already exists to accomplish this, but the overall decision to not go that direction was made to keep consistency and avoid hacks.