diff --git a/src/openai/_files.py b/src/openai/_files.py index 1a2cc77478..22b9f02e95 100644 --- a/src/openai/_files.py +++ b/src/openai/_files.py @@ -63,6 +63,9 @@ def to_httpx_files(files: RequestFiles | None) -> HttpxRequestFiles | None: def _transform_file(file: FileTypes) -> HttpxFileTypes: + if is_tuple_t(file): + return (file[0], read_file_content(file[1]), *file[2:]) + if is_file_content(file): if isinstance(file, os.PathLike): path = pathlib.Path(file) @@ -70,9 +73,6 @@ def _transform_file(file: FileTypes) -> HttpxFileTypes: return file - if is_tuple_t(file): - return (file[0], read_file_content(file[1]), *file[2:]) - raise TypeError(f"Expected file types input to be a FileContent type or to be a tuple") @@ -105,6 +105,9 @@ async def async_to_httpx_files(files: RequestFiles | None) -> HttpxRequestFiles async def _async_transform_file(file: FileTypes) -> HttpxFileTypes: + if is_tuple_t(file): + return (file[0], await async_read_file_content(file[1]), *file[2:]) + if is_file_content(file): if isinstance(file, os.PathLike): path = anyio.Path(file) @@ -112,9 +115,6 @@ async def _async_transform_file(file: FileTypes) -> HttpxFileTypes: return file - if is_tuple_t(file): - return (file[0], await async_read_file_content(file[1]), *file[2:]) - raise TypeError(f"Expected file types input to be a FileContent type or to be a tuple") diff --git a/tests/test_files.py b/tests/test_files.py index 56445fb550..8ee736edf9 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -22,6 +22,30 @@ def test_tuple_input() -> None: assert result == IsList(IsTuple("file", IsTuple("README.md", IsBytes()))) +def test_tuple_pathlike_content() -> None: + result = to_httpx_files({"file": ("custom.txt", readme_path)}) + print(result) + assert result == IsDict({"file": IsTuple("custom.txt", IsBytes())}) + + +def test_sequence_tuple_pathlike_content() -> None: + result = to_httpx_files([("file", ("custom.txt", readme_path))]) + print(result) + assert result == IsList(IsTuple("file", IsTuple("custom.txt", IsBytes()))) + + +def test_tuple_pathlike_content_with_content_type() -> None: + result = to_httpx_files({"file": ("custom.txt", readme_path, "text/markdown")}) + print(result) + assert result == IsDict({"file": IsTuple("custom.txt", IsBytes(), "text/markdown")}) + + +def test_tuple_pathlike_content_with_headers() -> None: + result = to_httpx_files({"file": ("custom.txt", readme_path, "text/markdown", {"X-Test": "1"})}) + print(result) + assert result == IsDict({"file": IsTuple("custom.txt", IsBytes(), "text/markdown", {"X-Test": "1"})}) + + @pytest.mark.asyncio async def test_async_pathlib_includes_file_name() -> None: result = await async_to_httpx_files({"file": readme_path}) @@ -43,6 +67,36 @@ async def test_async_tuple_input() -> None: assert result == IsList(IsTuple("file", IsTuple("README.md", IsBytes()))) +@pytest.mark.asyncio +async def test_async_tuple_pathlike_content() -> None: + result = await async_to_httpx_files({"file": ("custom.txt", anyio.Path(readme_path))}) + print(result) + assert result == IsDict({"file": IsTuple("custom.txt", IsBytes())}) + + +@pytest.mark.asyncio +async def test_async_sequence_tuple_pathlike_content() -> None: + result = await async_to_httpx_files([("file", ("custom.txt", anyio.Path(readme_path)))]) + print(result) + assert result == IsList(IsTuple("file", IsTuple("custom.txt", IsBytes()))) + + +@pytest.mark.asyncio +async def test_async_tuple_pathlike_content_with_content_type() -> None: + result = await async_to_httpx_files({"file": ("custom.txt", anyio.Path(readme_path), "text/markdown")}) + print(result) + assert result == IsDict({"file": IsTuple("custom.txt", IsBytes(), "text/markdown")}) + + +@pytest.mark.asyncio +async def test_async_tuple_pathlike_content_with_headers() -> None: + result = await async_to_httpx_files( + {"file": ("custom.txt", anyio.Path(readme_path), "text/markdown", {"X-Test": "1"})} + ) + print(result) + assert result == IsDict({"file": IsTuple("custom.txt", IsBytes(), "text/markdown", {"X-Test": "1"})}) + + def test_string_not_allowed() -> None: with pytest.raises(TypeError, match="Expected file types input to be a FileContent type or to be a tuple"): to_httpx_files(