diff --git a/conservancy_beancount/config.py b/conservancy_beancount/config.py index d03ea59915da20b518d4bcf4a3e96d3531621a9b..6d1157ad4d2a5e9c6332fd348e4f7f5d32bd369f 100644 --- a/conservancy_beancount/config.py +++ b/conservancy_beancount/config.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import configparser import decimal import functools import os @@ -74,6 +75,15 @@ class Config: 'XDG_CONFIG_HOME': Path('.config'), } + def __init__(self) -> None: + self.file_config = configparser.ConfigParser() + + def load_file(self, config_path: Optional[Path]=None) -> None: + if config_path is None: + config_path = self.config_file_path() + with config_path.open() as config_file: + self.file_config.read_file(config_file) + def _dir_or_none(self, path: Path) -> Optional[Path]: try: path.mkdir(exist_ok=True) @@ -94,6 +104,15 @@ class Config: retval = default or (Path.home() / self._ENVIRON_DEFAULT_PATHS[key]) return retval + def books_path(self) -> Optional[Path]: + try: + retval = Path(self.file_config['Beancount'].get('books dir')) + except (KeyError, ValueError): + ok = False + else: + ok = retval.is_absolute() + return retval if ok else None + def cache_dir_path(self, name: str='conservancy_beancount') -> Optional[Path]: cache_root = self._path_from_environ('XDG_CACHE_HOME') return ( diff --git a/tests/test_config.py b/tests/test_config.py index 44742b1e3372fd39c36651c147e3f89b617243b4..65743b39e1308619f8d2eb21b8dbf8d49d46501d 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -16,6 +16,7 @@ import contextlib import decimal +import operator import os import re @@ -317,3 +318,27 @@ def test_config_file_path_with_subdir(): expected = testutil.test_path('userconfig/conftest/config.ini') config = config_mod.Config() assert config.config_file_path('conftest') == expected + +@pytest.mark.parametrize('path', [ + None, + testutil.test_path('userconfig/conservancy_beancount/config.ini'), +]) +def test_load_file(path): + config = config_mod.Config() + config.load_file(path) + assert config.books_path() == Path('/test/conservancy_beancount') + +@pytest.mark.parametrize('path_func', [ + lambda path: None, + operator.methodcaller('touch', 0o200), +]) +def test_load_file_error(tmp_path, path_func): + config_path = tmp_path / 'nonexistent.ini' + path_func(config_path) + config = config_mod.Config() + with pytest.raises(OSError): + config.load_file(config_path) + +def test_no_books_path(): + config = config_mod.Config() + assert config.books_path() is None