From 2bbbc65c87ae13c2577e29c7ac2a32717242af70 Mon Sep 17 00:00:00 2001 From: Frank Barrett Date: Mon, 20 Jul 2026 22:40:16 -0700 Subject: [PATCH] fix(python): honor zero reconnect attempts Treat only a missing or None maxReconnectAttempts value as the default. This preserves an explicit zero so Python matches the TypeScript WebSocket client configuration semantics. Add regression coverage for both the None default and zero-attempt cases. Co-Authored-By: Codex --- sdks/python/pmxt/ws_client.py | 4 +++- sdks/python/tests/test_ws_client.py | 31 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/sdks/python/pmxt/ws_client.py b/sdks/python/pmxt/ws_client.py index bc93c362..2cf0a9bb 100644 --- a/sdks/python/pmxt/ws_client.py +++ b/sdks/python/pmxt/ws_client.py @@ -140,7 +140,9 @@ def _ensure_connected(self) -> None: # Connection attempts default to CONNECT_ATTEMPTS; callers may override # via the "maxReconnectAttempts" config key. - max_attempts = self._config.get("maxReconnectAttempts") or CONNECT_ATTEMPTS + max_attempts = self._config.get("maxReconnectAttempts") + if max_attempts is None: + max_attempts = CONNECT_ATTEMPTS # When "reconnectInterval" (ms) is not configured, preserve the fast # default backoff (0.25s, 0.5s, ...). Only a longer, explicitly # configured interval overrides it. diff --git a/sdks/python/tests/test_ws_client.py b/sdks/python/tests/test_ws_client.py index 13c9771c..3880577a 100644 --- a/sdks/python/tests/test_ws_client.py +++ b/sdks/python/tests/test_ws_client.py @@ -4,7 +4,10 @@ import sys import types +import pytest + import pmxt.ws_client as ws_client +from pmxt.errors import PmxtError from pmxt.ws_client import SidecarWsClient, _WsSubscription, _connect_websocket @@ -147,6 +150,34 @@ def test_ws_config_custom_url_and_reconnect_interval(monkeypatch): assert sleeps == [2.0] +def test_ws_none_reconnect_attempts_uses_default(monkeypatch): + urls = [] + _install_failing_websocket(monkeypatch, urls) + + client = SidecarWsClient( + "http://localhost:3847", config={"maxReconnectAttempts": None} + ) + with pytest.raises(OSError, match="handshake failure"): + with client._lock: + client._ensure_connected() + + assert len(urls) == 3 + + +def test_ws_zero_reconnect_attempts_is_honored(monkeypatch): + urls = [] + _install_failing_websocket(monkeypatch, urls) + + client = SidecarWsClient( + "http://localhost:3847", config={"maxReconnectAttempts": 0} + ) + with pytest.raises(PmxtError, match="WebSocket connection failed"): + with client._lock: + client._ensure_connected() + + assert urls == [] + + def test_ws_default_backoff_is_fast(monkeypatch): """Regression: the default reconnect backoff must stay 0.25s/0.5s, not a flat multi-second sleep, unless an interval is explicitly configured."""