Reputation: 25
I'm writing a pydantic_settings class to read data from a .env file/environment variables. The relevant parts look like this:
from pydantic_settings import BaseSettings
from pydantic import Field, field_validator
from typing import Tuple
class JobSettings(BaseSettings):
wp_generate_funnel_box: bool = Field(True)
wp_funnel_box_dims_mm: Tuple[int, int, int] = Field((380, 90, 380))
@field_validator('wp_funnel_box_dims_mm', mode='before')
@classmethod
def parse_int_tuple(cls, v) -> tuple[int, int, int]:
output = tuple(int(x.strip()) for x in v.split(','))
assert len(output) == 3
return output
model_config = {
"env_file": ".env",
"env_file_encoding": "utf-8",
"extra": "ignore",
}
I need to create a 3-tuple of ints from the string in the environment variable:
wp_generate_funnel_box="True"
wp_funnel_box_dims_mm="380, 90, 380"
Pydantic doens't seem to have a native parser for this datatype, so I implemented this field validator to properly parse and validate the data. However, Pydantic doesn't appear to be running the code in the method; print statements don't produce any output, and simply returning tuple(1, 2, 3)
doesn't do anything either. I think I'm misunderstanding how Pydantic handles fields, validators, and ordering. The particular error raised is:
SettingsError: error parsing value for field "wp_funnel_box_dims_mm" from source "DotEnvSettingsSource"
I've tried various configurations of decorators, modes, and logic structures. Nothing so far has changed the type of error generated. Pydantic doesn't run the validator before its own internal logic.
Upvotes: 1
Views: 354
Reputation: 482
method 1:
Write in the env file:
wp_funnel_box_dims_mm=[380, 90, 380]
method 2:
If you want to preprocess this value, write this in the env file:
wp_funnel_box_dims_mm='"1,2,3"'
pydantic treats this value as a complex type and executes json.loads().
class JobSettings(BaseSettings):
wp_funnel_box_dims_mm: Tuple[int, int, int] = Field((380, 90, 380))
@model_validator(mode="before")
@classmethod
def parse_int_tuple(cls, v) -> tuple[int, int, int]:
v["wp_funnel_box_dims_mm"] = tuple(int(x.strip()) for x in v["wp_funnel_box_dims_mm"].split(","))
return v
model_config = {
"env_file": ".env",
"env_file_encoding": "utf-8",
"extra": "ignore",
}
Upvotes: 0