Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 33 additions & 10 deletions src/interfaze/_inputs.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,14 +10,35 @@
BytesLike = Union[bytes, bytearray]

_EXT_MIME = {
"png": "image/png", "jpg": "image/jpeg", "jpeg": "image/jpeg", "webp": "image/webp",
"gif": "image/gif", "bmp": "image/bmp", "heic": "image/heic", "heif": "image/heif",
"pdf": "application/pdf", "csv": "text/csv", "tsv": "text/tab-separated-values",
"xml": "application/xml", "json": "application/json", "txt": "text/plain",
"md": "text/markdown", "markdown": "text/markdown", "yaml": "application/yaml", "yml": "application/yaml",
"wav": "audio/wav", "mp3": "audio/mpeg", "m4a": "audio/mp4", "ogg": "audio/ogg", "flac": "audio/flac",
"mp4": "video/mp4", "mov": "video/quicktime", "webm": "video/webm", "avi": "video/x-msvideo",
"mkv": "video/x-matroska", "3gp": "video/3gpp",
"png": "image/png",
"jpg": "image/jpeg",
"jpeg": "image/jpeg",
"webp": "image/webp",
"gif": "image/gif",
"bmp": "image/bmp",
"heic": "image/heic",
"heif": "image/heif",
"pdf": "application/pdf",
"csv": "text/csv",
"tsv": "text/tab-separated-values",
"xml": "application/xml",
"json": "application/json",
"txt": "text/plain",
"md": "text/markdown",
"markdown": "text/markdown",
"yaml": "application/yaml",
"yml": "application/yaml",
"wav": "audio/wav",
"mp3": "audio/mpeg",
"m4a": "audio/mp4",
"ogg": "audio/ogg",
"flac": "audio/flac",
"mp4": "video/mp4",
"mov": "video/quicktime",
"webm": "video/webm",
"avi": "video/x-msvideo",
"mkv": "video/x-matroska",
"3gp": "video/3gpp",
}


Expand DownExpand Up@@ -70,7 +91,9 @@ def file(src: str, *, filename: Optional[str] = None, format: Optional[str] = No

def audio(src: str, *, format: Optional[str] = None) -> Dict[str, Any]:
"""Audio content part via ``input_audio`` (``audio_url`` is a dead field in Interfaze)."""
fmt = format or _ext_of(src) or "wav"
mime = _mime_from_data_url(src)
_assert_allowed(mime or _EXT_MIME.get(_ext_of(src) or ""))
fmt = format or (mime.split("/", 1)[-1] if mime else _ext_of(src)) or "wav"
return {"type": "input_audio", "input_audio": {"data": src, "format": fmt}}


Expand All@@ -85,5 +108,5 @@ def auto_part(src: str, *, filename: Optional[str] = None, format: Optional[str]
if mime and mime.startswith("image/"):
return image(src)
if mime and mime.startswith("audio/"):
return audio(src, format=format) if format else audio(src)
return audio(src, format=format or mime.split("/", 1)[-1])
return file(src, filename=filename, format=format)
15 changes: 15 additions & 0 deletions tests/test_inputs_and_client.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,16 @@ def test_audio_uses_input_audio():
assert part["type"] == "input_audio" and part["input_audio"]["format"] == "wav"


def test_audio_data_uri_uses_mime_subtype():
assert inputs.audio("data:audio/mpeg;base64,AAAA")["input_audio"]["format"] == "mpeg"
assert inputs.audio("data:audio/wav;base64,AAAA")["input_audio"]["format"] == "wav"


def test_audio_rejects_blacklisted_data_uri():
with pytest.raises(InterfazeError):
inputs.audio("data:image/gif;base64,AAAA")


def test_gif_rejected():
with pytest.raises(InterfazeError):
inputs.image("https://x.com/a.gif")
Expand All@@ -53,6 +63,11 @@ def test_auto_part_routing():
assert inputs.auto_part("https://x.com/a.mp4")["type"] == "file"


def test_auto_part_forwards_audio_data_uri_format():
part = inputs.auto_part("data:audio/mpeg;base64,AAAA")
assert part["type"] == "input_audio" and part["input_audio"]["format"] == "mpeg"


# ---- client surface ----
def test_curated_surface():
c = Interfaze(api_key="t")
Expand Down