From 90235497ae29d2889bc229165ca6f5d49eb96115 Mon Sep 17 00:00:00 2001 From: gahusb Date: Sat, 16 May 2026 03:43:09 +0900 Subject: [PATCH] refactor(signal_v2): narrow stock_client exception catch + remove dead code Code quality review fixes: - _cached_request: catch httpx.HTTPError instead of bare Exception (avoid swallowing KeyboardInterrupt / asyncio.CancelledError) - _request_with_retry: remove unused last_exc variable + dead post-loop raise paths. Final sentinel raise preserved for mypy. 6 tests still pass. Deferred to Phase 7 backlog: cache concurrency coalescing + __aenter__/__aexit__ context manager support. Co-Authored-By: Claude Opus 4.7 (1M context) --- signal_v2/stock_client.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/signal_v2/stock_client.py b/signal_v2/stock_client.py index d718711..bfe4428 100644 --- a/signal_v2/stock_client.py +++ b/signal_v2/stock_client.py @@ -84,7 +84,7 @@ class StockClient: data = await self._request_with_retry(method, path, **kwargs) self._cache[cache_key] = (data, time.monotonic()) return data - except Exception: + except httpx.HTTPError: # Stale fallback: serve old cached value if exists if cache_key in self._cache: stale_data, stale_ts = self._cache[cache_key] @@ -98,7 +98,6 @@ class StockClient: async def _request_with_retry(self, method: str, path: str, **kwargs) -> dict: url = f"{self._base_url}{path}" headers = self._auth_headers() - last_exc: Exception | None = None for attempt in range(_MAX_ATTEMPTS): try: response = await self._client.request( @@ -111,18 +110,15 @@ class StockClient: response.raise_for_status() response.raise_for_status() return response.json() - except httpx.TimeoutException as e: - last_exc = e + except httpx.TimeoutException: if attempt < _MAX_ATTEMPTS - 1: await asyncio.sleep(2**attempt) continue raise - except httpx.HTTPStatusError as e: - last_exc = e + except httpx.HTTPStatusError: raise - if last_exc is not None: - raise last_exc - raise RuntimeError("retry exhausted") + # Unreachable: every iteration either returns or raises + raise RuntimeError("_request_with_retry exhausted loop without raising") def _auth_headers(self) -> dict[str, str]: return {"X-WebAI-Key": self._api_key}