From 7ba82429cadccbe64fa27063ec16079afb63d443 Mon Sep 17 00:00:00 2001 From: aloktripathi1 Date: Mon, 13 Jul 2026 20:39:26 +0530 Subject: [PATCH] test(openai): don't hard-require optional aiohttp in fail-open black-box tests aiohttp is only declared under the optional `async` extra, not the dev dependency group, so the black-box repros failed with ModuleNotFoundError under the default `uv sync --dev` setup before exercising anything. - Async repro now uses pytest.importorskip("aiohttp"), skipping cleanly when the extra is absent (it exercises the aiohttp code path). - Sync repro forces the requests fallback by making `import aiohttp` fail via sys.modules, so it runs in the default dev setup and actually covers the requests path production uses when aiohttp is not installed. Verified both ways: with aiohttp -> 35 passed, 11 skipped; without aiohttp -> 34 passed, 12 skipped (async repro skips, sync repro passes via requests). --- .../tests/test_middleware.py | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/packages/openai-sdk-python/tests/test_middleware.py b/packages/openai-sdk-python/tests/test_middleware.py index 45250eb7..ab823fa3 100644 --- a/packages/openai-sdk-python/tests/test_middleware.py +++ b/packages/openai-sdk-python/tests/test_middleware.py @@ -1052,9 +1052,15 @@ class TestMemorySearchFailOpen: async def test_black_box_async_connection_error( self, mock_async_openai_client, mock_openai_response ): - """Exact repro: the real search path hits a connection error at the - HTTP layer, and ``create()`` must still return successfully.""" - import aiohttp + """Exact repro over the aiohttp path: the real search path hits a + connection error at the HTTP layer, and ``create()`` must still return + successfully. + + ``aiohttp`` is only an optional (``async`` extra) dependency, so this + test skips cleanly when it is not installed; the ``requests`` fallback + is covered by ``test_black_box_sync_connection_error`` instead. + """ + aiohttp = pytest.importorskip("aiohttp") original_create = AsyncMock(return_value=mock_openai_response) mock_async_openai_client.chat.completions.create = original_create @@ -1087,9 +1093,16 @@ class TestMemorySearchFailOpen: def test_black_box_sync_connection_error( self, mock_openai_client, mock_openai_response ): - """Exact repro for the sync wrapper: a connection error at the HTTP - layer must not crash ``create()``.""" - import aiohttp + """Exact repro over the ``requests`` fallback: a connection error at the + HTTP layer must not crash ``create()``. + + ``requests`` is a core dependency, so this repro runs in the default dev + setup without the optional ``aiohttp`` extra. We force the fallback by + making ``import aiohttp`` fail inside ``supermemory_profile_search`` (via + ``sys.modules``), which mirrors a production install without the extra. + """ + import sys + import requests original_create = Mock(return_value=mock_openai_response) @@ -1100,11 +1113,8 @@ class TestMemorySearchFailOpen: "supermemory_openai.middleware.add_memory_tool", new=AsyncMock(return_value=None), ): - # Fail whichever HTTP client the search path ends up using. - with patch( - "aiohttp.ClientSession.post", - side_effect=aiohttp.ClientConnectionError("connection refused"), - ): + # Force the requests fallback: `import aiohttp` raises ImportError. + with patch.dict(sys.modules, {"aiohttp": None}): with patch( "requests.post", side_effect=requests.exceptions.ConnectionError(