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 .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
|
||||
self._save(set_path(self._load(), path, value))
|
||||
|
||||
|
||||
_DEFAULT_STORE: PreferenceStore = LocalFileStore()
|
||||
|
|
|
|||
|
|
@ -117,3 +117,32 @@ class TestLocalFileStore:
|
|||
store = self._store(tmp_path)
|
||||
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
|
||||
|
||||
|
||||
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