From bc7718c293cb28682aac97a7b2392b8574ae560a Mon Sep 17 00:00:00 2001 From: Auguste Baum <52001167+augustebaum@users.noreply.github.com> Date: Fri, 9 Aug 2024 15:00:25 +0200 Subject: [PATCH] set default behavior when `storage` argument is not given to `Store` (#147) Closes #125 --- src/mandr/store/store.py | 28 +++++++++++++++++-- tests/integration/test_default_store.py | 37 +++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 tests/integration/test_default_store.py diff --git a/src/mandr/store/store.py b/src/mandr/store/store.py index 017667ca1..ac3a696e9 100644 --- a/src/mandr/store/store.py +++ b/src/mandr/store/store.py @@ -3,11 +3,13 @@ from __future__ import annotations import dataclasses +import os from datetime import UTC, datetime +from pathlib import Path from typing import TYPE_CHECKING from mandr.item import DisplayType, Item, ItemMetadata -from mandr.storage import URI +from mandr.storage import URI, FileSystem if TYPE_CHECKING: from pathlib import PosixPath @@ -16,12 +18,34 @@ from mandr.storage import Storage +class MandrRootException(Exception): + """Raise when the MANDR_ROOT variable is set to a relative path.""" + + +def _get_storage_path(MANDR_ROOT: str | None) -> Path: + """Decide on the `Storage`'s location based on MANDR_ROOT.""" + if MANDR_ROOT is None: + return Path.cwd() / ".datamander" + + if not Path(MANDR_ROOT).is_absolute(): + raise MandrRootException( + "MANDR_ROOT must be set to an absolute path or unset, not set " + f"to a relative path; got '{MANDR_ROOT}'." + ) + + return Path(MANDR_ROOT) + + class Store: """Object used to store pairs of (key, value) by URI over a storage.""" def __init__(self, uri: URI | PosixPath | str, storage: Storage = None): self.uri = URI(uri) - self.storage = storage + if storage is None: + directory = _get_storage_path(os.environ.get("MANDR_ROOT")) + self.storage = FileSystem(directory=directory) + else: + self.storage = storage def __eq__(self, other: Any): """Return self == other.""" diff --git a/tests/integration/test_default_store.py b/tests/integration/test_default_store.py new file mode 100644 index 000000000..8b24e503e --- /dev/null +++ b/tests/integration/test_default_store.py @@ -0,0 +1,37 @@ +from pathlib import Path + +import pytest +from mandr.storage import FileSystem +from mandr.store import Store +from mandr.store.store import MandrRootException + + +class TestDefaultStorage: + """Test the behaviour of initialisation Mandr when `storage` is not given.""" + + def test_absolute_path(self, monkeypatch, tmp_path): + """If MANDR_ROOT is an absolute path, the storage is in MANDR_ROOT.""" + monkeypatch.setenv("MANDR_ROOT", str(tmp_path)) + + store = Store("root/probabl") + + assert isinstance(store.storage, FileSystem) + assert Path(store.storage.cache.directory) == tmp_path + + def test_relative_path(self, monkeypatch, tmp_path): + """If MANDR_ROOT is a relative path, we raise an error.""" + monkeypatch.setattr("pathlib.Path.cwd", lambda: tmp_path) + monkeypatch.setenv("MANDR_ROOT", ".not_datamander") + + with pytest.raises(MandrRootException, match="got '.not_datamander'"): + Store("root/probabl") + + def test_relative_path_no_mandr_root(self, monkeypatch, tmp_path): + """If MANDR_ROOT is unset, the storage is in ".datamander", + relative to the current working directory.""" + monkeypatch.setattr("pathlib.Path.cwd", lambda: tmp_path) + + store = Store("root/probabl") + + assert isinstance(store.storage, FileSystem) + assert Path(store.storage.cache.directory) == tmp_path / ".datamander"