Skip to content

Commit

Permalink
refactor(client): deprecate files.retrieve_content in favour of files…
Browse files Browse the repository at this point in the history
….content (#753)

The latter supports binary response types more elegantly.
  • Loading branch information
stainless-bot authored Nov 9, 2023
1 parent 8e4e5d4 commit eea5bc1
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 15 deletions.
1 change: 1 addition & 0 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ Methods:
- <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>
- <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>
- <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>
- <code title="get /files/{file_id}/content">client.files.<a href="./src/openai/resources/files.py">content</a>(file_id) -> HttpxBinaryResponseContent</code>
- <code title="get /files/{file_id}/content">client.files.<a href="./src/openai/resources/files.py">retrieve_content</a>(file_id) -> str</code>
- <code>client.files.<a href="./src/openai/resources/files.py">wait_for_processing</a>(\*args) -> FileObject</code>

Expand Down
85 changes: 80 additions & 5 deletions src/openai/resources/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import annotations

import time
import typing_extensions
from typing import TYPE_CHECKING, Mapping, cast
from typing_extensions import Literal

Expand All @@ -14,7 +15,11 @@
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import to_raw_response_wrapper, async_to_raw_response_wrapper
from ..pagination import SyncPage, AsyncPage
from .._base_client import AsyncPaginator, make_request_options
from .._base_client import (
AsyncPaginator,
HttpxBinaryResponseContent,
make_request_options,
)

if TYPE_CHECKING:
from .._client import OpenAI, AsyncOpenAI
Expand Down Expand Up @@ -197,6 +202,38 @@ def delete(
cast_to=FileDeleted,
)

def content(
self,
file_id: str,
*,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
) -> HttpxBinaryResponseContent:
"""
Returns the contents of the specified file.
Args:
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
extra_body: Add additional JSON properties to the request
timeout: Override the client-level default timeout for this request, in seconds
"""
return self._get(
f"/files/{file_id}/content",
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
cast_to=HttpxBinaryResponseContent,
)

@typing_extensions.deprecated("The `.content()` method should be used instead")
def retrieve_content(
self,
file_id: str,
Expand Down Expand Up @@ -428,6 +465,38 @@ async def delete(
cast_to=FileDeleted,
)

async def content(
self,
file_id: str,
*,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
) -> HttpxBinaryResponseContent:
"""
Returns the contents of the specified file.
Args:
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
extra_body: Add additional JSON properties to the request
timeout: Override the client-level default timeout for this request, in seconds
"""
return await self._get(
f"/files/{file_id}/content",
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
cast_to=HttpxBinaryResponseContent,
)

@typing_extensions.deprecated("The `.content()` method should be used instead")
async def retrieve_content(
self,
file_id: str,
Expand Down Expand Up @@ -498,8 +567,11 @@ def __init__(self, files: Files) -> None:
self.delete = to_raw_response_wrapper(
files.delete,
)
self.retrieve_content = to_raw_response_wrapper(
files.retrieve_content,
self.content = to_raw_response_wrapper(
files.content,
)
self.retrieve_content = to_raw_response_wrapper( # pyright: ignore[reportDeprecated]
files.retrieve_content # pyright: ignore[reportDeprecated],
)


Expand All @@ -517,6 +589,9 @@ def __init__(self, files: AsyncFiles) -> None:
self.delete = async_to_raw_response_wrapper(
files.delete,
)
self.retrieve_content = async_to_raw_response_wrapper(
files.retrieve_content,
self.content = async_to_raw_response_wrapper(
files.content,
)
self.retrieve_content = async_to_raw_response_wrapper( # pyright: ignore[reportDeprecated]
files.retrieve_content # pyright: ignore[reportDeprecated],
)
73 changes: 63 additions & 10 deletions tests/api_resources/test_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@

import os

import httpx
import pytest
from respx import MockRouter

from openai import OpenAI, AsyncOpenAI
from tests.utils import assert_matches_type
from openai.types import FileObject, FileDeleted
from openai._types import BinaryResponseContent
from openai._client import OpenAI, AsyncOpenAI
from openai.pagination import SyncPage, AsyncPage

# pyright: reportDeprecated=false

base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
api_key = "My API Key"

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

@parametrize
def test_method_retrieve_content(self, client: OpenAI) -> None:
file = client.files.retrieve_content(
@pytest.mark.respx(base_url=base_url)
def test_method_content(self, client: OpenAI, respx_mock: MockRouter) -> None:
respx_mock.get("/files/{file_id}/content").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
file = client.files.content(
"string",
)
assert_matches_type(str, file, path=["response"])
assert isinstance(file, BinaryResponseContent)
assert file.json() == {"foo": "bar"}

@parametrize
def test_raw_response_retrieve_content(self, client: OpenAI) -> None:
response = client.files.with_raw_response.retrieve_content(
@pytest.mark.respx(base_url=base_url)
def test_raw_response_content(self, client: OpenAI, respx_mock: MockRouter) -> None:
respx_mock.get("/files/{file_id}/content").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
response = client.files.with_raw_response.content(
"string",
)
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
file = response.parse()
assert isinstance(file, BinaryResponseContent)
assert file.json() == {"foo": "bar"}

@parametrize
def test_method_retrieve_content(self, client: OpenAI) -> None:
with pytest.warns(DeprecationWarning):
file = client.files.retrieve_content(
"string",
)
assert_matches_type(str, file, path=["response"])

@parametrize
def test_raw_response_retrieve_content(self, client: OpenAI) -> None:
with pytest.warns(DeprecationWarning):
response = client.files.with_raw_response.retrieve_content(
"string",
)
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
file = response.parse()
assert_matches_type(str, file, path=["response"])


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

@parametrize
async def test_method_retrieve_content(self, client: AsyncOpenAI) -> None:
file = await client.files.retrieve_content(
@pytest.mark.respx(base_url=base_url)
async def test_method_content(self, client: AsyncOpenAI, respx_mock: MockRouter) -> None:
respx_mock.get("/files/{file_id}/content").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
file = await client.files.content(
"string",
)
assert_matches_type(str, file, path=["response"])
assert isinstance(file, BinaryResponseContent)
assert file.json() == {"foo": "bar"}

@parametrize
async def test_raw_response_retrieve_content(self, client: AsyncOpenAI) -> None:
response = await client.files.with_raw_response.retrieve_content(
@pytest.mark.respx(base_url=base_url)
async def test_raw_response_content(self, client: AsyncOpenAI, respx_mock: MockRouter) -> None:
respx_mock.get("/files/{file_id}/content").mock(return_value=httpx.Response(200, json={"foo": "bar"}))
response = await client.files.with_raw_response.content(
"string",
)
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
file = response.parse()
assert isinstance(file, BinaryResponseContent)
assert file.json() == {"foo": "bar"}

@parametrize
async def test_method_retrieve_content(self, client: AsyncOpenAI) -> None:
with pytest.warns(DeprecationWarning):
file = await client.files.retrieve_content(
"string",
)
assert_matches_type(str, file, path=["response"])

@parametrize
async def test_raw_response_retrieve_content(self, client: AsyncOpenAI) -> None:
with pytest.warns(DeprecationWarning):
response = await client.files.with_raw_response.retrieve_content(
"string",
)
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
file = response.parse()
assert_matches_type(str, file, path=["response"])

0 comments on commit eea5bc1

Please sign in to comment.