From dec377c4f427ac58d795f110addbc48dc9ec63d3 Mon Sep 17 00:00:00 2001 From: Dumitru Gutu Date: Mon, 30 Jun 2025 10:47:11 +0100 Subject: [PATCH 1/2] Patch WebsocketClient to work with any websockets version >= 10.0 --- CHANGELOG.md | 4 ++++ VERSION | 2 +- requirements.txt | 2 +- speechmatics/client.py | 28 ++++++++++++++++++++++------ tests/test_client.py | 33 +++++++++++++++++++++++---------- 5 files changed, 51 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e3abec..aebcde0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [4.0.8] - 2025-06-30 + +- Patch WebsocketClient to work with any websockets version >= 10.0 + ## [4.0.7] - 2025-06-19 - Support requesting a temporary token (JWT) with region and client ref diff --git a/VERSION b/VERSION index 43beb40..a2cec7a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.0.7 +4.0.8 diff --git a/requirements.txt b/requirements.txt index f19dcaf..f1c27bd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -websockets>=14.0 +websockets>=10.0 httpx[http2]~=0.23 polling2~=0.5 toml~=0.10.2 diff --git a/speechmatics/client.py b/speechmatics/client.py index bb1c6a7..f2ce193 100644 --- a/speechmatics/client.py +++ b/speechmatics/client.py @@ -39,6 +39,18 @@ UsageMode, ) +try: + # Try to import from new websockets >=13.0 + from websockets.asyncio.client import connect + + WS_HEADERS_KEY = "additional_headers" +except ImportError: + # Fall back to legacy websockets + from websockets.legacy.client import connect + + WS_HEADERS_KEY = "extra_headers" + + LOGGER = logging.getLogger(__name__) # If the logging level is set to DEBUG then websockets logs very verbosely, @@ -613,14 +625,18 @@ async def run( parsed_url._replace(path=url_path, query=updated_query) ) + ws_kwargs = { + WS_HEADERS_KEY: extra_headers, + "ssl": self.connection_settings.ssl_context, + "ping_timeout": self.connection_settings.ping_timeout_seconds, + # Don't limit the max. size of incoming messages + "max_size": None, + } + try: - async with websockets.connect( # pylint: disable=no-member + async with connect( updated_url, - ssl=self.connection_settings.ssl_context, - ping_timeout=self.connection_settings.ping_timeout_seconds, - # Don't limit the max. size of incoming messages - max_size=None, - additional_headers=extra_headers, + **ws_kwargs, ) as self.websocket: await self._communicate(stream, audio_settings) finally: diff --git a/tests/test_client.py b/tests/test_client.py index fc72aa3..35187a0 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -10,7 +10,6 @@ import pytest from pytest_httpx import HTTPXMock -import websockets from speechmatics import client from speechmatics.batch_client import BatchClient from speechmatics.exceptions import ForceEndSession @@ -25,6 +24,17 @@ from tests.utils import path_to_test_resource, default_ws_client_setup +try: + # Try to import from new websockets >= 13 + from websockets.asyncio.client import connect + + WS_HEADERS_KEY = "additional_headers" +except ImportError: + # Fall back to legacy websockets + from websockets.legacy.client import connect + + WS_HEADERS_KEY = "extra_headers" + def test_json_utf8(): @client.json_utf8 @@ -229,13 +239,16 @@ async def test_send_message(mock_server, message_type: str, message_data: Any): """ ws_client, _, _ = default_ws_client_setup(mock_server.url) ws_client.session_running = True - - async with websockets.connect( + ws_kwargs = { + "ssl": ws_client.connection_settings.ssl_context, + "ping_timeout": ws_client.connection_settings.ping_timeout_seconds, + "max_size": None, + WS_HEADERS_KEY: None, + } + + async with connect( mock_server.url, - ssl=ws_client.connection_settings.ssl_context, - ping_timeout=ws_client.connection_settings.ping_timeout_seconds, - max_size=None, - additional_headers=None, + **ws_kwargs, ) as ws_client.websocket: await ws_client.send_message(message_type, message_data) assert message_type in [ @@ -387,7 +400,7 @@ async def mock_connect(*_, **__): mock_logger_error_method = MagicMock() - with patch("websockets.connect", mock_connect): + with patch("speechmatics.client.connect", mock_connect): with patch.object(client.LOGGER, "error", mock_logger_error_method): try: ws_client.run_synchronously( @@ -411,7 +424,7 @@ def call_exit(*args, **kwargs): mock_server.url ) stream = MagicMock() - with patch("websockets.connect", connect_mock): + with patch("speechmatics.client.connect", connect_mock): try: ws_client.run_synchronously( transcription_config=transcription_config, @@ -422,7 +435,7 @@ def call_exit(*args, **kwargs): except Exception: assert len(connect_mock.mock_calls) == 1 assert ( - connect_mock.mock_calls[0][2]["additional_headers"] == extra_headers + connect_mock.mock_calls[0][2][WS_HEADERS_KEY] == extra_headers ), f"Extra headers don't appear in the call list = {connect_mock.mock_calls}" From d2151a5fa219feceaf2c182f482b9b9e22e5661b Mon Sep 17 00:00:00 2001 From: Dumitru Gutu Date: Thu, 3 Jul 2025 12:26:16 +0100 Subject: [PATCH 2/2] Patch WebsocketClient to work with any websockets version >= 10.0 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aebcde0..57de1b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [4.0.8] - 2025-06-30 +## [4.0.8] - 2025-07-03 - Patch WebsocketClient to work with any websockets version >= 10.0