pythonpython-typingpydantic

Defining an Annotated[str] with constraints in Pydantic v2


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.


Solution

  • 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.