Skip to content

Instantly share code, notes, and snippets.

@pirate
Last active September 23, 2024 00:11
Show Gist options
  • Save pirate/962002fbe4c944e448ff940c34c12e72 to your computer and use it in GitHub Desktop.
Save pirate/962002fbe4c944e448ff940c34c12e72 to your computer and use it in GitHub Desktop.
pydantic_settings BaseSettings model that allows using functions as that depend on other fields as default values
#!/usr/bin/env python
from typing import Callable
from pydantic import model_validator, TypeAdapter
from pydantic_settings import BaseSettings, SettingsConfigDict
class ModelWithDefaults(BaseSettings):
"""
This is an addon to pydantic_settings's BaseSettings that allows you to use
field default factories that depend on other field values. This is very
useful for parsing config, where some config values might depend others.
class ExampleConfig(ModelWithDefaults):
IS_TTY: bool = Field(default=lambda c: sys.stdout.isatty())
USE_COLOR: bool = Field(default=lambda c: c["IS_TTY"])
SHOW_PROGRESS: bool = Field(default=lambda c: c["IS_TTY"] and c['USE_COLOR'])
config = ExampleConfig(USE_COLOR=False)
print(config.IS_TTY) # Output: True
print(config.USE_COLOR) # Output: False
print(config.SHOW_PROGRESS) # Output: False
"""
model_config = SettingsConfigDict(validate_default=False, case_sensitive=False, extra='ignore')
@model_validator(mode='after')
def fill_defaults(self):
"""Populate any unset values using function provided as their default"""
for key, field in self.model_fields.items():
value = getattr(self, key)
if isinstance(value, Callable):
# if value is a function, execute it to get the actual value, passing existing config as a dict arg
config_so_far = self.dict(exclude_unset=True)
fallback_value = field.default(config_so_far)
# check to make sure default factory return value matches type annotation
TypeAdapter(field.annotation).validate_python(fallback_value)
# set generated default value as final validated value
setattr(self, key, fallback_value)
return self
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment