refactor: centralize settings and application services
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest.mock import Mock, patch
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from assistant_bot import application as application_module
|
||||
from assistant_bot.auth import authentication_guard
|
||||
from assistant_bot.config import AppSettings
|
||||
from assistant_bot.handlers import (
|
||||
ask_command,
|
||||
help_command,
|
||||
@@ -22,23 +22,26 @@ from assistant_bot.handlers import (
|
||||
|
||||
class ApplicationRegistrationTests(unittest.TestCase):
|
||||
def test_registers_the_current_public_handlers_in_order(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory, patch.multiple(
|
||||
application_module,
|
||||
get_assistant_password=Mock(return_value="secret"),
|
||||
get_bot_token=Mock(return_value="123456:TEST"),
|
||||
get_db_path=Mock(
|
||||
return_value=Path(directory) / "assistant.sqlite3"
|
||||
),
|
||||
get_assistant_mode=Mock(return_value="local"),
|
||||
get_ollama_base_url=Mock(return_value="http://localhost:11434"),
|
||||
get_whisper_model=Mock(return_value="small"),
|
||||
get_whisper_device=Mock(return_value="cpu"),
|
||||
get_whisper_compute_type=Mock(return_value="int8"),
|
||||
get_whisper_language=Mock(return_value="ru"),
|
||||
get_local_timezone=Mock(return_value=ZoneInfo("UTC")),
|
||||
get_voice_max_duration_seconds=Mock(return_value=120),
|
||||
):
|
||||
application = application_module.create_application()
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
settings = AppSettings(
|
||||
bot_token="123456:TEST",
|
||||
assistant_password="secret",
|
||||
db_path=Path(directory) / "assistant.sqlite3",
|
||||
mode="local",
|
||||
timezone=ZoneInfo("UTC"),
|
||||
voice_max_duration_seconds=120,
|
||||
ollama_base_url="http://localhost:11434",
|
||||
ollama_model="qwen3.5:9b",
|
||||
yandex_cloud_folder=None,
|
||||
yandex_cloud_model="yandexgpt/latest",
|
||||
yandex_stt_model="general",
|
||||
yandex_stt_language="ru-RU",
|
||||
whisper_model="small",
|
||||
whisper_device="cpu",
|
||||
whisper_compute_type="int8",
|
||||
whisper_language="ru",
|
||||
)
|
||||
application = application_module.create_application(settings)
|
||||
|
||||
self.assertEqual(
|
||||
[handler.callback for handler in application.handlers[-1]],
|
||||
|
||||
@@ -4,11 +4,13 @@ from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from telegram.constants import ChatType, ParseMode
|
||||
from telegram.ext import ApplicationHandlerStop
|
||||
|
||||
from assistant_bot.auth import authentication_guard
|
||||
from assistant_bot.services import SERVICES_KEY, ApplicationServices
|
||||
from assistant_bot.storage import AssistantStorage
|
||||
from assistant_bot.telegram_utils import render_markdown_chunks
|
||||
|
||||
@@ -34,8 +36,14 @@ class AuthenticationGuardTests(unittest.IsolatedAsyncioTestCase):
|
||||
context = SimpleNamespace(
|
||||
application=SimpleNamespace(
|
||||
bot_data={
|
||||
"storage": self.storage,
|
||||
"assistant_password": "секрет",
|
||||
SERVICES_KEY: ApplicationServices(
|
||||
storage=self.storage,
|
||||
ai_client=SimpleNamespace(),
|
||||
timezone=ZoneInfo("UTC"),
|
||||
speech_recognizer=SimpleNamespace(),
|
||||
voice_max_duration_seconds=120,
|
||||
assistant_password="секрет",
|
||||
),
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -5,6 +5,35 @@ from unittest.mock import patch
|
||||
from assistant_bot import config
|
||||
|
||||
|
||||
class AppSettingsTests(unittest.TestCase):
|
||||
def test_loads_complete_startup_configuration_once(self) -> None:
|
||||
environment = {
|
||||
config.TOKEN_ENV_NAME: "token",
|
||||
config.PASSWORD_ENV_NAME: "secret",
|
||||
config.MODE_ENV_NAME: "local",
|
||||
config.DB_ENV_NAME: "data/test.sqlite3",
|
||||
config.TIMEZONE_ENV_NAME: "UTC",
|
||||
config.WHISPER_LANGUAGE_ENV_NAME: "auto",
|
||||
}
|
||||
with patch(
|
||||
"assistant_bot.config.load_env_file"
|
||||
) as load_env_file, patch.dict(
|
||||
os.environ,
|
||||
environment,
|
||||
clear=True,
|
||||
):
|
||||
settings = config.load_app_settings()
|
||||
|
||||
load_env_file.assert_called_once_with()
|
||||
self.assertEqual(settings.bot_token, "token")
|
||||
self.assertEqual(settings.assistant_password, "secret")
|
||||
self.assertEqual(settings.mode, "local")
|
||||
self.assertEqual(settings.db_path, config.PROJECT_ROOT / "data/test.sqlite3")
|
||||
self.assertEqual(settings.timezone.key, "UTC")
|
||||
self.assertIsNone(settings.whisper_language)
|
||||
self.assertIsNone(settings.yandex_cloud_folder)
|
||||
|
||||
|
||||
class WhisperConfigTests(unittest.TestCase):
|
||||
def test_gpu_int8_defaults(self) -> None:
|
||||
variable_names = (
|
||||
|
||||
@@ -3,10 +3,12 @@ from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from telegram.constants import ParseMode
|
||||
|
||||
from assistant_bot.handlers import private_voice
|
||||
from assistant_bot.services import SERVICES_KEY, ApplicationServices
|
||||
from assistant_bot.telegram_utils import render_markdown_chunks
|
||||
|
||||
|
||||
@@ -31,8 +33,14 @@ class VoiceHandlerTests(unittest.IsolatedAsyncioTestCase):
|
||||
bot=bot,
|
||||
application=SimpleNamespace(
|
||||
bot_data={
|
||||
"speech_recognizer": recognizer,
|
||||
"voice_max_duration": 120,
|
||||
SERVICES_KEY: ApplicationServices(
|
||||
storage=SimpleNamespace(),
|
||||
ai_client=SimpleNamespace(),
|
||||
timezone=ZoneInfo("UTC"),
|
||||
speech_recognizer=recognizer,
|
||||
voice_max_duration_seconds=120,
|
||||
assistant_password="secret",
|
||||
),
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user