Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions src/openai/types/websocket_connection_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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."""
Expand Down
31 changes: 31 additions & 0 deletions tests/test_websocket_connection_options.py
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -18,3 +22,30 @@ 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,
) -> tuple[SyncWebSocketConnectionOptions, SyncWebSocketConnectionOptions]:
# All synchronous native options remain representable. max_queue requires
# websockets >=14 for a synchronous native connection.
valid_sync: SyncWebSocketConnectionOptions = {
"extensions": None,
"subprotocols": None,
"compression": None,
"max_size": None,
"max_queue": (8, 2),
}
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.
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)
return valid_sync, invalid_sync
Loading