From d9eb99b72e780433a459aceb5d0f0f6063f68cca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?c=C4=83t=C4=83lin?= Date: Sun, 28 Aug 2022 22:24:16 +0200 Subject: [PATCH] tests: add utils.py tests --- .drone.yml | 1 + halig/config.py | 18 ++++++------------ halig/exceptions.py | 4 ++-- halig/logger.py | 8 +++++--- halig/main.py | 3 ++- halig/utils.py | 4 +--- pyproject.toml | 2 +- tests/test_config.py | 26 ++++++++++++++++++++------ tests/test_utils.py | 33 +++++++++++++++++++++++++++++++++ 9 files changed, 71 insertions(+), 28 deletions(-) create mode 100644 tests/test_utils.py diff --git a/.drone.yml b/.drone.yml index 4a06147..8ef110c 100644 --- a/.drone.yml +++ b/.drone.yml @@ -53,6 +53,7 @@ steps: image: git.roboces.dev/catalin/poetry:beta commands: - apk add --no-cache age openssh + - ssh-keygen -t ed25519 -C "" -N "" -f /root/.ssh/id_ed25519 - .venv/bin/pytest depends_on: - install_deps diff --git a/halig/config.py b/halig/config.py index 8eb4aa9..20939aa 100644 --- a/halig/config.py +++ b/halig/config.py @@ -11,8 +11,7 @@ from pydantic import ( Field, ) -from halig import exceptions -from halig.exceptions import ConfigFileIsInvalid +from halig.exceptions import ConfigFileIsInvalid, ConfigFileDoesNotExist DEFAULT_CONFIGURATION_PATH = Path("~/.config/halig/halig.yml").expanduser() @@ -27,7 +26,7 @@ class EncryptionKeysConfig(BaseSettings): return Path(v).expanduser() if isinstance(v, Path): return v.expanduser() - return v + return v # pragma: no cover class Config(BaseSettings): @@ -52,11 +51,7 @@ version: 1.0.0 return Path(v).expanduser() if isinstance(v, Path): return v.expanduser() - return v - - def dict(self, *args, **kwargs): - values = super().dict() - return {k: str(v) for k, v in values.items()} + return v # pragma: no cover def get_config(config_path: Path = DEFAULT_CONFIGURATION_PATH) -> Config: @@ -64,8 +59,7 @@ def get_config(config_path: Path = DEFAULT_CONFIGURATION_PATH) -> Config: the default config initialization will be provided Args: - config_path (Path): The path to the config, defaults to - DEFAULT_CONFIGURATION_PATH + config_path (Path): The config path, defaults to DEFAULT_CONFIGURATION_PATH Returns: a Config object Raises: @@ -74,10 +68,10 @@ def get_config(config_path: Path = DEFAULT_CONFIGURATION_PATH) -> Config: """ if not config_path: - return Config() + return Config() # pragma: no cover if not config_path.exists(): - raise exceptions.ConfigFileDoesNotExist + raise ConfigFileDoesNotExist with open(config_path, "r") as f: yml = yaml.load(f, Loader=yaml.SafeLoader) diff --git a/halig/exceptions.py b/halig/exceptions.py index 075ad24..8d852a1 100644 --- a/halig/exceptions.py +++ b/halig/exceptions.py @@ -9,7 +9,7 @@ from halig import logger class HaligError(Exception, ABC): @property @abstractmethod - def msg(self) -> str: + def msg(self) -> str: # pragma: no cover ... error_code = 1 @@ -55,7 +55,7 @@ class InvalidNotePath(HaligError): error_code = 7 -def handle_errors(func): +def handle_errors(func): # pragma: no cover # TODO: parse age/sh errors @wraps(func) def inner_function(*args, **kwargs): diff --git a/halig/logger.py b/halig/logger.py index 3ea7434..2f8f860 100644 --- a/halig/logger.py +++ b/halig/logger.py @@ -3,15 +3,17 @@ import seedir as sd from pathlib import Path -def info(text: str): +def info(text: str): # pragma: no cover print(text) -def error(text: str): +def error(text: str): # pragma: no cover rich.print(f"[red]{text}") -def tree(dir_path: Path, print_files: bool = False, print_hidden: bool = False): +def tree( + dir_path: Path, print_files: bool = False, print_hidden: bool = False +): # pragma: no cover def mask(x: str) -> bool: path = Path(x) if path.name.startswith(".") and not print_hidden: diff --git a/halig/main.py b/halig/main.py index c446e26..7e24d2b 100755 --- a/halig/main.py +++ b/halig/main.py @@ -15,6 +15,7 @@ from halig.edit_note import edit_note from halig.exceptions import InvalidNotePath from halig.exceptions import handle_errors from halig.new_note import new_note +from halig.utils import resolve_path app = Typer(pretty_exceptions_enable=False) @@ -66,7 +67,7 @@ def edit(path: Path, configuration_path: Path = DEFAULT_CONFIGURATION_PATH): if path.is_absolute(): raise InvalidNotePath - full_path = (config.notes_root_path / path).expanduser().resolve() + full_path = resolve_path(path) if full_path.is_dir(): return new_note(full_path / f"{datetime.now():%Y-%m-%d}.age", config) diff --git a/halig/utils.py b/halig/utils.py index 217bb9c..cd9cc6d 100644 --- a/halig/utils.py +++ b/halig/utils.py @@ -14,9 +14,7 @@ def resolve_path(path: Path) -> Path: Returns: Path: The resolved path """ - path = Path("~/.config/halig/halig.yml").expanduser() - - return path + return Path(os.path.expandvars(path)).expanduser().resolve() def get_template_data(path: Path) -> str | None: diff --git a/pyproject.toml b/pyproject.toml index 4ccd429..773efeb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "halig" version = "0.1.1" description = "" -authors = ["cătălin "] +authors = ["cătălin <185504a9@duck.com>"] readme = "README.md" [tool.poetry.scripts] diff --git a/tests/test_config.py b/tests/test_config.py index cff26d9..bf81329 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -3,6 +3,7 @@ from tempfile import NamedTemporaryFile import pytest import yaml +from pydantic import ValidationError from halig.config import get_config, Config, EncryptionKeysConfig from halig.exceptions import ConfigFileDoesNotExist, ConfigFileIsInvalid @@ -26,9 +27,9 @@ def test_get_config_raises_invalid_config_file_00(tmpfile): # noqa: F811 get_config(Path(tmpfile.name)) -def test_get_config_raises_invalid_config_file_01(tmpfile): # noqa: F811 +def test_get_config_raises_validation_error(tmpfile): # noqa: F811 yaml.dump({"foo": "bar"}, tmpfile, Dumper=yaml.SafeDumper) - with pytest.raises(ConfigFileIsInvalid): + with pytest.raises(ValidationError): get_config(Path(tmpfile.name)) @@ -50,7 +51,20 @@ def test_get_config(tmpdir): # noqa: F811 public_key_path=public_key_path, private_key_path=private_key_path ), ) - assert config.notes_root_path == notes_root_path - assert config.age_binary_path == age_binary_path - assert config.encryption_keys.public_key_path == public_key_path - assert config.encryption_keys.private_key_path == private_key_path + raw_config = config.dict() + assert ( + config.notes_root_path == notes_root_path == Path(raw_config["notes_root_path"]) + ) + assert ( + config.age_binary_path == age_binary_path == Path(raw_config["age_binary_path"]) + ) + assert ( + config.encryption_keys.public_key_path + == public_key_path + == Path(raw_config["encryption_keys"]["public_key_path"]) + ) + assert ( + config.encryption_keys.private_key_path + == private_key_path + == Path(raw_config["encryption_keys"]["private_key_path"]) + ) diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000..7707232 --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,33 @@ +import os +from pathlib import Path + +from halig.utils import resolve_path + + +def test_resolve_absolute_path(): + path = Path("/foo/bar/baz") + assert resolve_path(path) == path + + +def test_resolve_user_path(): + path = Path("~/foo/bar/baz") + assert resolve_path(path) == path.expanduser() + + +def test_resolve_path_with_envvars(): + os.environ["FOO"] = "foo" + os.environ["BAR"] = "bar" + path = Path("/${FOO}/${BAR}") + assert resolve_path(path) == Path("/foo/bar") + + +def test_resolve_relative_path(): + path = Path("foo/bar/baz") + assert resolve_path(path) == path.resolve() + + +def test_resolve_path_all(): + os.environ["FOO"] = "foo" + os.environ["BAR"] = "bar" + path = Path("foo/bar/$FOO/../$BAR") + assert resolve_path(path) == Path(os.path.expandvars(path)).resolve().expanduser()