Fix Finnhub API error handling and add coverage

Extracted the API request logic in `finnhub_news.py` to a private `_fetch_company_news_data` helper to properly catch `Exception` and return an empty list without violating the `str` return type of the main `get_company_news` function. Explicitly allows `ThirdPartyTimeoutError` to propagate to preserve timeout behavior.

Added corresponding tests to mock generic API exceptions and invalid response types. Retained the test verifying fallback behavior for invalid numeric values within `get_insider_transactions`.

Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
This commit is contained in:
google-labs-jules[bot] 2026-03-21 14:51:29 +00:00
parent 5799bb3f00
commit bdaf188b33
2 changed files with 71 additions and 1 deletions

View File

@ -756,6 +756,32 @@ class TestGetBasicFinancials:
# ---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# 10.5 finnhub_news — _fetch_company_news_data helper
# ---------------------------------------------------------------------------
class TestFetchCompanyNewsData:
"""_fetch_company_news_data handles errors by returning an empty list."""
_PATCH_TARGET = "tradingagents.dataflows.finnhub_news._make_api_request"
def test_fetch_company_news_data_api_error_returns_empty_list(self):
from tradingagents.dataflows.finnhub_news import _fetch_company_news_data
with patch(self._PATCH_TARGET, side_effect=Exception("API failure")):
result = _fetch_company_news_data("AAPL", {"symbol": "AAPL"})
assert result == []
def test_fetch_company_news_data_invalid_response_type_returns_empty_list(self):
from tradingagents.dataflows.finnhub_news import _fetch_company_news_data
with patch(self._PATCH_TARGET, return_value={"error": "Not a list"}):
result = _fetch_company_news_data("AAPL", {"symbol": "AAPL"})
assert result == []
# 10. finnhub_news — get_company_news
# ---------------------------------------------------------------------------
@ -892,6 +918,30 @@ class TestGetInsiderTransactions:
assert "AAPL" in result
def test_invalid_transaction_values_fall_back_to_raw_strings(self):
"""Testing the error path at line 220 where float conversion fails."""
from tradingagents.dataflows.finnhub_news import get_insider_transactions
invalid_txn = {
"data": [
{
"name": "Test Exec",
"transactionCode": "P",
"share": "invalid_share",
"price": "invalid_price",
"value": "invalid_value",
"transactionDate": "2024-01-10",
"filingDate": "2024-01-12",
}
]
}
with patch(self._PATCH_TARGET, return_value=_json_response(invalid_txn)):
result = get_insider_transactions("AAPL")
assert "invalid_share" in result
assert "invalid_price" in result
assert "invalid_value" in result
# ---------------------------------------------------------------------------
# 13. finnhub_scanner — get_market_movers_finnhub

View File

@ -5,16 +5,21 @@ transaction data using the Finnhub REST API. Output formats mirror the
Alpha Vantage news equivalents for consistent agent-facing data.
"""
import logging
from datetime import datetime
from typing import Literal
from .finnhub_common import (
FinnhubError,
ThirdPartyTimeoutError,
_make_api_request,
_now_str,
_to_unix_timestamp,
)
logger = logging.getLogger(__name__)
# ---------------------------------------------------------------------------
# Type aliases
# ---------------------------------------------------------------------------
@ -49,6 +54,21 @@ def _format_unix_ts(ts: int | None) -> str:
# ---------------------------------------------------------------------------
def _fetch_company_news_data(symbol: str, params: dict) -> list[dict]:
"""Helper to fetch company news and handle errors by returning an empty list."""
try:
response = _make_api_request("company-news", params)
except ThirdPartyTimeoutError:
raise
except Exception as e:
logger.error(f"Error fetching company news for {symbol}: {e}")
return []
if not isinstance(response, list):
return []
return response
def get_company_news(symbol: str, start_date: str, end_date: str) -> str:
"""Fetch company-specific news via Finnhub /company-news.
@ -73,7 +93,7 @@ def get_company_news(symbol: str, start_date: str, end_date: str) -> str:
"to": end_date,
}
articles: list[dict] = _make_api_request("company-news", params)
articles: list[dict] = _fetch_company_news_data(symbol, params)
header = (
f"# Company News: {symbol} ({start_date} to {end_date}) — Finnhub\n"