Skip to content

Instantly share code, notes, and snippets.

@huaxlin
Last active December 15, 2022 07:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save huaxlin/5494f1510eceafdd8dfe669a37ba9aa5 to your computer and use it in GitHub Desktop.
Save huaxlin/5494f1510eceafdd8dfe669a37ba9aa5 to your computer and use it in GitHub Desktop.
from pathlib import Path
from typing import Any, Dict, Optional, Union
from hydra import compose, initialize_config_dir
from omegaconf import DictConfig
from pydantic import BaseModel, BaseSettings
from pydantic.env_settings import SettingsSourceCallable
# {python project}/app/config.py
project_dir = Path(__file__).parent.parent
def dictconfig_to_pydict(cfg) -> dict:
"""convert omegaconf.DictConfig to python build-in dict
If initialized Settings with hydra and
BaseSetting#changing-priority(env_settings > init_settings ...),
there is bug when partial override config by environ variable.
Convert dictconfig to python build-in dict to fix it.
"""
if not isinstance(cfg, DictConfig):
return cfg
return {k: dictconfig_to_pydict(v) for k, v in cfg.items()}
def hydra_config_settings_source(settings: BaseSettings) -> Dict[str, Any]:
# https://docs.pydantic.dev/usage/settings/#adding-sources
config_dir, config_name = str(project_dir), 'config.yaml'
try:
initialize_config_dir(version_base=None, config_dir=config_dir)
_cfg = compose(config_name)
return dictconfig_to_pydict(_cfg)
except Exception as exc:
raise ValueError(f"initialize config fail. {config_dir = }; {config_name = }") from exc
class Mongo(BaseModel):
HOST: str
PORT: int
DBNAME: str
USER: Optional[str] = None
PASSWORD: Optional[str] = None
class Stuff(BaseModel):
URL: str
TIMEOUT: int
class Settings(BaseSettings):
MONGO: Mongo
STUFF: Stuff
class Config:
case_sensitive = True
frozen = True
env_nested_delimiter = "__"
env_file = ".env"
env_file_encoding = "utf-8"
# https://pydantic-docs.helpmanual.io/usage/settings/#changing-priority
@classmethod
def customise_sources(
cls,
init_settings: SettingsSourceCallable,
env_settings: SettingsSourceCallable,
file_secret_settings: SettingsSourceCallable,
) -> tuple[SettingsSourceCallable, ...]:
return env_settings, init_settings, hydra_config_settings_source, file_secret_settings
settings = Settings()
if __name__ == '__main__':
print(settings)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment