This commit is contained in:
Raunak Kumar Pandey 2026-11-05 03:25:10 +00:00 • committed by GitHub
commit b4d52dc1ea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 21 additions and 10 deletions

View file

@ -311,7 +311,9 @@ def calculate_request_duration(file: FileTypes) -> float | None:
content: Final = file[1]
if isinstance(content, bytes):
file_content = content
elif hasattr(content, "read") and not isinstance(content, (str, os.PathLike)):
elif isinstance(content, os.PathLike):
return calculate_request_duration(content)
elif hasattr(content, "read") and not isinstance(content, str):
# File-like object in tuple
current_pos: Final = getattr(content, "tell", lambda: None)()
# Seek to start to ensure we read the entire content

View file

@ -6,6 +6,7 @@ import base64
import io
import os
import tempfile
from pathlib import Path
from typing import Final
from unittest.mock import mock_open, patch
@ -329,16 +330,12 @@ class TestCalculateRequestDuration:
duration = calculate_request_duration(file_obj)
# Verify it succeeded (returns a duration, not None)
assert (
duration is not None
), "Duration should be calculated even when BytesIO is at end"
assert duration is not None, "Duration should be calculated even when BytesIO is at end"
assert isinstance(duration, float), "Duration should be a float"
assert duration > 0, "Duration should be positive"
# Verify the file position was restored
assert file_obj.tell() == len(
wav_header
), "File position should be restored to original position"
assert file_obj.tell() == len(wav_header), "File position should be restored to original position"
class TestGetAudioFileContentHash:
@ -364,9 +361,7 @@ class TestGetAudioFileContentHash:
hash1 = get_audio_file_content_hash((filename1, content))
hash2 = get_audio_file_content_hash((filename2, content))
assert (
hash1 == hash2
), "Same content should produce same hash regardless of filename"
assert hash1 == hash2, "Same content should produce same hash regardless of filename"
def test_bytes_input(self):
"""Test that raw bytes input works"""
@ -473,3 +468,17 @@ class TestSpeechMediaTypeFromAudioBytes:
from litellm.litellm_core_utils.audio_utils.utils import speech_media_type_from_audio_bytes
assert speech_media_type_from_audio_bytes(audio) == expected
@pytest.mark.parametrize("include_content_type", [False, True])
def test_duration_reads_pathlike_content_in_multipart_tuple(tmp_path: Path, include_content_type: bool) -> None:
audio_path: Final = tmp_path / "sample.wav"
audio_path.write_bytes(base64.b64decode(_encoded_audio(2, 8000, 1, "WAV")))
upload: Final = ("sample.wav", audio_path, "audio/wav") if include_content_type else ("sample.wav", audio_path)
assert calculate_request_duration(upload) == 2.0
def test_duration_does_not_open_bare_string_tuple_content(tmp_path: Path) -> None:
audio_path: Final = tmp_path / "sample.wav"
audio_path.write_bytes(base64.b64decode(_encoded_audio(2, 8000, 1, "WAV")))
assert calculate_request_duration(("sample.wav", str(audio_path))) is None