diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b44b287037..4dedeaebc3 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.4.0" + ".": "2.5.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index d0ff2b0dc2..b15622eba0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 136 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-104cced8f4c7436a76eea02e26307828166405ccfb296faffb008b72772c11a7.yml -openapi_spec_hash: fdc03ed84a65a31b80da909255e53924 -config_hash: 03b48e9b8c7231a902403210dbd7dfa0 +configured_endpoints: 135 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-f59befea071ed7729cbb7bce219e7f837eccfdb57e01698514e6a0bd6052ff60.yml +openapi_spec_hash: 49da48619d37932b2e257c532078b2bb +config_hash: 1af83449a09a3b4f276444dbcdd3eb67 diff --git a/CHANGELOG.md b/CHANGELOG.md index 30f898c23b..3f79fb75fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 2.5.0 (2025-10-17) + +Full Changelog: [v2.4.0...v2.5.0](https://github.com/openai/openai-python/compare/v2.4.0...v2.5.0) + +### Features + +* **api:** api update ([8b280d5](https://github.com/openai/openai-python/commit/8b280d57d6d361bc3a032e030158f6859c445291)) + + +### Chores + +* bump `httpx-aiohttp` version to 0.1.9 ([67f2f0a](https://github.com/openai/openai-python/commit/67f2f0afe51dab9d5899fe18b1a4e86b2c774d10)) + ## 2.4.0 (2025-10-16) Full Changelog: [v2.3.0...v2.4.0](https://github.com/openai/openai-python/compare/v2.3.0...v2.4.0) diff --git a/pyproject.toml b/pyproject.toml index 43de9882f2..a2f0ab7176 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openai" -version = "2.4.0" +version = "2.5.0" description = "The official Python library for the openai API" dynamic = ["readme"] license = "Apache-2.0" @@ -44,7 +44,7 @@ Repository = "https://github.com/openai/openai-python" openai = "openai.cli:main" [project.optional-dependencies] -aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.8"] +aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.9"] realtime = ["websockets >= 13, < 16"] datalib = ["numpy >= 1", "pandas >= 1.2.3", "pandas-stubs >= 1.1.0.11"] voice_helpers = ["sounddevice>=0.5.1", "numpy>=2.0.2"] diff --git a/requirements-dev.lock b/requirements-dev.lock index e2446f2222..b454537b96 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -79,7 +79,7 @@ httpx==0.28.1 # via httpx-aiohttp # via openai # via respx -httpx-aiohttp==0.1.8 +httpx-aiohttp==0.1.9 # via openai idna==3.4 # via anyio diff --git a/requirements.lock b/requirements.lock index aaca0834db..b047cb3f88 100644 --- a/requirements.lock +++ b/requirements.lock @@ -45,7 +45,7 @@ httpcore==1.0.9 httpx==0.28.1 # via httpx-aiohttp # via openai -httpx-aiohttp==0.1.8 +httpx-aiohttp==0.1.9 # via openai idna==3.4 # via anyio diff --git a/src/openai/_version.py b/src/openai/_version.py index e09654e09d..0d92388b98 100644 --- a/src/openai/_version.py +++ b/src/openai/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "openai" -__version__ = "2.4.0" # x-release-please-version +__version__ = "2.5.0" # x-release-please-version diff --git a/src/openai/resources/beta/chatkit/chatkit.py b/src/openai/resources/beta/chatkit/chatkit.py index 2d090cf396..5a10a39c7b 100644 --- a/src/openai/resources/beta/chatkit/chatkit.py +++ b/src/openai/resources/beta/chatkit/chatkit.py @@ -2,11 +2,6 @@ from __future__ import annotations -from typing import Any, Mapping, cast - -import httpx - -from .... import _legacy_response from .threads import ( Threads, AsyncThreads, @@ -23,14 +18,8 @@ SessionsWithStreamingResponse, AsyncSessionsWithStreamingResponse, ) -from ...._types import Body, Query, Headers, NotGiven, FileTypes, not_given -from ...._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform from ...._compat import cached_property from ...._resource import SyncAPIResource, AsyncAPIResource -from ...._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper -from ....types.beta import chatkit_upload_file_params -from ...._base_client import make_request_options -from ....types.beta.chatkit_upload_file_response import ChatKitUploadFileResponse __all__ = ["ChatKit", "AsyncChatKit"] @@ -63,55 +52,6 @@ def with_streaming_response(self) -> ChatKitWithStreamingResponse: """ return ChatKitWithStreamingResponse(self) - def upload_file( - self, - *, - file: FileTypes, - # 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, - ) -> ChatKitUploadFileResponse: - """ - Upload a ChatKit file - - Args: - file: Binary file contents to store with the ChatKit session. Supports PDFs and PNG, - JPG, JPEG, GIF, or WEBP images. - - 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 - """ - extra_headers = {"OpenAI-Beta": "chatkit_beta=v1", **(extra_headers or {})} - body = deepcopy_minimal({"file": file}) - files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) - if files: - # It should be noted that the actual Content-Type header that will be - # sent to the server will contain a `boundary` parameter, e.g. - # multipart/form-data; boundary=---abc-- - extra_headers["Content-Type"] = "multipart/form-data" - return cast( - ChatKitUploadFileResponse, - self._post( - "/chatkit/files", - body=maybe_transform(body, chatkit_upload_file_params.ChatKitUploadFileParams), - files=files, - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=cast( - Any, ChatKitUploadFileResponse - ), # Union types cannot be passed in as arguments in the type system - ), - ) - class AsyncChatKit(AsyncAPIResource): @cached_property @@ -141,64 +81,11 @@ def with_streaming_response(self) -> AsyncChatKitWithStreamingResponse: """ return AsyncChatKitWithStreamingResponse(self) - async def upload_file( - self, - *, - file: FileTypes, - # 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, - ) -> ChatKitUploadFileResponse: - """ - Upload a ChatKit file - - Args: - file: Binary file contents to store with the ChatKit session. Supports PDFs and PNG, - JPG, JPEG, GIF, or WEBP images. - - 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 - """ - extra_headers = {"OpenAI-Beta": "chatkit_beta=v1", **(extra_headers or {})} - body = deepcopy_minimal({"file": file}) - files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) - if files: - # It should be noted that the actual Content-Type header that will be - # sent to the server will contain a `boundary` parameter, e.g. - # multipart/form-data; boundary=---abc-- - extra_headers["Content-Type"] = "multipart/form-data" - return cast( - ChatKitUploadFileResponse, - await self._post( - "/chatkit/files", - body=await async_maybe_transform(body, chatkit_upload_file_params.ChatKitUploadFileParams), - files=files, - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=cast( - Any, ChatKitUploadFileResponse - ), # Union types cannot be passed in as arguments in the type system - ), - ) - class ChatKitWithRawResponse: def __init__(self, chatkit: ChatKit) -> None: self._chatkit = chatkit - self.upload_file = _legacy_response.to_raw_response_wrapper( - chatkit.upload_file, - ) - @cached_property def sessions(self) -> SessionsWithRawResponse: return SessionsWithRawResponse(self._chatkit.sessions) @@ -212,10 +99,6 @@ class AsyncChatKitWithRawResponse: def __init__(self, chatkit: AsyncChatKit) -> None: self._chatkit = chatkit - self.upload_file = _legacy_response.async_to_raw_response_wrapper( - chatkit.upload_file, - ) - @cached_property def sessions(self) -> AsyncSessionsWithRawResponse: return AsyncSessionsWithRawResponse(self._chatkit.sessions) @@ -229,10 +112,6 @@ class ChatKitWithStreamingResponse: def __init__(self, chatkit: ChatKit) -> None: self._chatkit = chatkit - self.upload_file = to_streamed_response_wrapper( - chatkit.upload_file, - ) - @cached_property def sessions(self) -> SessionsWithStreamingResponse: return SessionsWithStreamingResponse(self._chatkit.sessions) @@ -246,10 +125,6 @@ class AsyncChatKitWithStreamingResponse: def __init__(self, chatkit: AsyncChatKit) -> None: self._chatkit = chatkit - self.upload_file = async_to_streamed_response_wrapper( - chatkit.upload_file, - ) - @cached_property def sessions(self) -> AsyncSessionsWithStreamingResponse: return AsyncSessionsWithStreamingResponse(self._chatkit.sessions) diff --git a/src/openai/types/beta/__init__.py b/src/openai/types/beta/__init__.py index 9ef6283864..deb2369677 100644 --- a/src/openai/types/beta/__init__.py +++ b/src/openai/types/beta/__init__.py @@ -4,8 +4,6 @@ from .thread import Thread as Thread from .assistant import Assistant as Assistant -from .file_part import FilePart as FilePart -from .image_part import ImagePart as ImagePart from .function_tool import FunctionTool as FunctionTool from .assistant_tool import AssistantTool as AssistantTool from .thread_deleted import ThreadDeleted as ThreadDeleted @@ -23,11 +21,9 @@ from .file_search_tool_param import FileSearchToolParam as FileSearchToolParam from .assistant_create_params import AssistantCreateParams as AssistantCreateParams from .assistant_update_params import AssistantUpdateParams as AssistantUpdateParams -from .chatkit_upload_file_params import ChatKitUploadFileParams as ChatKitUploadFileParams from .assistant_tool_choice_param import AssistantToolChoiceParam as AssistantToolChoiceParam from .code_interpreter_tool_param import CodeInterpreterToolParam as CodeInterpreterToolParam from .assistant_tool_choice_option import AssistantToolChoiceOption as AssistantToolChoiceOption -from .chatkit_upload_file_response import ChatKitUploadFileResponse as ChatKitUploadFileResponse from .thread_create_and_run_params import ThreadCreateAndRunParams as ThreadCreateAndRunParams from .assistant_tool_choice_function import AssistantToolChoiceFunction as AssistantToolChoiceFunction from .assistant_response_format_option import AssistantResponseFormatOption as AssistantResponseFormatOption diff --git a/src/openai/types/beta/chatkit_upload_file_params.py b/src/openai/types/beta/chatkit_upload_file_params.py deleted file mode 100644 index 87dc993664..0000000000 --- a/src/openai/types/beta/chatkit_upload_file_params.py +++ /dev/null @@ -1,17 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Required, TypedDict - -from ..._types import FileTypes - -__all__ = ["ChatKitUploadFileParams"] - - -class ChatKitUploadFileParams(TypedDict, total=False): - file: Required[FileTypes] - """Binary file contents to store with the ChatKit session. - - Supports PDFs and PNG, JPG, JPEG, GIF, or WEBP images. - """ diff --git a/src/openai/types/beta/chatkit_upload_file_response.py b/src/openai/types/beta/chatkit_upload_file_response.py deleted file mode 100644 index 9527df76fb..0000000000 --- a/src/openai/types/beta/chatkit_upload_file_response.py +++ /dev/null @@ -1,12 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Union -from typing_extensions import Annotated, TypeAlias - -from ..._utils import PropertyInfo -from .file_part import FilePart -from .image_part import ImagePart - -__all__ = ["ChatKitUploadFileResponse"] - -ChatKitUploadFileResponse: TypeAlias = Annotated[Union[FilePart, ImagePart], PropertyInfo(discriminator="type")] diff --git a/src/openai/types/beta/file_part.py b/src/openai/types/beta/file_part.py deleted file mode 100644 index cf60bddc99..0000000000 --- a/src/openai/types/beta/file_part.py +++ /dev/null @@ -1,28 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = ["FilePart"] - - -class FilePart(BaseModel): - id: str - """Unique identifier for the uploaded file.""" - - mime_type: Optional[str] = None - """MIME type reported for the uploaded file. Defaults to null when unknown.""" - - name: Optional[str] = None - """Original filename supplied by the uploader. Defaults to null when unnamed.""" - - type: Literal["file"] - """Type discriminator that is always `file`.""" - - upload_url: Optional[str] = None - """Signed URL for downloading the uploaded file. - - Defaults to null when no download link is available. - """ diff --git a/src/openai/types/beta/image_part.py b/src/openai/types/beta/image_part.py deleted file mode 100644 index 4c06b4730b..0000000000 --- a/src/openai/types/beta/image_part.py +++ /dev/null @@ -1,31 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = ["ImagePart"] - - -class ImagePart(BaseModel): - id: str - """Unique identifier for the uploaded image.""" - - mime_type: str - """MIME type of the uploaded image.""" - - name: Optional[str] = None - """Original filename for the uploaded image. Defaults to null when unnamed.""" - - preview_url: str - """Preview URL that can be rendered inline for the image.""" - - type: Literal["image"] - """Type discriminator that is always `image`.""" - - upload_url: Optional[str] = None - """Signed URL for downloading the uploaded image. - - Defaults to null when no download link is available. - """ diff --git a/tests/api_resources/beta/test_chatkit.py b/tests/api_resources/beta/test_chatkit.py deleted file mode 100644 index b05be0ece5..0000000000 --- a/tests/api_resources/beta/test_chatkit.py +++ /dev/null @@ -1,86 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from openai import OpenAI, AsyncOpenAI -from tests.utils import assert_matches_type -from openai.types.beta import ChatKitUploadFileResponse - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestChatKit: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_upload_file(self, client: OpenAI) -> None: - chatkit = client.beta.chatkit.upload_file( - file=b"raw file contents", - ) - assert_matches_type(ChatKitUploadFileResponse, chatkit, path=["response"]) - - @parametrize - def test_raw_response_upload_file(self, client: OpenAI) -> None: - response = client.beta.chatkit.with_raw_response.upload_file( - file=b"raw file contents", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - chatkit = response.parse() - assert_matches_type(ChatKitUploadFileResponse, chatkit, path=["response"]) - - @parametrize - def test_streaming_response_upload_file(self, client: OpenAI) -> None: - with client.beta.chatkit.with_streaming_response.upload_file( - file=b"raw file contents", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - chatkit = response.parse() - assert_matches_type(ChatKitUploadFileResponse, chatkit, path=["response"]) - - assert cast(Any, response.is_closed) is True - - -class TestAsyncChatKit: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @parametrize - async def test_method_upload_file(self, async_client: AsyncOpenAI) -> None: - chatkit = await async_client.beta.chatkit.upload_file( - file=b"raw file contents", - ) - assert_matches_type(ChatKitUploadFileResponse, chatkit, path=["response"]) - - @parametrize - async def test_raw_response_upload_file(self, async_client: AsyncOpenAI) -> None: - response = await async_client.beta.chatkit.with_raw_response.upload_file( - file=b"raw file contents", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - chatkit = response.parse() - assert_matches_type(ChatKitUploadFileResponse, chatkit, path=["response"]) - - @parametrize - async def test_streaming_response_upload_file(self, async_client: AsyncOpenAI) -> None: - async with async_client.beta.chatkit.with_streaming_response.upload_file( - file=b"raw file contents", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - chatkit = await response.parse() - assert_matches_type(ChatKitUploadFileResponse, chatkit, path=["response"]) - - assert cast(Any, response.is_closed) is True