Skip to content

Commit bd96a86

Browse files
Fix asyncio.CancelledError detection and add test coverage
- Fix module check to use startswith("asyncio") instead of == "asyncio" to properly match asyncio.exceptions.CancelledError - Add test case for asyncio.CancelledError to verify it bypasses retry loop Addresses review feedback from chatgpt-codex-connector bot
1 parent 40f4c4a commit bd96a86

File tree

3 files changed

+33
-1
lines changed

3 files changed

+33
-1
lines changed

repos/anthropic-sdk-python

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit 506a6cd37afb791f5d61760375eab841916921bd

src/openai/_base_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def _should_not_retry(exc: Exception) -> bool:
112112
return True
113113

114114
# asyncio cancellation
115-
if exc_module == "asyncio" and exc_name == "CancelledError":
115+
if exc_module.startswith("asyncio") and exc_name == "CancelledError":
116116
return True
117117

118118
return False

tests/test_client.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,37 @@ class MockCelerySoftTimeLimitExceeded(Exception):
896896
# Verify only one attempt was made (no retries)
897897
assert len(respx_mock.calls) == 1
898898

899+
@mock.patch("openai._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
900+
@pytest.mark.respx(base_url=base_url)
901+
def test_asyncio_cancelled_error_not_retried(self, respx_mock: MockRouter, client: OpenAI) -> None:
902+
"""Test that asyncio.CancelledError is not retried."""
903+
client = client.with_options(max_retries=3)
904+
905+
# Create a mock exception that mimics asyncio.exceptions.CancelledError
906+
class MockCancelledError(Exception):
907+
"""Mock of asyncio.exceptions.CancelledError"""
908+
909+
__module__ = "asyncio.exceptions"
910+
__name__ = "CancelledError"
911+
912+
# Mock the request to raise our cancellation signal
913+
respx_mock.post("/chat/completions").mock(side_effect=MockCancelledError("Task cancelled"))
914+
915+
# Verify the exception propagates without retry
916+
with pytest.raises(MockCancelledError):
917+
client.chat.completions.create(
918+
messages=[
919+
{
920+
"content": "string",
921+
"role": "developer",
922+
}
923+
],
924+
model="gpt-4o",
925+
)
926+
927+
# Verify only one attempt was made (no retries)
928+
assert len(respx_mock.calls) == 1
929+
899930
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
900931
@mock.patch("openai._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
901932
@pytest.mark.respx(base_url=base_url)

0 commit comments

Comments
 (0)