-
-
Notifications
You must be signed in to change notification settings - Fork 102
Closed
Description
Summary
BaseSettings
, unlike BaseModel
validates field default value. This contradicts the documentation. pydantic docs state:
Validators won't run when the default value is used. This applies both to @field_validator validators and Annotated validators. You can force them to run with Field(validate_default=True).
Documentation of pydantic-settings
doesn't mention exception from this behavior.
I don't know whether this behavior is intended or not (I'd guess not, because workarounds are quite ugly, see below). But even if it is, it should probably be documented in pydantic-settings
docs.
Minimal working example
from zoneinfo import ZoneInfo
from pydantic import BaseModel, ConfigDict
from pydantic.functional_validators import BeforeValidator
from pydantic_settings import BaseSettings, SettingsConfigDict
from typing_extensions import Annotated
class Model(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)
zone: Annotated[ZoneInfo, BeforeValidator(ZoneInfo)] = ZoneInfo("UTC")
class Settings(BaseSettings):
# arbitrary_types_allowed are not needed for BaseSettings and don't change anything
zone: Annotated[ZoneInfo, BeforeValidator(ZoneInfo)] = ZoneInfo("UTC")
print(repr(Model().zone)) # prints "zoneinfo.ZoneInfo(key='UTC')"
print(repr(Settings().zone)) # raises TypeError: expected str, bytes or os.PathLike object, not ZoneInfo
python -V
Python 3.11.2
pip --list
Package Version
----------------- -------
annotated-types 0.5.0
pip 23.0.1
pydantic 2.3.0
pydantic_core 2.6.3
pydantic-settings 2.0.3
python-dotenv 1.0.0
setuptools 66.1.1
typing_extensions 4.7.1
Workarounds
- Use plain default value. This works as expected, but doesn't play well with type checkers:
class Settings(BaseSettings):
zone: Annotated[ZoneInfo, BeforeValidator(ZoneInfo)] = "UTC"
- Set
validate_default=False
explicitely. This works, but is unnecessarily verbose:
class Settings(BaseSettings):
zone: Annotated[ZoneInfo, Field(validate_default=False), BeforeValidator(ZoneInfo)] = ZoneInfo("UTC")
Metadata
Metadata
Assignees
Labels
No labels