Source code for twtb.config
"""File for the main config."""
import dataclasses
import os
import pathlib
import typing as t
import omegaconf
import typing_extensions as te
from omegaconf import dictconfig
from twtb import utils
from twtb.logic.shared.db import DatabaseConfigSection
from twtb.logic.shared.logging import LoggingConfigSection
from twtb.logic.shared.sentry_config import SentryConfigSection
from twtb.logic.telegram.config import TelegramConfigSection
@dataclasses.dataclass
[docs]class Config(metaclass=utils.Singleton):
"""The main config that holds everything in itself."""
@classmethod
[docs] def _setup(cls) -> te.Self:
"""Set up the config.
It is just load config from file, also it is rewrite config with merged data.
Returns:
:py:class:`.Config` instance.
"""
config_path = BASE_DIR / "data" / "config.yml"
config_path.parent.mkdir(exist_ok=True)
cfg = omegaconf.OmegaConf.structured(cls)
if config_path.exists():
loaded_config = omegaconf.OmegaConf.load(config_path)
cfg = omegaconf.OmegaConf.merge(cfg, loaded_config)
cls._handle_env_variables(cfg)
with open(config_path, "w") as config_file:
omegaconf.OmegaConf.save(cfg, config_file)
return t.cast(te.Self, cfg)
@staticmethod
[docs] def _handle_env_variables(cfg: dictconfig.DictConfig, *, prefix: t.Optional[str] = None) -> None:
"""Process all values, and redef them with values from env variables.
Args:
cfg: :py:class:`.Config` instance.
prefix:
Prefix for env variable. Example ``prefix="telegram"`` and
``key="token"`` will look for ``TELEGRAM_TOKEN``.
"""
for key in cfg:
key_to_look_for = f"{prefix}_{key!r}" if prefix else str(key)
if isinstance(cfg[key], dictconfig.DictConfig):
Config._handle_env_variables(cfg[key], prefix=key_to_look_for)
continue
if key_to_look_for.upper() in os.environ:
cfg[str(key)] = os.environ[str(key).upper()]