From df933d089b52a8e2a891eaffdf994eaf337adf77 Mon Sep 17 00:00:00 2001 From: Jonny Date: Mon, 14 Sep 2026 07:11:32 +0200 Subject: [PATCH] feat: add settings DB helpers with default fallback Co-Authored-By: Claude Haiku 4.5 Claude-Session: https://claude.ai/code/session_01V57jSQPqwkGG8BuAXg59X5 --- Claude outputs/main.py | 30 +++++++++++++ Claude outputs/tests/test_settings.py | 64 +++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 Claude outputs/tests/test_settings.py diff --git a/Claude outputs/main.py b/Claude outputs/main.py index 614b62b..e3858f5 100644 --- a/Claude outputs/main.py +++ b/Claude outputs/main.py @@ -304,6 +304,36 @@ async def get_all_memory_facts() -> list: ) +SETTINGS_DEFAULTS = { + "assistant_name": "JARVIS", + "company_name": "MBO-Tech-IT", + "contact_email": "kontakt@mbo-tech-it.de", +} + + +async def get_setting(key: str) -> str: + row = await db_query("SELECT value FROM settings WHERE key = %s", (key,), fetch="one") + return row["value"] if row else SETTINGS_DEFAULTS[key] + + +async def get_all_settings() -> dict: + rows = await db_query("SELECT key, value FROM settings", fetch="all") + merged = dict(SETTINGS_DEFAULTS) + for row in rows: + merged[row["key"]] = row["value"] + return merged + + +async def set_setting(key: str, value: str): + await db_query( + """ + INSERT INTO settings (key, value) VALUES (%s, %s) + ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = CURRENT_TIMESTAMP + """, + (key, value), + ) + + async def upsert_conversation_summary(conversation_id: int, summary: str, embedding: list): await db_query( """ diff --git a/Claude outputs/tests/test_settings.py b/Claude outputs/tests/test_settings.py new file mode 100644 index 0000000..7c9f8ec --- /dev/null +++ b/Claude outputs/tests/test_settings.py @@ -0,0 +1,64 @@ +import os +import sys +from unittest.mock import AsyncMock, MagicMock, patch + +sys.modules["psycopg2"] = MagicMock() +sys.modules["psycopg2.pool"] = MagicMock() +sys.modules["psycopg2.extras"] = MagicMock() + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) + +import pytest + +import main + + +@pytest.mark.asyncio +async def test_get_setting_returns_stored_value(): + with patch.object(main, "db_query", new=AsyncMock(return_value={"value": "Custom GmbH"})) as mock_query: + value = await main.get_setting("company_name") + + assert value == "Custom GmbH" + args, kwargs = mock_query.call_args + assert "SELECT value FROM settings" in args[0] + assert args[1] == ("company_name",) + + +@pytest.mark.asyncio +async def test_get_setting_falls_back_to_default_when_missing(): + with patch.object(main, "db_query", new=AsyncMock(return_value=None)): + value = await main.get_setting("assistant_name") + + assert value == "JARVIS" + + +@pytest.mark.asyncio +async def test_get_all_settings_merges_defaults_with_stored_overrides(): + rows = [{"key": "assistant_name", "value": "FRIDAY"}] + with patch.object(main, "db_query", new=AsyncMock(return_value=rows)): + settings = await main.get_all_settings() + + assert settings == { + "assistant_name": "FRIDAY", + "company_name": "MBO-Tech-IT", + "contact_email": "kontakt@mbo-tech-it.de", + } + + +@pytest.mark.asyncio +async def test_get_all_settings_returns_defaults_when_table_empty(): + with patch.object(main, "db_query", new=AsyncMock(return_value=[])): + settings = await main.get_all_settings() + + assert settings == main.SETTINGS_DEFAULTS + + +@pytest.mark.asyncio +async def test_set_setting_upserts_value(): + with patch.object(main, "db_query", new=AsyncMock(return_value=None)) as mock_query: + await main.set_setting("company_name", "Neue Firma GmbH") + + args, kwargs = mock_query.call_args + assert "INSERT INTO settings" in args[0] + assert "ON CONFLICT (key) DO UPDATE" in args[0] + assert args[1] == ("company_name", "Neue Firma GmbH")