Condense Pydantic Validators into Class Annotations

Question:

Looking to create a datastructure in Python that condenses Pydantic’s validators into oneline arguments:

ie. from this

from pydantic import BaseModel, validator


class MyClass(BaseModel):
    a: str
    b: str
    c: str
    
    @validator('b')
    def calculate_b(cls, v, values):
        return values['a'] + v
      
    @validator('c')
    def calculate_c(cls, v, values):
        return values['a'] + values['b'] + v

to (something like) this

class MyClass:
    a: str
    b: str = calculate_b(...)
    c: str = calculate_c(...)
Asked By: Oliver

||

Answers:

My Pydantic version is: 2.5.0


Note: The @validator you used is deprecated in V2 and will be removed in V3. You should use field_validator instead if you want.

You can use Annotated + AfterValidator(actually the default mode for field_validator is "after"):

from typing import Annotated

from pydantic import AfterValidator, BaseModel


class MyClass(BaseModel):
    a: str
    b: Annotated[str, AfterValidator(lambda v, values: values.data["a"] + v)]
    c: Annotated[str, AfterValidator(lambda v, values: values.data["a"] + values.data["b"] + v)]


obj = MyClass(a="a", b="b", c="c")
print(obj)
# a='a' b='ab' c='aabc'

If the annotation became long, you can make alias out of them outside the class. But I think it’s ok.

The values are of type ValidationInfo and in order to access to the data you can use the .data attribute.

Answered By: S.B
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.