Skip to content

Commit fecfacd

Browse files
committed
refactor(client): deprecate files.retrieve_content in favour of files.content
The latter supports binary response types more elegantly.
1 parent 8e4e5d4 commit fecfacd

File tree

3 files changed

+144
-15
lines changed

3 files changed

+144
-15
lines changed

api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ Methods:
8787
- <code title="get /files/{file_id}">client.files.<a href="./src/openai/resources/files.py">retrieve</a>(file_id) -> <a href="./src/openai/types/file_object.py">FileObject</a></code>
8888
- <code title="get /files">client.files.<a href="./src/openai/resources/files.py">list</a>(\*\*<a href="src/openai/types/file_list_params.py">params</a>) -> <a href="./src/openai/types/file_object.py">SyncPage[FileObject]</a></code>
8989
- <code title="delete /files/{file_id}">client.files.<a href="./src/openai/resources/files.py">delete</a>(file_id) -> <a href="./src/openai/types/file_deleted.py">FileDeleted</a></code>
90+
- <code title="get /files/{file_id}/content">client.files.<a href="./src/openai/resources/files.py">content</a>(file_id) -> HttpxBinaryResponseContent</code>
9091
- <code title="get /files/{file_id}/content">client.files.<a href="./src/openai/resources/files.py">retrieve_content</a>(file_id) -> str</code>
9192
- <code>client.files.<a href="./src/openai/resources/files.py">wait_for_processing</a>(\*args) -> FileObject</code>
9293

src/openai/resources/files.py

Lines changed: 80 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from __future__ import annotations
44

55
import time
6+
import typing_extensions
67
from typing import TYPE_CHECKING, Mapping, cast
78
from typing_extensions import Literal
89

@@ -14,7 +15,11 @@
1415
from .._resource import SyncAPIResource, AsyncAPIResource
1516
from .._response import to_raw_response_wrapper, async_to_raw_response_wrapper
1617
from ..pagination import SyncPage, AsyncPage
17-
from .._base_client import AsyncPaginator, make_request_options
18+
from .._base_client import (
19+
AsyncPaginator,
20+
HttpxBinaryResponseContent,
21+
make_request_options,
22+
)
1823

1924
if TYPE_CHECKING:
2025
from .._client import OpenAI, AsyncOpenAI
@@ -197,6 +202,38 @@ def delete(
197202
cast_to=FileDeleted,
198203
)
199204

