From a575a380b2f68b77291bc6bb28984cba3628a7c9 Mon Sep 17 00:00:00 2001 From: markstuart-oai Date: Mon, 19 Oct 2026 22:07:08 +0000 Subject: [PATCH 1/2] feat(types): prepare native synchronous WebSocket option type --- .../types/websocket_connection_options.py | 17 +++++++---- tests/test_websocket_connection_options.py | 28 +++++++++++++++++++ 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/openai/types/websocket_connection_options.py b/src/openai/types/websocket_connection_options.py index 0ddbf5af49..d8bfabad18 100644 --- a/src/openai/types/websocket_connection_options.py +++ b/src/openai/types/websocket_connection_options.py @@ -5,17 +5,17 @@ from typing import TYPE_CHECKING from typing_extensions import Sequence, TypeAlias, TypedDict -__all__ = ["WebSocketConnectionOptions", "WebsocketConnectionOptions"] +__all__ = ["SyncWebSocketConnectionOptions", "WebSocketConnectionOptions", "WebsocketConnectionOptions"] if TYPE_CHECKING: from websockets import Subprotocol from websockets.extensions import ClientExtensionFactory -class WebSocketConnectionOptions(TypedDict, total=False): - """WebSocket connection options copied from `websockets`. +class SyncWebSocketConnectionOptions(TypedDict, total=False): + """Native options for synchronous WebSocket connections. - For example: https://websockets.readthedocs.io/en/stable/reference/asyncio/client.html#websockets.asyncio.client.connect + See https://websockets.readthedocs.io/en/stable/reference/sync/client.html#websockets.sync.client.connect """ extensions: Sequence[ClientExtensionFactory] | None @@ -32,7 +32,14 @@ class WebSocketConnectionOptions(TypedDict, total=False): """Maximum size of incoming messages in bytes. None disables the limit.""" max_queue: int | None | tuple[int | None, int | None] - """High-water mark of the buffer where frames are received. It defaults to 16 frames. The low-water mark defaults to max_queue // 4. You may pass a (high, low) tuple to set the high-water and low-water marks. If you want to disable flow control entirely, you may set it to None, although that’s a bad idea.""" + """For synchronous connections, this requires websockets >=14. High-water mark of the buffer where frames are received. It defaults to 16 frames. The low-water mark defaults to max_queue // 4. You may pass a (high, low) tuple to set the high-water and low-water marks. If you want to disable flow control entirely, you may set it to None, although that’s a bad idea.""" + + +class WebSocketConnectionOptions(SyncWebSocketConnectionOptions, total=False): + """Native options for asynchronous WebSocket connections. + + See https://websockets.readthedocs.io/en/stable/reference/asyncio/client.html#websockets.asyncio.client.connect + """ write_limit: int | tuple[int, int | None] """High-water mark of write buffer in bytes. It is passed to set_write_buffer_limits(). It defaults to 32 KiB. You may pass a (high, low) tuple to set the high-water and low-water marks.""" diff --git a/tests/test_websocket_connection_options.py b/tests/test_websocket_connection_options.py index 122ee10078..0c0adf23d5 100644 --- a/tests/test_websocket_connection_options.py +++ b/tests/test_websocket_connection_options.py @@ -1,3 +1,7 @@ +# An invalid native-sync literal becoming accepted must fail the type check. +# pyright: reportUnnecessaryTypeIgnoreComment=true +from typing import TYPE_CHECKING + from openai import types from openai.types import websocket_connection_options @@ -18,3 +22,27 @@ def test_beta_realtime_import_still_works_with_old_alias() -> None: assert Realtime.__name__ == "Realtime" assert AsyncRealtime.__name__ == "AsyncRealtime" + + +if TYPE_CHECKING: + from openai import AsyncOpenAI + from openai.types.websocket_connection_options import SyncWebSocketConnectionOptions + + def native_options_contract(client: AsyncOpenAI) -> None: + # All synchronous native options remain representable. max_queue requires + # websockets >=14 for a synchronous native connection. + _sync: SyncWebSocketConnectionOptions = { + "extensions": None, + "subprotocols": None, + "compression": None, + "max_size": None, + "max_queue": (8, 2), + } + _sync = {"write_limit": 65536} # pyright: ignore[reportAssignmentType] + + # The existing names still support async write limits on all supported + # websocket versions, including through the generated public entrypoint. + original: types.WebSocketConnectionOptions = {"write_limit": 65536, "max_queue": 8} + legacy: types.WebsocketConnectionOptions = {"write_limit": (65536, 16384)} + client.realtime.connect(model="test", websocket_connection_options=original) + client.responses.connect(websocket_connection_options=legacy) From 07bcd9a18dddea892ccd9bd209d4964d1f38b35c Mon Sep 17 00:00:00 2001 From: markstuart-oai Date: Mon, 19 Oct 2026 22:16:28 +0000 Subject: [PATCH 2/2] test: consume sync options type-check cases --- tests/test_websocket_connection_options.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/test_websocket_connection_options.py b/tests/test_websocket_connection_options.py index 0c0adf23d5..468b797c8a 100644 --- a/tests/test_websocket_connection_options.py +++ b/tests/test_websocket_connection_options.py @@ -28,17 +28,19 @@ def test_beta_realtime_import_still_works_with_old_alias() -> None: from openai import AsyncOpenAI from openai.types.websocket_connection_options import SyncWebSocketConnectionOptions - def native_options_contract(client: AsyncOpenAI) -> None: + def native_options_contract( + client: AsyncOpenAI, + ) -> tuple[SyncWebSocketConnectionOptions, SyncWebSocketConnectionOptions]: # All synchronous native options remain representable. max_queue requires # websockets >=14 for a synchronous native connection. - _sync: SyncWebSocketConnectionOptions = { + valid_sync: SyncWebSocketConnectionOptions = { "extensions": None, "subprotocols": None, "compression": None, "max_size": None, "max_queue": (8, 2), } - _sync = {"write_limit": 65536} # pyright: ignore[reportAssignmentType] + invalid_sync: SyncWebSocketConnectionOptions = {"write_limit": 65536} # pyright: ignore[reportAssignmentType] # The existing names still support async write limits on all supported # websocket versions, including through the generated public entrypoint. @@ -46,3 +48,4 @@ def native_options_contract(client: AsyncOpenAI) -> None: legacy: types.WebsocketConnectionOptions = {"write_limit": (65536, 16384)} client.realtime.connect(model="test", websocket_connection_options=original) client.responses.connect(websocket_connection_options=legacy) + return valid_sync, invalid_sync