From ce6fb9a24d865073360d609de39a64208a8f4149 Mon Sep 17 00:00:00 2001 From: Kayvan Zahiri <123409429+Kayvan-Zahiri@users.noreply.github.com> Date: Fri, 23 Oct 2026 16:13:07 -0700 Subject: [PATCH 1/2] fix: convert event request timeout to seconds --- devcycle_python_sdk/api/event_client.py | 2 +- test/api/test_event_timeout.py | 47 +++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 test/api/test_event_timeout.py diff --git a/devcycle_python_sdk/api/event_client.py b/devcycle_python_sdk/api/event_client.py index 862a115..942b064 100644 --- a/devcycle_python_sdk/api/event_client.py +++ b/devcycle_python_sdk/api/event_client.py @@ -36,7 +36,7 @@ def publish_events(self, batch: List[UserEventsBatchRecord]) -> str: Attempts to send a batch of events to the server """ retries_remaining = self.max_batch_retries + 1 - timeout = self.options.event_request_timeout_ms + timeout = self.options.event_request_timeout_ms / 1000.0 payload_json = json.dumps( { diff --git a/test/api/test_event_timeout.py b/test/api/test_event_timeout.py new file mode 100644 index 0000000..f46dd9b --- /dev/null +++ b/test/api/test_event_timeout.py @@ -0,0 +1,47 @@ +import unittest + +import responses +from responses.matchers import request_kwargs_matcher + +from devcycle_python_sdk.api.event_client import EventAPIClient +from devcycle_python_sdk.models.event import UserEventsBatchRecord +from devcycle_python_sdk.models.user import DevCycleUser +from devcycle_python_sdk.options import DevCycleLocalOptions + + +class EventTimeoutTest(unittest.TestCase): + @responses.activate + def _check_timeout(self, timeout_ms=None): + options = ( + DevCycleLocalOptions() + if timeout_ms is None + else DevCycleLocalOptions(event_request_timeout_ms=timeout_ms) + ) + client = EventAPIClient("dvc_server_test", options) + expected_seconds = (10000 if timeout_ms is None else timeout_ms) / 1000.0 + responses.add( + responses.POST, + client.batch_url, + json={"message": "received"}, + match=[request_kwargs_matcher({"timeout": expected_seconds})], + ) + batch = [ + UserEventsBatchRecord(user=DevCycleUser(user_id="test-user"), events=[]) + ] + try: + self.assertEqual(client.publish_events(batch), "received") + self.assertEqual(len(responses.calls), 1) + finally: + client.session.close() + + def test_default_timeout(self): + self._check_timeout() + + def test_one_millisecond_timeout(self): + self._check_timeout(1) + + def test_subsecond_timeout(self): + self._check_timeout(250) + + def test_fractional_second_timeout(self): + self._check_timeout(1250) From 2ec10c609e945cd9ff44f3f00365d20e018b64c4 Mon Sep 17 00:00:00 2001 From: Kayvan Zahiri <123409429+Kayvan-Zahiri@users.noreply.github.com> Date: Wed, 28 Oct 2026 14:53:51 -0700 Subject: [PATCH 2/2] test: assert event timeout directly in EventAPIClientTest --- test/api/test_event_client.py | 18 +++++++++++++ test/api/test_event_timeout.py | 47 ---------------------------------- 2 files changed, 18 insertions(+), 47 deletions(-) delete mode 100644 test/api/test_event_timeout.py diff --git a/test/api/test_event_client.py b/test/api/test_event_client.py index 6a12537..ccec818 100644 --- a/test/api/test_event_client.py +++ b/test/api/test_event_client.py @@ -66,6 +66,24 @@ def test_publish_events_empty_batch(self): message = self.test_client.publish_events([]) self.assertEqual(message, "Successfully received 1 event batches.") + @responses.activate + def test_publish_events_timeout_in_seconds(self): + responses.add(responses.POST, self.test_batch_url, json={"message": "ok"}) + self.test_client.publish_events(self.test_batch) + self.assertEqual(responses.calls[0].request.req_kwargs["timeout"], 10.0) + + @responses.activate + def test_publish_events_custom_timeout_in_seconds(self): + client = EventAPIClient( + self.sdk_key, + DevCycleLocalOptions( + events_api_uri="http://localhost:8080", event_request_timeout_ms=250 + ), + ) + responses.add(responses.POST, self.test_batch_url, json={"message": "ok"}) + client.publish_events(self.test_batch) + self.assertEqual(responses.calls[0].request.req_kwargs["timeout"], 0.25) + @responses.activate(registry=OrderedRegistry) def test_publish_events_retries_exceeded(self): for i in range(2): diff --git a/test/api/test_event_timeout.py b/test/api/test_event_timeout.py deleted file mode 100644 index f46dd9b..0000000 --- a/test/api/test_event_timeout.py +++ /dev/null @@ -1,47 +0,0 @@ -import unittest - -import responses -from responses.matchers import request_kwargs_matcher - -from devcycle_python_sdk.api.event_client import EventAPIClient -from devcycle_python_sdk.models.event import UserEventsBatchRecord -from devcycle_python_sdk.models.user import DevCycleUser -from devcycle_python_sdk.options import DevCycleLocalOptions - - -class EventTimeoutTest(unittest.TestCase): - @responses.activate - def _check_timeout(self, timeout_ms=None): - options = ( - DevCycleLocalOptions() - if timeout_ms is None - else DevCycleLocalOptions(event_request_timeout_ms=timeout_ms) - ) - client = EventAPIClient("dvc_server_test", options) - expected_seconds = (10000 if timeout_ms is None else timeout_ms) / 1000.0 - responses.add( - responses.POST, - client.batch_url, - json={"message": "received"}, - match=[request_kwargs_matcher({"timeout": expected_seconds})], - ) - batch = [ - UserEventsBatchRecord(user=DevCycleUser(user_id="test-user"), events=[]) - ] - try: - self.assertEqual(client.publish_events(batch), "received") - self.assertEqual(len(responses.calls), 1) - finally: - client.session.close() - - def test_default_timeout(self): - self._check_timeout() - - def test_one_millisecond_timeout(self): - self._check_timeout(1) - - def test_subsecond_timeout(self): - self._check_timeout(250) - - def test_fractional_second_timeout(self): - self._check_timeout(1250)