205+
def content(
206+
self,
207+
file_id: str,
208+
*,
209+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
210+
# The extra values given here take precedence over values defined on the client or passed to this method.
211+
extra_headers: Headers | None = None,
212+
extra_query: Query | None = None,
213+
extra_body: Body | None = None,
214+
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
215+
) -> HttpxBinaryResponseContent:
216+
"""
217+
Returns the contents of the specified file.
218+
219+
Args:
220+
extra_headers: Send extra headers
221+
222+
extra_query: Add additional query parameters to the request
223+
224+
extra_body: Add additional JSON properties to the request
225+
226+
timeout: Override the client-level default timeout for this request, in seconds
227+
"""
228+
return self._get(
229+
f"/files/{file_id}/content",
230+
options=make_request_options(
231+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
232+
),
233+
cast_to=HttpxBinaryResponseContent,
234+
)
235+
236+
@typing_extensions.deprecated("The `.content()` method should be used instead")
200237
def retrieve_content(
201238
self,
202239
file_id: str,
@@ -428,6 +465,38 @@ async def delete(
428465
cast_to=FileDeleted,
429466
)
430467

468+
async def content(
469+
self,
470+
file_id: str,
471+
*,
472+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
473+
# The extra values given here take precedence over values defined on the client or passed to this method.
474+
extra_headers: Headers | None = None,
475+
extra_query: Query | None = None,
476+
extra_body: Body | None = None,
477+
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
478+
) -> HttpxBinaryResponseContent:
479+
"""
480+
Returns the contents of the specified file.
481+
482+
Args:
483+
extra_headers: Send extra headers
484+
485+
extra_query: Add additional query parameters to the request
486+
487+
extra_body: Add additional JSON properties to the request
488+
489+
timeout: Override the client-level default timeout for this request, in seconds
490+
"""
491+
return await self._get(
492+
f"/files/{file_id}/content",
493+
options=make_request_options(
494+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
495+
),
496+
cast_to=HttpxBinaryResponseContent,
497+
)
498+
499+
@typing_extensions.deprecated("The `.content()` method should be used instead")
431500
async def retrieve_content(
432501
self,
433502
file_id: str,
@@ -498,8 +567,11 @@ def __init__(self, files: Files) -> None:
498567
self.delete = to_raw_response_wrapper(
499568
files.delete,
500569
)
501-
self.retrieve_content = to_raw_response_wrapper(
502-
files.retrieve_content,
570+
self.content = to_raw_response_wrapper(
571+
files.content,
572+
)
573+
self.retrieve_content = to_raw_response_wrapper( # pyright: ignore[reportDeprecated]
574+
files.retrieve_content # pyright: ignore[reportDeprecated],
503575
)
504576

505577

@@ -517,6 +589,9 @@ def __init__(self, files: AsyncFiles) -> None:
517589
self.delete = async_to_raw_response_wrapper(
518590
files.delete,
519591
)
520-
self.retrieve_content = async_to_raw_response_wrapper(
521-
files.retrieve_content,
592+
self.content = async_to_raw_response_wrapper(
593+
files.content,
594+
)
595+
self.retrieve_content = async_to_raw_response_wrapper( # pyright: ignore[reportDeprecated]
596+
files.retrieve_content # pyright: ignore[reportDeprecated],
522597
)

tests/api_resources/test_files.py

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,19 @@
44

55
import os
66

7+
import httpx
78
import pytest
9+
from respx import MockRouter
810

911
from openai import OpenAI, AsyncOpenAI
1012
from tests.utils import assert_matches_type
1113
from openai.types import FileObject, FileDeleted
14+
from openai._types import BinaryResponseContent
1215
from openai._client import OpenAI, AsyncOpenAI
1316
from openai.pagination import SyncPage, AsyncPage
1417

18+
# pyright: reportDeprecated=false
19+
1520
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
1621
api_key = "My API Key"
1722

@@ -91,19 +96,43 @@ def test_raw_response_delete(self, client: OpenAI) -> None:
9196
assert_matches_type(FileDeleted, file, path=["response"])
9297

9398
@parametrize
94-
def test_method_retrieve_content(self, client: OpenAI) -> None:
95-
file = client.files.retrieve_content(
99+
@pytest.mark.respx(base_url=base_url)
100+
def test_method_content(self, client: OpenAI, respx_mock: MockRouter) -> None:
101+
respx_mock.get("/files/{file_id}/content").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
102+
file = client.files.content(
96103
"string",
97104
)
98-
assert_matches_type(str, file, path=["response"])
105+
assert isinstance(file, BinaryResponseContent)
106+
assert file.json() == {"foo": "bar"}
99107

100108
@parametrize
101-
def test_raw_response_retrieve_content(self, client: OpenAI) -> None:
102-
response = client.files.with_raw_response.retrieve_content(
109+
@pytest.mark.respx(base_url=base_url)
110+
def test_raw_response_content(self, client: OpenAI, respx_mock: MockRouter) -> None:
111+
respx_mock.get("/files/{file_id}/content").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
112+
response = client.files.with_raw_response.content(
103113
"string",
104114
)
105115
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
106116
file = response.parse()
117+
assert isinstance(file, BinaryResponseContent)
118+
assert file.json() == {"foo": "bar"}
119+
120+
@parametrize
121+
def test_method_retrieve_content(self, client: OpenAI) -> None:
122+
with pytest.warns(DeprecationWarning):
123+
file = client.files.retrieve_content(
124+
"string",
125+
)
126+
assert_matches_type(str, file, path=["response"])
127+
128+
@parametrize
129+
def test_raw_response_retrieve_content(self, client: OpenAI) -> None:
130+
with pytest.warns(DeprecationWarning):
131+
response = client.files.with_raw_response.retrieve_content(
132+
"string",
133+
)
134+
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
135+
file = response.parse()
107136
assert_matches_type(str, file, path=["response"])
108137

109138

@@ -182,17 +211,41 @@ async def test_raw_response_delete(self, client: AsyncOpenAI) -> None:
182211
assert_matches_type(FileDeleted, file, path=["response"])
183212

184213
@parametrize
185-
async def test_method_retrieve_content(self, client: AsyncOpenAI) -> None:
186-
file = await client.files.retrieve_content(
214+
@pytest.mark.respx(base_url=base_url)
215+
async def test_method_content(self, client: AsyncOpenAI, respx_mock: MockRouter) -> None:
216+
respx_mock.get("/files/{file_id}/content").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
217+
file = await client.files.content(
187218
"string",
188219
)
189-
assert_matches_type(str, file, path=["response"])
220+
assert isinstance(file, BinaryResponseContent)
221+
assert file.json() == {"foo": "bar"}
190222

191223
@parametrize
192-
async def test_raw_response_retrieve_content(self, client: AsyncOpenAI) -> None:
193-
response = await client.files.with_raw_response.retrieve_content(
224+
@pytest.mark.respx(base_url=base_url)
225+
async def test_raw_response_content(self, client: AsyncOpenAI, respx_mock: MockRouter) -> None:
226+
respx_mock.get("/files/{file_id}/content").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
227+
response = await client.files.with_raw_response.content(
194228
"string",
195229
)
196230
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
197231
file = response.parse()
232+
assert isinstance(file, BinaryResponseContent)
233+
assert file.json() == {"foo": "bar"}
234+
235+
@parametrize
236+
async def test_method_retrieve_content(self, client: AsyncOpenAI) -> None:
237+
with pytest.warns(DeprecationWarning):
238+
file = await client.files.retrieve_content(
239+
"string",
240+
)
241+
assert_matches_type(str, file, path=["response"])
242+
243+
@parametrize
244+
async def test_raw_response_retrieve_content(self, client: AsyncOpenAI) -> None:
245+
with pytest.warns(DeprecationWarning):
246+
response = await client.files.with_raw_response.retrieve_content(
247+
"string",
248+
)
249+
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
250+
file = response.parse()
198251
assert_matches_type(str, file, path=["response"])

0 commit comments

Comments
 (0)