Is it possible to have a pydantic model where I would pass the data type for one of the variables during runtime somehow? I have tried to read, but I cannot wrap my head around Pydantic on how would it work. I need data type enforcement essentially, also during assigment. I hope for something that would do things like that:
class State(BaseModel):
datatype: type,
value: self.datatype,
getter: Callable
setter: Callable
state1 = State(bool, True, get_state1, set_state1)
state2 = State(int, 0, get_state2, set_state2)
state1.value = 7 # this should throw error, expected datatype of state1 is bool
In think there are two independent questions here:
To enable validating assignments you can use a specific config option. See https://docs.pydantic.dev/latest/api/config/#pydantic.config.ConfigDict.validate_assignment
Regarding (2) I would argue that Pydantic is not really made to handle type definitions at runtime. The whole point of Pydantic is to define the types beforehand, then Pydantic builds a model schema once and uses it to validate at runtime. However there are options to achieve this, if you have very good reasons to do so.
First you could mimic that behavior by defining a custom field_validator
. In the field validator you then use a TypeValidator
to trigger the type validation. However it is important to say, that this only works well for small models, because the TypeValidator
will build a schema on creation and rebuild every time the validation is called.
Combined with the validate_assignment=True
option you get something along the lines of:
from pydantic import BaseModel, field_validator, TypeAdapter, ConfigDict
from typing import Any
class State(BaseModel):
model_config = ConfigDict(validate_assignment=True)
value_type: type
value: Any
@field_validator("value", mode="before")
@classmethod
def validate_value(cls, value, info):
adapter = TypeAdapter(info.data["value_type"])
return adapter.validate_python(value)
state1 = State(value=True, value_type=bool)
state2 = State(value=7, value_type=int)
state1.value = 7 # this should throw error, exp
Which exactly raises:
ValidationError: 1 validation error for State
value
Input should be a valid boolean, unable to interpret input [type=bool_parsing, input_value=7, input_type=int]
For further information visit https://errors.pydantic.dev/2.5/v/bool_parsing
Alternatively you could look into creating the whole model on runtime. For this Pydantic provides dynamic model creation, see for example https://docs.pydantic.dev/latest/concepts/models/#dynamic-model-creation
I hope this helps!