Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions annet/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

_HOMEDIR_PATH: Optional[str] = None # defaults to ~/.annet
_TEMPLATE_CONTEXT_PATH: Optional[str] = None # defaults to annet/configs/context.yml
_DEFAULT_CONTEXT_PATH: Optional[str] = None # defaults to ~/.annet/context.yml
_DEFAULT_CONTEXT_PATH: Optional[str] = None # defaults to ~/.annet/context.yml, checks for ~/.annet/context.yaml


def get_homedir_path() -> str:
Expand All @@ -53,6 +53,23 @@ def set_homedir_path(path: str) -> None:
_HOMEDIR_PATH = path


def add_context_extension(path: str, default: str, *checks: str) -> str:
existing = []
expanded = os.path.expanduser(path)
if os.path.exists(p := expanded + default):
existing.append(p)
for check in checks:
if os.path.exists(p := expanded + check):
existing.append(p)
if not existing:
return path + default
elif len(existing) == 1:
return existing[0]
exc = ValueError(f"Multiple context files found: {existing}; either delete all but one, or merge them")
setattr(exc, "formatted_output", str(exc))
raise exc


def get_template_context_path() -> str:
if _TEMPLATE_CONTEXT_PATH is None:
set_template_context_path(str(Path(sys.modules["annet"].__file__).parent / "configs/context.yml"))
Expand All @@ -66,7 +83,8 @@ def set_template_context_path(path: str) -> None:

def get_default_context_path() -> str:
if _DEFAULT_CONTEXT_PATH is None:
set_default_context_path("~/.annet/context.yml")
path = add_context_extension("~/.annet/context", ".yml", ".yaml")
set_default_context_path(path)
return _DEFAULT_CONTEXT_PATH


Expand Down
3 changes: 3 additions & 0 deletions docs/usage/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ The path to the configuration file is searched in following order:

* ``ANN_CONTEXT_CONFIG_PATH`` env.
* ``~/.annet/context.yml``.
* ``~/.annet/context.yaml``.
* ``annet/configs/context.yml``.

.. warning:: The simultaneous existence of ``~/.annet/context.yml`` and ``~/.annet/context.yaml`` is considered an error.

Config example:

.. code-block:: yaml
Expand Down
54 changes: 54 additions & 0 deletions tests/annet/test_context_extensions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import os

import pytest
from annet.lib import add_context_extension


@pytest.fixture
def mock_home_directory(tmp_path, monkeypatch):
def mock_expanduser(path):
if path.startswith("~"):
return str(tmp_path) + path[1:]
return path

monkeypatch.setattr(os.path, "expanduser", mock_expanduser)
return tmp_path


def test_add_context_extension_no_files_exist(tmp_path):
base_path = str(tmp_path / "context")
result = add_context_extension(base_path, ".yml", ".yaml")
assert result == base_path + ".yml"


def test_add_context_extension_default_exists(tmp_path):
base_path = tmp_path / "context"
default_path = base_path.with_suffix(".yml")
default_path.touch()

result = add_context_extension(base_path, ".yml", ".yaml")
assert result == str(default_path)


def test_add_context_extension_check_exists(tmp_path):
base_path = tmp_path / "context"
check_file = base_path.with_suffix(".yml")
check_file.touch()

result = add_context_extension(base_path, ".yml", ".json", ".yaml", ".toml")
assert result == str(check_file)


def test_add_context_extension_multiple_files(tmp_path):
base_path = tmp_path / "context"
yml_file = base_path.with_suffix(".yml")
yaml_file = base_path.with_suffix(".yaml")
yml_file.touch()
yaml_file.touch()

with pytest.raises(ValueError) as exc_info:
add_context_extension(base_path, ".yml", ".yaml")

assert "Multiple context files found" in str(exc_info.value)
assert str(yml_file) in str(exc_info.value)
assert str(yaml_file) in str(exc_info.value)