from pathlib import Path import tempfile import unittest from unittest.mock import patch from parley.config import Config, DEFAULT_MODEL_PATH, DEFAULT_TRANSCRIPT_DIR from parley.errors import ConfigurationError class ConfigTests(unittest.TestCase): @patch("parley.config.shutil.which") def test_system_defaults(self, which) -> None: which.side_effect = lambda command: f"/usr/bin/{command}" config = Config.load(Path("/nonexistent/parley.toml")) self.assertEqual(config.ffmpeg, Path("/usr/bin/ffmpeg")) self.assertEqual(config.transcribe_cli, Path("/usr/bin/transcribe-cli")) self.assertEqual(config.model, DEFAULT_MODEL_PATH) self.assertEqual(config.transcript_dir, DEFAULT_TRANSCRIPT_DIR) self.assertTrue(config.auto_insert) self.assertEqual(config.insertion_mode, "ibus") self.assertFalse(config.notifications_enabled) def test_loads_toml_overrides(self) -> None: with tempfile.TemporaryDirectory() as temporary: path = Path(temporary) / "config.toml" path.write_text( """ [audio] ffmpeg = "/opt/ffmpeg" device = "studio" sample_rate = 48000 [transcription] command = "/opt/transcribe" model = "~/model.gguf" language = "fr" [storage] transcript_directory = "~/dictation" [insertion] enabled = false mode = "clipboard" [notifications] enabled = true """, encoding="utf-8", ) config = Config.load(path) self.assertEqual(config.ffmpeg, Path("/opt/ffmpeg")) self.assertEqual(config.transcribe_cli, Path("/opt/transcribe")) self.assertEqual(config.device, "studio") self.assertEqual(config.sample_rate, 48_000) self.assertEqual(config.language, "fr") self.assertFalse(config.auto_insert) self.assertEqual(config.insertion_mode, "clipboard") self.assertTrue(config.notifications_enabled) def test_rejects_malformed_toml(self) -> None: with tempfile.TemporaryDirectory() as temporary: path = Path(temporary) / "config.toml" path.write_text("[audio\n", encoding="utf-8") with self.assertRaisesRegex(ConfigurationError, "could not read"): Config.load(path) def test_rejects_invalid_types(self) -> None: with tempfile.TemporaryDirectory() as temporary: path = Path(temporary) / "config.toml" path.write_text("[insertion]\nenabled = 'yes'\n", encoding="utf-8") with self.assertRaisesRegex(ConfigurationError, "must be a boolean"): Config.load(path) if __name__ == "__main__": unittest.main()