diff --git a/src/delta_barth/config.py b/src/delta_barth/config.py new file mode 100644 index 0000000..85bb14e --- /dev/null +++ b/src/delta_barth/config.py @@ -0,0 +1,43 @@ +from __future__ import annotations + +from pathlib import Path + +import dopt_basics.configs +from pydantic import BaseModel + + +class Config(BaseModel): + forecast: CfgForecast + + +class CfgForecast(BaseModel): + threshold_month_data_points: int + + +class LazyCfgLoader: + def __init__( + self, + cfg_path: Path, + ) -> None: + cfg_path = cfg_path.resolve() + assert cfg_path.exists(), f"config path {cfg_path} seems not to exist" + assert cfg_path.is_file(), f"config path {cfg_path} seems not to be a file" + self._path = cfg_path + self._cfg: Config | None = None + + @property + def path(self) -> Path: + return self._path + + def _load(self) -> Config: + cfg = dopt_basics.configs.load_toml(self.path) + + return Config(**cfg) + + def reload(self) -> None: + self._cfg = self._load() + + def get(self) -> Config: + if self._cfg is None: + self._cfg = self._load() + return self._cfg diff --git a/src/delta_barth/dopt-cfg.toml b/src/delta_barth/dopt-cfg.toml new file mode 100644 index 0000000..33eba72 --- /dev/null +++ b/src/delta_barth/dopt-cfg.toml @@ -0,0 +1,2 @@ +[forecast] +threshold_month_data_points = 28 \ No newline at end of file diff --git a/src/delta_barth/logging.py b/src/delta_barth/logging.py index f6e3e08..5e1d3df 100644 --- a/src/delta_barth/logging.py +++ b/src/delta_barth/logging.py @@ -31,6 +31,8 @@ logger_status = logging.getLogger("delta_barth.status") logger_status.setLevel(logging.DEBUG) logger_session = logging.getLogger("delta_barth.session") logger_session.setLevel(logging.DEBUG) +logger_config = logging.getLogger("delta_barth.config") +logger_config.setLevel(logging.DEBUG) logger_management = logging.getLogger("delta_barth.management") logger_management.setLevel(logging.DEBUG) logger_wrapped_results = logging.getLogger("delta_barth.wrapped_results") diff --git a/tests/_test_data/dopt-cfg.toml b/tests/_test_data/dopt-cfg.toml new file mode 100644 index 0000000..33eba72 --- /dev/null +++ b/tests/_test_data/dopt-cfg.toml @@ -0,0 +1,2 @@ +[forecast] +threshold_month_data_points = 28 \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index 52878e7..42ed397 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -33,6 +33,15 @@ def api_base_url(credentials) -> str: return credentials["base_url"] +@pytest.fixture(scope="session") +def pth_dummy_cfg() -> Path: + pwd = Path.cwd() + assert "barth" in pwd.parent.name.lower(), "not in project root directory" + data_pth = pwd / "./tests/_test_data/dopt-cfg.toml" + assert data_pth.exists(), "file to dummy CFG not found" + return data_pth + + @pytest.fixture(scope="session") def sales_data_real() -> pd.DataFrame: pwd = Path.cwd() diff --git a/tests/test_config.py b/tests/test_config.py new file mode 100644 index 0000000..bcef362 --- /dev/null +++ b/tests/test_config.py @@ -0,0 +1,58 @@ +import tomllib +from pathlib import Path + +import pytest +import tomli_w + +from delta_barth import config + + +@pytest.fixture(scope="function") +def pth_cfg(pth_dummy_cfg, tmp_path) -> Path: + with open(pth_dummy_cfg, "rb") as file: + cfg_data = tomllib.load(file) + + target = tmp_path / "dummy_cfg.toml" + target.touch() + with open(target, "wb") as file: + tomli_w.dump(cfg_data, file) + + return target + + +@pytest.mark.new +def test_CfgLoader_Init(pth_cfg): + loader = config.LazyCfgLoader(pth_cfg) + + assert loader.path == pth_cfg + assert loader._cfg is None + + +@pytest.mark.new +def test_CfgLoader_Get(pth_cfg): + loader = config.LazyCfgLoader(pth_cfg) + + parsed_cfg = loader.get() + assert isinstance(parsed_cfg, config.Config) + assert parsed_cfg.forecast.threshold_month_data_points == 28 + + +@pytest.mark.new +def test_CfgLoader_Reload(pth_cfg): + loader = config.LazyCfgLoader(pth_cfg) + + parsed_cfg = loader.get() + assert isinstance(parsed_cfg, config.Config) + assert parsed_cfg.forecast.threshold_month_data_points == 28 + # modify config and reload + with open(pth_cfg, "rb") as file: + cfg_data = tomllib.load(file) + cfg_data["forecast"]["threshold_month_data_points"] = 30 + with open(pth_cfg, "wb") as file: + tomli_w.dump(cfg_data, file) + + assert parsed_cfg.forecast.threshold_month_data_points == 28 + loader.reload() + parsed_cfg = loader.get() + assert isinstance(parsed_cfg, config.Config) + assert parsed_cfg.forecast.threshold_month_data_points == 30