Suppose I want a validator for checksums that I can reuse throughout an application. The Python type-hint system has changed a lot in 3.9+ and that is adding to my confusion. In pydantic v1, I subclassed str
and implement __get_pydantic_core_schema__
and __get_validators__
class methods. v2 has changed some of this and the preferred way has changed to using annotated types.
In pydantic-extra-types package I have found examples that require insight into the inner workings of pydantic. I can copy and get something working, but I would prefer to find the "correct" user's way to do it rather than copying without understanding.
In pydantic v2 it looks like I can make a constrained string as part of a pydantic class, e.g.
from typing import Annotated
from pydantic import BaseModel, StringConstraints
class GeneralThing(BaseModel):
special_string = Annotated[str, StringConstraints(pattern="^[a-fA-F0-9]{64}$")]
but this is not valid (pydantic.errors.PydanticUserError: A non-annotated attribute was detected). Additionally I would have to annotate every field I want to constrain, as opposed to special_string = ChecksumStr
that I was able to do in the past.
For pydantic you need to annotate your fields, but you're assigning them. The following code should do the trick for you
from typing import Annotated
from pydantic import BaseModel, StringConstraints
ChecksumString = Annotated[str, StringConstraints(pattern="^[a-fA-F0-9]{64}$")]
class GeneralThing(BaseModel):
special_string: ChecksumString
Note that special_string: ChecksumString
and not special_string = ChecksumString
. special_string: Annotated[str, StringConstraints(...)
would be valid as well just to know.