config: Get repository directory from config file.
One less thing users have to fiddle with to get set up.
This commit is contained in:
parent
efe9bd8855
commit
b1f82badf7
3 changed files with 34 additions and 20 deletions
|
@ -27,6 +27,7 @@ import rt
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import (
|
from typing import (
|
||||||
|
Mapping,
|
||||||
NamedTuple,
|
NamedTuple,
|
||||||
Optional,
|
Optional,
|
||||||
Tuple,
|
Tuple,
|
||||||
|
@ -81,6 +82,7 @@ class Config:
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.file_config = configparser.ConfigParser()
|
self.file_config = configparser.ConfigParser()
|
||||||
|
self.file_config.read_string("[Beancount]\n")
|
||||||
|
|
||||||
def load_file(self, config_path: Optional[Path]=None) -> None:
|
def load_file(self, config_path: Optional[Path]=None) -> None:
|
||||||
if config_path is None:
|
if config_path is None:
|
||||||
|
@ -91,6 +93,17 @@ class Config:
|
||||||
def load_string(self, config_str: str) -> None:
|
def load_string(self, config_str: str) -> None:
|
||||||
self.file_config.read_string(config_str)
|
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]:
|
def _dir_or_none(self, path: Path) -> Optional[Path]:
|
||||||
try:
|
try:
|
||||||
path.mkdir(exist_ok=True)
|
path.mkdir(exist_ok=True)
|
||||||
|
@ -100,14 +113,8 @@ class Config:
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def _path_from_environ(self, key: str, default: Optional[Path]=None) -> Path:
|
def _path_from_environ(self, key: str, default: Optional[Path]=None) -> Path:
|
||||||
try:
|
retval = self._abspath(os.environ, key)
|
||||||
retval = Path(os.environ[key])
|
if retval is None:
|
||||||
except (KeyError, ValueError):
|
|
||||||
ok = False
|
|
||||||
else:
|
|
||||||
# Per the spec, non-absolute paths should be ignored.
|
|
||||||
ok = retval.is_absolute()
|
|
||||||
if not ok:
|
|
||||||
retval = default or (Path.home() / self._ENVIRON_DEFAULT_PATHS[key])
|
retval = default or (Path.home() / self._ENVIRON_DEFAULT_PATHS[key])
|
||||||
return retval
|
return retval
|
||||||
|
|
||||||
|
@ -119,13 +126,7 @@ class Config:
|
||||||
return books.Loader(books_path, self.fiscal_year_begin())
|
return books.Loader(books_path, self.fiscal_year_begin())
|
||||||
|
|
||||||
def books_path(self) -> Optional[Path]:
|
def books_path(self) -> Optional[Path]:
|
||||||
try:
|
return self._abspath(self.file_config['Beancount'], 'books dir')
|
||||||
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
|
|
||||||
|
|
||||||
def cache_dir_path(self, name: str='conservancy_beancount') -> Optional[Path]:
|
def cache_dir_path(self, name: str='conservancy_beancount') -> Optional[Path]:
|
||||||
cache_root = self._path_from_environ('XDG_CACHE_HOME')
|
cache_root = self._path_from_environ('XDG_CACHE_HOME')
|
||||||
|
@ -163,10 +164,10 @@ class Config:
|
||||||
return decimal.Decimal(10)
|
return decimal.Decimal(10)
|
||||||
|
|
||||||
def repository_path(self) -> Optional[Path]:
|
def repository_path(self) -> Optional[Path]:
|
||||||
try:
|
retval = self._abspath(self.file_config['Beancount'], 'repository dir')
|
||||||
return Path(os.environ['CONSERVANCY_REPOSITORY'])
|
if retval is None:
|
||||||
except (KeyError, ValueError):
|
retval = self._abspath(os.environ, 'CONSERVANCY_REPOSITORY')
|
||||||
return None
|
return retval
|
||||||
|
|
||||||
def rt_credentials(self) -> RTCredentials:
|
def rt_credentials(self) -> RTCredentials:
|
||||||
all_creds = zip(
|
all_creds = zip(
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -5,7 +5,7 @@ from setuptools import setup
|
||||||
setup(
|
setup(
|
||||||
name='conservancy_beancount',
|
name='conservancy_beancount',
|
||||||
description="Plugin, library, and reports for reading Conservancy's books",
|
description="Plugin, library, and reports for reading Conservancy's books",
|
||||||
version='1.2.1',
|
version='1.2.2',
|
||||||
author='Software Freedom Conservancy',
|
author='Software Freedom Conservancy',
|
||||||
author_email='info@sfconservancy.org',
|
author_email='info@sfconservancy.org',
|
||||||
license='GNU AGPLv3+',
|
license='GNU AGPLv3+',
|
||||||
|
|
|
@ -86,6 +86,19 @@ def update_umask(mask):
|
||||||
finally:
|
finally:
|
||||||
os.umask(old_mask)
|
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():
|
def test_repository_from_environment():
|
||||||
config = config_mod.Config()
|
config = config_mod.Config()
|
||||||
assert config.repository_path() == testutil.test_path('repository')
|
assert config.repository_path() == testutil.test_path('repository')
|
||||||
|
|
Loading…
Reference in a new issue