* feat(asr): add chat audio remote benchmarking * style(asr): apply black formatting * test(main): include remote API model kwarg * test(asr): add coverage for chat-completions error handling and parsing Add 10 new tests to cover uncovered lines in PR #468: - ConnectionError handler in _try_chat_completions_audio_api (lines 1601-1602) - _parse_chat_completion_transcription edge cases: None, list content, empty/whitespace strings, JSON without text field, plain text, and single-line language metadata (lines 1610, 1613-1621, 1625, 1629-1640) Coverage for recognition_manager.py improved from 85% to 86%. * feat(asr): support FunASR remote responses * refactor(asr): scope remote FunASR support to the #469 path Drop chat-completions/Qwen client, evaluation notes, and the remote ASR benchmark harness. Keep model field, tolerant OpenAI response parsing, SenseVoice label stripping, FunASR docs, and tests.
563 lines
23 KiB
Python
563 lines
23 KiB
Python
"""
|
|
Tests for the config manager functionality.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import shutil
|
|
import tempfile
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
# Update import path to use the new package structure
|
|
from vocalinux.ui.config_manager import DEFAULT_CONFIG, ConfigManager
|
|
|
|
|
|
def _ensure_test_config_dir(path: str):
|
|
"""Create the temp config directory without relying on recursive makedirs patches."""
|
|
parent_dir = os.path.dirname(path)
|
|
if not os.path.exists(parent_dir):
|
|
os.mkdir(parent_dir)
|
|
if not os.path.exists(path):
|
|
os.mkdir(path)
|
|
|
|
|
|
class TestConfigManager(unittest.TestCase):
|
|
"""Test cases for the configuration manager."""
|
|
|
|
def setUp(self):
|
|
"""Set up test environment."""
|
|
# Create a temporary directory for configuration
|
|
self.temp_dir = tempfile.TemporaryDirectory()
|
|
self.temp_config_dir = os.path.join(self.temp_dir.name, ".config/vocalinux")
|
|
_ensure_test_config_dir(self.temp_config_dir)
|
|
self.temp_config_file = os.path.join(self.temp_config_dir, "config.json")
|
|
|
|
# Patch the config paths to use our temporary directory
|
|
self.config_dir_patcher = patch(
|
|
"vocalinux.ui.config_manager.CONFIG_DIR", self.temp_config_dir
|
|
)
|
|
self.config_file_patcher = patch(
|
|
"vocalinux.ui.config_manager.CONFIG_FILE", self.temp_config_file
|
|
)
|
|
self.makedirs_patcher = patch(
|
|
"vocalinux.ui.config_manager.os.makedirs",
|
|
side_effect=lambda path, exist_ok=True: _ensure_test_config_dir(path),
|
|
)
|
|
|
|
self.config_dir_patcher.start()
|
|
self.config_file_patcher.start()
|
|
self.makedirs_patcher.start()
|
|
|
|
# Recreate after patching so each test starts from a known config path.
|
|
_ensure_test_config_dir(self.temp_config_dir)
|
|
|
|
# Patch logging to avoid actual logging
|
|
self.logger_patcher = patch("vocalinux.ui.config_manager.logger")
|
|
self.mock_logger = self.logger_patcher.start()
|
|
|
|
def tearDown(self):
|
|
"""Clean up after tests."""
|
|
self.config_dir_patcher.stop()
|
|
self.config_file_patcher.stop()
|
|
self.makedirs_patcher.stop()
|
|
self.logger_patcher.stop()
|
|
self.temp_dir.cleanup()
|
|
|
|
def test_init_default_config(self):
|
|
"""Test initialization with default configuration."""
|
|
config_manager = ConfigManager()
|
|
self.assertEqual(config_manager.config, DEFAULT_CONFIG)
|
|
self.mock_logger.info.assert_called_with(
|
|
f"Config file not found at {self.temp_config_file}. Using defaults."
|
|
)
|
|
self.assertTrue(os.path.exists(self.temp_config_dir))
|
|
|
|
def test_ensure_config_dir(self):
|
|
"""Test that _ensure_config_dir creates the directory."""
|
|
# Delete the config directory to test creation
|
|
shutil.rmtree(self.temp_config_dir)
|
|
self.assertFalse(os.path.exists(self.temp_config_dir))
|
|
|
|
# Create config manager, which should create the directory
|
|
ConfigManager()
|
|
self.assertTrue(os.path.exists(self.temp_config_dir))
|
|
|
|
def test_load_config(self):
|
|
"""Test loading configuration from file."""
|
|
# Create a test config file
|
|
test_config = {
|
|
"speech_recognition": {
|
|
"engine": "whisper",
|
|
"model_size": "large",
|
|
},
|
|
"ui": {
|
|
"start_minimized": True,
|
|
},
|
|
}
|
|
|
|
with open(self.temp_config_file, "w") as f:
|
|
json.dump(test_config, f)
|
|
|
|
# Load the config
|
|
config_manager = ConfigManager()
|
|
|
|
# Verify it merged with defaults correctly
|
|
self.assertEqual(config_manager.config["speech_recognition"]["engine"], "whisper")
|
|
self.assertEqual(config_manager.config["speech_recognition"]["model_size"], "large")
|
|
self.assertEqual(
|
|
config_manager.config["speech_recognition"]["vad_sensitivity"], 3
|
|
) # From defaults
|
|
self.assertEqual(config_manager.config["ui"]["start_minimized"], True)
|
|
self.assertEqual(config_manager.config["ui"]["show_notifications"], True) # From defaults
|
|
|
|
def test_load_config_file_error(self):
|
|
"""Test handling of errors when loading config file."""
|
|
# Create a broken config file
|
|
with open(self.temp_config_file, "w") as f:
|
|
f.write("{broken json")
|
|
|
|
# Load the config - with broken JSON, it should use defaults
|
|
config_manager = ConfigManager()
|
|
|
|
# Verify it used defaults - check key structure exists
|
|
self.assertIn("speech_recognition", config_manager.config)
|
|
self.assertIn("engine", config_manager.config["speech_recognition"])
|
|
self.assertIn("ui", config_manager.config)
|
|
|
|
# Verify logger.error was called for the broken JSON
|
|
self.mock_logger.error.assert_called()
|
|
|
|
def test_save_config(self):
|
|
"""Test saving configuration to file."""
|
|
config_manager = ConfigManager()
|
|
|
|
# Modify config
|
|
config_manager.config["speech_recognition"]["engine"] = "whisper"
|
|
config_manager.config["ui"]["start_minimized"] = True
|
|
|
|
# Save config
|
|
result = config_manager.save_config()
|
|
self.assertTrue(result)
|
|
|
|
# Verify file was created with correct content
|
|
self.assertTrue(os.path.exists(self.temp_config_file))
|
|
with open(self.temp_config_file, "r") as f:
|
|
saved_config = json.load(f)
|
|
|
|
self.assertEqual(saved_config["speech_recognition"]["engine"], "whisper")
|
|
self.assertEqual(saved_config["ui"]["start_minimized"], True)
|
|
|
|
def test_save_config_error(self):
|
|
"""Test handling of errors when saving config file."""
|
|
config_manager = ConfigManager()
|
|
|
|
# Mock open to raise an exception
|
|
with patch("builtins.open", side_effect=PermissionError("Permission denied")):
|
|
result = config_manager.save_config()
|
|
self.assertFalse(result)
|
|
self.mock_logger.error.assert_called()
|
|
|
|
def test_get_existing_value(self):
|
|
"""Test getting an existing configuration value from defaults."""
|
|
# Test that DEFAULT_CONFIG constant has the expected default engine
|
|
# Import directly to get the current value (not cached from earlier imports)
|
|
import importlib
|
|
|
|
import vocalinux.ui.config_manager as cm
|
|
|
|
importlib.reload(cm)
|
|
self.assertEqual(
|
|
cm.DEFAULT_CONFIG["speech_recognition"]["engine"], "whisper_cpp"
|
|
) # Default is whisper_cpp for best performance with Vulkan support
|
|
|
|
# Also test the get method works - it should return a valid engine value
|
|
config_manager = ConfigManager()
|
|
value = config_manager.get("speech_recognition", "engine")
|
|
self.assertIn(value, ["vosk", "whisper", "whisper_cpp"]) # Should be one of valid engines
|
|
self.assertEqual(
|
|
config_manager.get("speech_recognition", "remote_api_model"),
|
|
"whisper-1",
|
|
)
|
|
|
|
def test_get_nonexistent_value(self):
|
|
"""Test getting a nonexistent configuration value."""
|
|
config_manager = ConfigManager()
|
|
value = config_manager.get("nonexistent", "key", "default_value")
|
|
self.assertEqual(value, "default_value")
|
|
|
|
def test_set_existing_section(self):
|
|
"""Test setting a value in an existing section."""
|
|
config_manager = ConfigManager()
|
|
result = config_manager.set("speech_recognition", "engine", "vosk")
|
|
self.assertTrue(result)
|
|
self.assertEqual(config_manager.config["speech_recognition"]["engine"], "vosk")
|
|
|
|
def test_set_new_section(self):
|
|
"""Test setting a value in a new section."""
|
|
config_manager = ConfigManager()
|
|
result = config_manager.set("new_section", "key", "value")
|
|
self.assertTrue(result)
|
|
self.assertEqual(config_manager.config["new_section"]["key"], "value")
|
|
|
|
def test_set_error(self):
|
|
"""Test handling of errors when setting a value."""
|
|
config_manager = ConfigManager()
|
|
config_manager.config = 1 # Not a dict, will cause error
|
|
result = config_manager.set("section", "key", "value")
|
|
self.assertFalse(result)
|
|
self.mock_logger.error.assert_called()
|
|
|
|
def test_update_dict_recursive(self):
|
|
"""Test recursive dictionary update."""
|
|
target = {"a": {"b": 1, "c": 2}, "d": 3}
|
|
|
|
source = {"a": {"b": 10, "e": 20}, "f": 30}
|
|
|
|
config_manager = ConfigManager()
|
|
config_manager._update_dict_recursive(target, source)
|
|
|
|
# Check that values were updated correctly
|
|
self.assertEqual(target["a"]["b"], 10) # Updated
|
|
self.assertEqual(target["a"]["c"], 2) # Unchanged
|
|
self.assertEqual(target["a"]["e"], 20) # Added
|
|
self.assertEqual(target["d"], 3) # Unchanged
|
|
self.assertEqual(target["f"], 30) # Added
|
|
|
|
def test_get_model_size_for_engine(self):
|
|
"""Test getting model size for a specific engine."""
|
|
config_manager = ConfigManager()
|
|
|
|
# Test default values
|
|
self.assertEqual(config_manager.get_model_size_for_engine("vosk"), "small")
|
|
self.assertEqual(config_manager.get_model_size_for_engine("whisper"), "tiny")
|
|
|
|
# Set specific model sizes
|
|
config_manager.set_model_size_for_engine("vosk", "medium")
|
|
config_manager.set_model_size_for_engine("whisper", "small")
|
|
|
|
# Verify they are returned correctly
|
|
self.assertEqual(config_manager.get_model_size_for_engine("vosk"), "medium")
|
|
self.assertEqual(config_manager.get_model_size_for_engine("whisper"), "small")
|
|
|
|
def test_set_model_size_for_engine(self):
|
|
"""Test setting model size for a specific engine."""
|
|
config_manager = ConfigManager()
|
|
|
|
# Set model size for vosk
|
|
config_manager.set_model_size_for_engine("vosk", "large")
|
|
self.assertEqual(config_manager.config["speech_recognition"]["vosk_model_size"], "large")
|
|
self.assertEqual(config_manager.config["speech_recognition"]["model_size"], "large")
|
|
|
|
# Set model size for whisper
|
|
config_manager.set_model_size_for_engine("whisper", "medium")
|
|
self.assertEqual(
|
|
config_manager.config["speech_recognition"]["whisper_model_size"], "medium"
|
|
)
|
|
self.assertEqual(config_manager.config["speech_recognition"]["model_size"], "medium")
|
|
|
|
def test_migrate_old_config(self):
|
|
"""Test migration of old config format without per-engine model sizes."""
|
|
# Create an old-style config file without per-engine model sizes
|
|
old_config = {
|
|
"speech_recognition": {
|
|
"engine": "vosk",
|
|
"model_size": "medium",
|
|
"vad_sensitivity": 3,
|
|
"silence_timeout": 2.0,
|
|
}
|
|
}
|
|
|
|
with open(self.temp_config_file, "w") as f:
|
|
json.dump(old_config, f)
|
|
|
|
# Load the config (should trigger migration)
|
|
config_manager = ConfigManager()
|
|
|
|
# Verify migration added per-engine model sizes
|
|
self.assertEqual(config_manager.config["speech_recognition"]["vosk_model_size"], "medium")
|
|
self.assertEqual(config_manager.config["speech_recognition"]["whisper_model_size"], "tiny")
|
|
|
|
def test_update_speech_recognition_settings_per_engine(self):
|
|
"""Test that update_speech_recognition_settings saves per-engine model sizes."""
|
|
config_manager = ConfigManager()
|
|
|
|
# Update settings for vosk
|
|
config_manager.update_speech_recognition_settings({"engine": "vosk", "model_size": "large"})
|
|
|
|
self.assertEqual(config_manager.config["speech_recognition"]["vosk_model_size"], "large")
|
|
|
|
# Update settings for whisper
|
|
config_manager.update_speech_recognition_settings(
|
|
{"engine": "whisper", "model_size": "small"}
|
|
)
|
|
|
|
self.assertEqual(config_manager.config["speech_recognition"]["whisper_model_size"], "small")
|
|
|
|
# Verify the vosk setting wasn't changed
|
|
self.assertEqual(config_manager.config["speech_recognition"]["vosk_model_size"], "large")
|
|
|
|
def test_save_settings(self):
|
|
"""Test the save_settings method (alias for save_config)."""
|
|
config_manager = ConfigManager()
|
|
|
|
# Modify config
|
|
config_manager.config["speech_recognition"]["engine"] = "vosk"
|
|
|
|
# Save settings
|
|
result = config_manager.save_settings()
|
|
self.assertTrue(result)
|
|
|
|
# Verify file was saved
|
|
self.assertTrue(os.path.exists(self.temp_config_file))
|
|
with open(self.temp_config_file, "r") as f:
|
|
saved_config = json.load(f)
|
|
self.assertEqual(saved_config["speech_recognition"]["engine"], "vosk")
|
|
|
|
def test_get_settings(self):
|
|
"""Test the get_settings method returns the entire config."""
|
|
config_manager = ConfigManager()
|
|
|
|
# Get settings
|
|
settings = config_manager.get_settings()
|
|
|
|
# Verify it returns the config
|
|
self.assertEqual(settings, config_manager.config)
|
|
self.assertIn("speech_recognition", settings)
|
|
self.assertIn("ui", settings)
|
|
|
|
def test_get_model_size_for_engine_with_engine_specific_key(self):
|
|
"""Test getting model size when engine-specific key exists."""
|
|
# Create config with engine-specific model sizes
|
|
test_config = {
|
|
"speech_recognition": {
|
|
"engine": "whisper",
|
|
"vosk_model_size": "medium",
|
|
"whisper_model_size": "small",
|
|
"model_size": "large", # Generic fallback
|
|
}
|
|
}
|
|
|
|
with open(self.temp_config_file, "w") as f:
|
|
json.dump(test_config, f)
|
|
|
|
config_manager = ConfigManager()
|
|
|
|
# Should use engine-specific size, not generic
|
|
self.assertEqual(config_manager.get_model_size_for_engine("vosk"), "medium")
|
|
self.assertEqual(config_manager.get_model_size_for_engine("whisper"), "small")
|
|
|
|
def test_set_model_size_for_engine_new_section(self):
|
|
"""Test setting model size when speech_recognition section doesn't exist."""
|
|
config_manager = ConfigManager()
|
|
|
|
# Remove the speech_recognition section
|
|
del config_manager.config["speech_recognition"]
|
|
|
|
# Set model size - should create the section
|
|
config_manager.set_model_size_for_engine("vosk", "large")
|
|
|
|
# Verify section was created and value was set
|
|
self.assertIn("speech_recognition", config_manager.config)
|
|
self.assertEqual(config_manager.config["speech_recognition"]["vosk_model_size"], "large")
|
|
|
|
def test_get_model_size_for_engine_fallback_to_generic(self):
|
|
"""Test fallback to generic model_size when no engine-specific key exists."""
|
|
# Create config with only generic model_size (no engine-specific)
|
|
test_config = {
|
|
"speech_recognition": {
|
|
"engine": "vosk",
|
|
"model_size": "large",
|
|
# No vosk_model_size or whisper_model_size
|
|
}
|
|
}
|
|
|
|
with open(self.temp_config_file, "w") as f:
|
|
json.dump(test_config, f)
|
|
|
|
config_manager = ConfigManager()
|
|
|
|
# Should fall back to generic model_size
|
|
# Note: migration might add engine-specific keys, so we test this directly
|
|
del config_manager.config["speech_recognition"]["vosk_model_size"]
|
|
del config_manager.config["speech_recognition"]["whisper_model_size"]
|
|
|
|
self.assertEqual(config_manager.get_model_size_for_engine("vosk"), "large")
|
|
self.assertEqual(config_manager.get_model_size_for_engine("whisper"), "large")
|
|
|
|
def test_update_speech_recognition_settings_new_section(self):
|
|
"""Test update_speech_recognition_settings when section doesn't exist."""
|
|
config_manager = ConfigManager()
|
|
|
|
# Remove the speech_recognition section
|
|
del config_manager.config["speech_recognition"]
|
|
|
|
# Update settings - should create the section
|
|
config_manager.update_speech_recognition_settings(
|
|
{"engine": "whisper", "vad_sensitivity": 5}
|
|
)
|
|
|
|
# Verify section was created
|
|
self.assertIn("speech_recognition", config_manager.config)
|
|
self.assertEqual(config_manager.config["speech_recognition"]["engine"], "whisper")
|
|
self.assertEqual(config_manager.config["speech_recognition"]["vad_sensitivity"], 5)
|
|
|
|
def test_migrate_super_shortcut_to_ctrl(self):
|
|
test_config = {
|
|
"shortcuts": {
|
|
"toggle_recognition": "super+super",
|
|
"mode": "toggle",
|
|
}
|
|
}
|
|
|
|
with open(self.temp_config_file, "w") as f:
|
|
json.dump(test_config, f)
|
|
|
|
config_manager = ConfigManager()
|
|
self.assertEqual(config_manager.config["shortcuts"]["toggle_recognition"], "ctrl+ctrl")
|
|
|
|
def test_non_super_shortcut_unchanged(self):
|
|
test_config = {
|
|
"shortcuts": {
|
|
"toggle_recognition": "alt+alt",
|
|
"mode": "push_to_talk",
|
|
}
|
|
}
|
|
|
|
with open(self.temp_config_file, "w") as f:
|
|
json.dump(test_config, f)
|
|
|
|
config_manager = ConfigManager()
|
|
self.assertEqual(config_manager.config["shortcuts"]["toggle_recognition"], "alt+alt")
|
|
self.assertEqual(config_manager.config["shortcuts"]["mode"], "push_to_talk")
|
|
|
|
def test_sound_effects_enabled_by_default(self):
|
|
"""Test that sound effects are enabled by default."""
|
|
config_manager = ConfigManager()
|
|
self.assertTrue(config_manager.is_sound_effects_enabled())
|
|
|
|
def test_set_sound_effects_enabled(self):
|
|
"""Test setting sound effects enabled state."""
|
|
config_manager = ConfigManager()
|
|
config_manager.set_sound_effects_enabled(False)
|
|
self.assertFalse(config_manager.is_sound_effects_enabled())
|
|
config_manager.set_sound_effects_enabled(True)
|
|
self.assertTrue(config_manager.is_sound_effects_enabled())
|
|
|
|
def test_sound_effects_config_persistence(self):
|
|
"""Test that sound effects setting persists across ConfigManager instances."""
|
|
config_manager = ConfigManager()
|
|
config_manager.set_sound_effects_enabled(False)
|
|
config_manager.save_config()
|
|
|
|
new_config_manager = ConfigManager()
|
|
self.assertFalse(new_config_manager.is_sound_effects_enabled())
|
|
|
|
|
|
class TestTypedAccessors(unittest.TestCase):
|
|
"""Tests for typed config accessors."""
|
|
|
|
def setUp(self):
|
|
self.config_manager = ConfigManager.__new__(ConfigManager)
|
|
self.config_manager.config = {
|
|
"general": {"autostart": True, "language": "en"},
|
|
"audio": {"sample_rate": 16000, "device_index": 2, "gain": 1.5},
|
|
"shortcuts": {"toggle_recognition": "ctrl+ctrl", "mode": "toggle"},
|
|
}
|
|
|
|
def test_get_str_returns_string(self):
|
|
result = self.config_manager.get_str("shortcuts", "mode", "hold")
|
|
assert result == "toggle"
|
|
assert isinstance(result, str)
|
|
|
|
def test_get_str_default(self):
|
|
result = self.config_manager.get_str("shortcuts", "nonexistent", "default")
|
|
assert result == "default"
|
|
|
|
def test_get_str_converts_non_string(self):
|
|
result = self.config_manager.get_str("audio", "sample_rate", "0")
|
|
assert result == "16000"
|
|
assert isinstance(result, str)
|
|
|
|
def test_get_str_none_returns_default(self):
|
|
self.config_manager.config["audio"]["device_index"] = None
|
|
result = self.config_manager.get_str("audio", "device_index", "fallback")
|
|
assert result == "fallback"
|
|
|
|
def test_get_bool_returns_bool(self):
|
|
result = self.config_manager.get_bool("general", "autostart", False)
|
|
assert result is True
|
|
|
|
def test_get_bool_default(self):
|
|
result = self.config_manager.get_bool("general", "nonexistent", True)
|
|
assert result is True
|
|
|
|
def test_get_int_returns_int(self):
|
|
result = self.config_manager.get_int("audio", "sample_rate", 0)
|
|
assert result == 16000
|
|
assert isinstance(result, int)
|
|
|
|
def test_get_int_default_on_invalid(self):
|
|
self.config_manager.config["audio"]["sample_rate"] = "not_a_number"
|
|
result = self.config_manager.get_int("audio", "sample_rate", 44100)
|
|
assert result == 44100
|
|
|
|
def test_get_int_default_on_none(self):
|
|
result = self.config_manager.get_int("audio", "nonexistent", 99)
|
|
assert result == 99
|
|
|
|
def test_get_float_returns_float(self):
|
|
result = self.config_manager.get_float("audio", "gain", 0.0)
|
|
assert result == 1.5
|
|
assert isinstance(result, float)
|
|
|
|
def test_get_float_default_on_invalid(self):
|
|
self.config_manager.config["audio"]["gain"] = "bad"
|
|
result = self.config_manager.get_float("audio", "gain", 2.0)
|
|
assert result == 2.0
|
|
|
|
def test_get_optional_int_returns_int(self):
|
|
result = self.config_manager.get_optional_int("audio", "device_index", None)
|
|
assert result == 2
|
|
assert isinstance(result, int)
|
|
|
|
def test_get_optional_int_returns_none(self):
|
|
self.config_manager.config["audio"]["device_index"] = None
|
|
result = self.config_manager.get_optional_int("audio", "device_index", None)
|
|
assert result is None
|
|
|
|
def test_get_optional_int_default_on_missing(self):
|
|
result = self.config_manager.get_optional_int("audio", "nonexistent", None)
|
|
assert result is None
|
|
|
|
def test_get_optional_int_default_on_invalid(self):
|
|
self.config_manager.config["audio"]["device_index"] = "not_int"
|
|
result = self.config_manager.get_optional_int("audio", "device_index", 5)
|
|
assert result == 5
|
|
|
|
def test_whispercpp_advanced_defaults(self):
|
|
"""Test that whisper.cpp advanced parameters have correct defaults."""
|
|
advanced = DEFAULT_CONFIG["advanced"]
|
|
self.assertFalse(advanced["power_user_mode"])
|
|
self.assertTrue(advanced["whispercpp_no_timestamps"])
|
|
self.assertTrue(advanced["whispercpp_no_context"])
|
|
self.assertEqual(advanced["whispercpp_initial_prompt"], "")
|
|
self.assertEqual(advanced["whispercpp_temperature"], 0.0)
|
|
self.assertEqual(advanced["whispercpp_temperature_inc"], -1.0)
|
|
self.assertEqual(advanced["whispercpp_entropy_thold"], 2.4)
|
|
self.assertEqual(advanced["whispercpp_logprob_thold"], -1.0)
|
|
self.assertEqual(advanced["whispercpp_no_speech_thold"], 0.6)
|
|
self.assertEqual(advanced["whispercpp_n_threads"], 0)
|
|
|
|
def test_whispercpp_advanced_persistence(self):
|
|
self.config_manager.set("advanced", "whispercpp_temperature", 0.5)
|
|
self.config_manager.set("advanced", "whispercpp_no_timestamps", False)
|
|
self.config_manager.set("advanced", "whispercpp_initial_prompt", "Meeting notes")
|
|
self.config_manager.save_config()
|
|
|
|
new_manager = ConfigManager()
|
|
advanced = new_manager.get_settings().get("advanced", {})
|
|
self.assertEqual(advanced["whispercpp_temperature"], 0.5)
|
|
self.assertFalse(advanced["whispercpp_no_timestamps"])
|
|
self.assertEqual(advanced["whispercpp_initial_prompt"], "Meeting notes")
|