From b1f82badf77004820759a366013e9dd95bf2b8a8 Mon Sep 17 00:00:00 2001 From: Brett Smith Date: Tue, 16 Jun 2020 14:42:09 -0400 Subject: [PATCH] config: Get repository directory from config file. One less thing users have to fiddle with to get set up. --- conservancy_beancount/config.py | 39 +++++++++++++++++---------------- setup.py | 2 +- tests/test_config.py | 13 +++++++++++ 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/conservancy_beancount/config.py b/conservancy_beancount/config.py index 91fc3e5..b26737c 100644 --- a/conservancy_beancount/config.py +++ b/conservancy_beancount/config.py @@ -27,6 +27,7 @@ import rt from pathlib import Path from typing import ( + Mapping, NamedTuple, Optional, Tuple, @@ -81,6 +82,7 @@ class Config: def __init__(self) -> None: self.file_config = configparser.ConfigParser() + self.file_config.read_string("[Beancount]\n") def load_file(self, config_path: Optional[Path]=None) -> None: if config_path is None: @@ -91,6 +93,17 @@ class Config: def load_string(self, config_str: str) -> None: self.file_config.read_string(config_str) + def _abspath(self, source: Mapping[str, str], key: str) -> Optional[Path]: + try: + retval = Path(source[key]) + except (KeyError, ValueError): + ok = False + else: + if source is not os.environ: + retval = retval.expanduser() + ok = retval.is_absolute() + return retval if ok else None + def _dir_or_none(self, path: Path) -> Optional[Path]: try: path.mkdir(exist_ok=True) @@ -100,14 +113,8 @@ class Config: return path def _path_from_environ(self, key: str, default: Optional[Path]=None) -> Path: - try: - retval = Path(os.environ[key]) - except (KeyError, ValueError): - ok = False - else: - # Per the spec, non-absolute paths should be ignored. - ok = retval.is_absolute() - if not ok: + retval = self._abspath(os.environ, key) + if retval is None: retval = default or (Path.home() / self._ENVIRON_DEFAULT_PATHS[key]) return retval @@ -119,13 +126,7 @@ class Config: return books.Loader(books_path, self.fiscal_year_begin()) def books_path(self) -> Optional[Path]: - try: - retval = Path(self.file_config['Beancount']['books dir']).expanduser() - except (KeyError, ValueError): - ok = False - else: - ok = retval.is_absolute() - return retval if ok else None + return self._abspath(self.file_config['Beancount'], 'books dir') def cache_dir_path(self, name: str='conservancy_beancount') -> Optional[Path]: cache_root = self._path_from_environ('XDG_CACHE_HOME') @@ -163,10 +164,10 @@ class Config: return decimal.Decimal(10) def repository_path(self) -> Optional[Path]: - try: - return Path(os.environ['CONSERVANCY_REPOSITORY']) - except (KeyError, ValueError): - return None + retval = self._abspath(self.file_config['Beancount'], 'repository dir') + if retval is None: + retval = self._abspath(os.environ, 'CONSERVANCY_REPOSITORY') + return retval def rt_credentials(self) -> RTCredentials: all_creds = zip( diff --git a/setup.py b/setup.py index 57db701..d2742fa 100755 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ from setuptools import setup setup( name='conservancy_beancount', description="Plugin, library, and reports for reading Conservancy's books", - version='1.2.1', + version='1.2.2', author='Software Freedom Conservancy', author_email='info@sfconservancy.org', license='GNU AGPLv3+', diff --git a/tests/test_config.py b/tests/test_config.py index bb4625a..0537d52 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -86,6 +86,19 @@ def update_umask(mask): finally: os.umask(old_mask) +def test_repository_from_file(): + path_s = '/home/good' + with update_environ(CONSERVANCY_REPOSITORY='bad'): + config = config_mod.Config() + config.load_string(f"[Beancount]\nrepository dir = {path_s}\n") + assert config.repository_path() == Path(path_s) + +def test_repository_expands_user(): + path_s = 'tilderepo' + config = config_mod.Config() + config.load_string(f"[Beancount]\nrepository dir = ~/{path_s}\n") + assert config.repository_path() == Path.home() / path_s + def test_repository_from_environment(): config = config_mod.Config() assert config.repository_path() == testutil.test_path('repository')