Skip to content

Making validators

Thor Whalen edited this page Jan 13, 2023 · 1 revision

In an effort to make our code more robust and error messages more helpful (closer to the context of the call), we would like to be able to make validators (and for example, decorate our functions (or entire modules?) to use them).

pydantic has a very nice interface for this. But I'm still trying to figure things out.

For example, if I wanted to determine whether an input was one accepted by a typing.Literal, how would I do it with pydantic? See below how I hack it through, but it really looks like unnecessary contortions for such a common case. Two things seem to be in the way:

  • The fact that types ("models" here) need (or do they?) to have attributes, so I'm just using an attribute to contain my actual value I'm trying to validate
  • The fact that pydantic's validation raises an error. But here I want to have an is_valid function that returns a bool.
from typing import Literal
from pydantic import BaseModel, ValidationError

def literal_to_validator(literal):
    class C(BaseModel):
        valid_vals: literal
        
    def validator(val):
        C.validate({'valid_vals': val})
        
    def validator(val):
        try:
            C.validate({'valid_vals': val})
            return True
        except ValidationError:
            return False
        
    return validator

is_valid = literal_to_validator(Literal[1, 2, 3])
assert is_valid(3)
assert not is_valid(4)


def literal_to_is_valid(literal):
    class C(BaseModel):
        valid_vals: literal
        
    def is_valid(val):
        try:
            C.validate({'valid_vals': val})
            return True
        except ValidationError:
            return False
        
    return is_valid

is_valid = literal_to_is_valid(Literal[1, 2, 3])
assert is_valid(3)
assert not is_valid(4)

Clone this wiki locally