feat: preferences public helpers — get_user_preference / set_user_preference (closes #22 self-hosted)
This commit is contained in:
parent
0d9d030320
commit
d719ea2309
3 changed files with 77 additions and 1 deletions
|
|
@ -1,3 +1,47 @@
|
||||||
|
from . import store as store_module
|
||||||
from .paths import get_path, set_path
|
from .paths import get_path, set_path
|
||||||
|
from .store import LocalFileStore, PreferenceStore
|
||||||
|
|
||||||
__all__ = ["get_path", "set_path"]
|
|
||||||
|
def get_user_preference(
|
||||||
|
user_id: str | None,
|
||||||
|
path: str,
|
||||||
|
default=None,
|
||||||
|
store: PreferenceStore | None = None,
|
||||||
|
):
|
||||||
|
"""Read a preference value at dot-separated *path*.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user_id: User identifier (passed to store; local store ignores it).
|
||||||
|
path: Dot-separated preference path, e.g. ``"affiliate.opt_out"``.
|
||||||
|
default: Returned when the path is not set.
|
||||||
|
store: Optional store override; defaults to ``LocalFileStore`` at
|
||||||
|
``~/.config/circuitforge/preferences.yaml``.
|
||||||
|
"""
|
||||||
|
s = store or store_module._DEFAULT_STORE
|
||||||
|
return s.get(user_id=user_id, path=path, default=default)
|
||||||
|
|
||||||
|
|
||||||
|
def set_user_preference(
|
||||||
|
user_id: str | None,
|
||||||
|
path: str,
|
||||||
|
value,
|
||||||
|
store: PreferenceStore | None = None,
|
||||||
|
) -> None:
|
||||||
|
"""Write *value* at dot-separated *path*.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user_id: User identifier (passed to store; local store ignores it).
|
||||||
|
path: Dot-separated preference path, e.g. ``"affiliate.byok_ids.ebay"``.
|
||||||
|
value: Value to persist.
|
||||||
|
store: Optional store override; defaults to ``LocalFileStore``.
|
||||||
|
"""
|
||||||
|
s = store or store_module._DEFAULT_STORE
|
||||||
|
s.set(user_id=user_id, path=path, value=value)
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"get_path", "set_path",
|
||||||
|
"get_user_preference", "set_user_preference",
|
||||||
|
"LocalFileStore", "PreferenceStore",
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -73,3 +73,6 @@ class LocalFileStore:
|
||||||
|
|
||||||
def set(self, user_id: str | None, path: str, value: Any) -> None: # noqa: ARG002
|
def set(self, user_id: str | None, path: str, value: Any) -> None: # noqa: ARG002
|
||||||
self._save(set_path(self._load(), path, value))
|
self._save(set_path(self._load(), path, value))
|
||||||
|
|
||||||
|
|
||||||
|
_DEFAULT_STORE: PreferenceStore = LocalFileStore()
|
||||||
|
|
|
||||||
|
|
@ -117,3 +117,32 @@ class TestLocalFileStore:
|
||||||
store = self._store(tmp_path)
|
store = self._store(tmp_path)
|
||||||
store.set(user_id="u123", path="affiliate.opt_out", value=True)
|
store.set(user_id="u123", path="affiliate.opt_out", value=True)
|
||||||
assert store.get(user_id="u456", path="affiliate.opt_out", default=False) is True
|
assert store.get(user_id="u456", path="affiliate.opt_out", default=False) is True
|
||||||
|
|
||||||
|
|
||||||
|
from circuitforge_core.preferences import get_user_preference, set_user_preference
|
||||||
|
|
||||||
|
|
||||||
|
class TestPreferenceHelpers:
|
||||||
|
def _store(self, tmp_path) -> LocalFileStore:
|
||||||
|
return LocalFileStore(prefs_path=tmp_path / "preferences.yaml")
|
||||||
|
|
||||||
|
def test_get_returns_default_when_unset(self, tmp_path):
|
||||||
|
store = self._store(tmp_path)
|
||||||
|
result = get_user_preference(user_id=None, path="affiliate.opt_out",
|
||||||
|
default=False, store=store)
|
||||||
|
assert result is False
|
||||||
|
|
||||||
|
def test_set_then_get(self, tmp_path):
|
||||||
|
store = self._store(tmp_path)
|
||||||
|
set_user_preference(user_id=None, path="affiliate.opt_out", value=True, store=store)
|
||||||
|
result = get_user_preference(user_id=None, path="affiliate.opt_out",
|
||||||
|
default=False, store=store)
|
||||||
|
assert result is True
|
||||||
|
|
||||||
|
def test_default_store_is_local(self, tmp_path, monkeypatch):
|
||||||
|
"""When no store is passed, helpers use LocalFileStore at default path."""
|
||||||
|
from circuitforge_core.preferences import store as store_module
|
||||||
|
local = self._store(tmp_path)
|
||||||
|
monkeypatch.setattr(store_module, "_DEFAULT_STORE", local)
|
||||||
|
set_user_preference(user_id=None, path="x.y", value=42)
|
||||||
|
assert get_user_preference(user_id=None, path="x.y") == 42
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue