Last active
September 23, 2024 00:11
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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