From c128822d3037263b671ee3de6d6c6ce40932205f Mon Sep 17 00:00:00 2001 From: Raphael Fakhri <153192858+RaphaelFakhri@users.noreply.github.com> Date: Tue, 29 Sep 2026 11:39:40 +0000 Subject: [PATCH] fix(sync): accept file objects that have no path for a name SyncTranscriber.transcribe() read the audio part's filename from the file object's name attribute and passed it to os.path.basename(). Anonymous files such as tempfile.TemporaryFile() report a file descriptor (an int) as their name, so the call raised TypeError. Use the name only when it is a str, as the streaming path already does. --- assemblyai/_audio.py | 4 +++- tests/unit/test_sync.py | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/assemblyai/_audio.py b/assemblyai/_audio.py index e0bab838..3756ac94 100644 --- a/assemblyai/_audio.py +++ b/assemblyai/_audio.py @@ -90,7 +90,9 @@ def _resolve_audio( elif hasattr(data, "read"): audio = data.read() name = getattr(data, "name", None) - if name: + # `name` is a file descriptor (an int) for anonymous files such as + # `tempfile.TemporaryFile()`, so only a str is a usable path. + if isinstance(name, str) and name: filename = os.path.basename(name) suffix = os.path.splitext(name)[1].lower() else: diff --git a/tests/unit/test_sync.py b/tests/unit/test_sync.py index 054101cc..9aac6465 100644 --- a/tests/unit/test_sync.py +++ b/tests/unit/test_sync.py @@ -1,3 +1,5 @@ +import tempfile + import httpx import pytest from pytest_httpx import HTTPXMock @@ -316,6 +318,24 @@ def test_transcribe_path_input(httpx_mock: HTTPXMock, tmp_path): assert b'filename="call.wav"' in body +def test_transcribe_file_object_without_a_path_name(httpx_mock: HTTPXMock): + # Given an anonymous temporary file, whose `name` is a file descriptor + # rather than a path + _mock_ok(httpx_mock) + with tempfile.TemporaryFile() as audio_file: + audio_file.write(b"RIFFfake-wav-bytes") + audio_file.seek(0) + + # When transcribing the file object + result = aai.SyncTranscriber().transcribe(audio_file) + + # Then it succeeds and ships the audio under the default name + assert result.text == "hello world" + body = httpx_mock.get_requests()[0].read() + assert b'filename="audio.wav"' in body + assert b"RIFFfake-wav-bytes" in body + + def test_keyterms_prompt_too_long_raises(): # Given a keyterms_prompt exceeding the character cap # When building the config, Then validation fails immediately