From 13fe8cef177b8777c3d578e5a512f64e6d8e2354 Mon Sep 17 00:00:00 2001 From: adavyas Date: Wed, 8 Apr 2026 23:12:31 -0400 Subject: [PATCH] Clean up audio probe temp files --- src/utils/files.py | 11 +++++----- tests/utils/test_audio_processing.py | 31 ++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/utils/files.py b/src/utils/files.py index 61d1931f..1b3eae6c 100644 --- a/src/utils/files.py +++ b/src/utils/files.py @@ -191,14 +191,15 @@ class AudioProcessor: return f"{filename}{suffix}" def _probe_audio_duration_seconds(self, content: bytes, suffix: str) -> float: - with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as temp_file: - temp_file.write(content) - temp_path = Path(temp_file.name) - + temp_path: Path | None = None try: + with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as temp_file: + temp_path = Path(temp_file.name) + temp_file.write(content) return self.probe_audio_duration_seconds_from_path(temp_path) finally: - temp_path.unlink(missing_ok=True) + if temp_path is not None: + temp_path.unlink(missing_ok=True) def probe_audio_duration_seconds_from_path(self, path: Path) -> float: try: diff --git a/tests/utils/test_audio_processing.py b/tests/utils/test_audio_processing.py index 68786cdd..1c16e9bc 100644 --- a/tests/utils/test_audio_processing.py +++ b/tests/utils/test_audio_processing.py @@ -30,6 +30,37 @@ def test_audio_defaults_use_openai_whisper_without_backup(): assert settings.AUDIO.MODEL == "whisper-1" +def test_probe_audio_duration_cleans_up_temp_file_on_write_failure(): + processor = AudioProcessor() + + class FailingTempFile: + name: str = "/tmp/test-audio-probe.mp3" + + def __enter__(self) -> "FailingTempFile": + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc: BaseException | None, + tb: TracebackType | None, + ) -> bool: + return False + + def write(self, _content: bytes) -> int: + raise OSError("disk full") + + with ( + patch("src.utils.files.tempfile.NamedTemporaryFile", return_value=FailingTempFile()), + patch("src.utils.files.Path.unlink") as mock_unlink, + pytest.raises(OSError, match="disk full"), + ): + probe_audio_duration_seconds = getattr(processor, "_probe_audio_duration_seconds") + probe_audio_duration_seconds(b"audio-bytes", ".mp3") + + mock_unlink.assert_called_once_with(missing_ok=True) + + @pytest.mark.asyncio async def test_audio_upload_requires_openai_client_before_processing(): file = UploadFile(