Skip to content

Guard _fetch_sec_filings and _fetch_calendar against null/empty Yahoo results - #2883

Open
8910work-cell wants to merge 1 commit into
ranaroussi:devfrom
8910work-cell:fix/sec-filings-calendar-null-guard
Open

Guard _fetch_sec_filings and _fetch_calendar against null/empty Yahoo results#2883
8910work-cell wants to merge 1 commit into
ranaroussi:devfrom
8910work-cell:fix/sec-filings-calendar-null-guard

Conversation

@8910work-cell

Copy link
Copy Markdown

Problem

_fetch_sec_filings runs filings = result["quoteSummary"]["result"][0]["secFilings"]["filings"] immediately after the if result is None: return None guard. When Yahoo returns a non-None payload whose quoteSummary.result is null/empty (or is missing the secFilings key), this crashes with TypeError: 'NoneType' object is not subscriptable (or KeyError/IndexError).

_fetch_calendar has the same class of gap: its parse block only catches (KeyError, IndexError), so a null nested structure raises an uncaught TypeError.

Fix

  • _fetch_sec_filings: wrap the nested lookup in try/except (KeyError, IndexError, TypeError) and return None — graceful degradation, consistent with the existing result is None guard.
  • _fetch_calendar: add TypeError to the existing except tuple.

Tests

Adds network-free regression tests (mocking Quote._fetch) in tests/test_ticker.py:

  • test_sec_filings_null_result — a null result degrades to None instead of crashing
  • test_sec_filings_happy_path — a valid payload still parses correctly
  • test_calendar_null_result — a null result raises a clean YFDataException

Verified red→green: test_sec_filings_null_result fails on current dev with TypeError: 'NoneType' object is not subscriptable and passes with this change.

… result

Both methods accessed result["quoteSummary"]["result"][0] with no guard
against null or empty list responses from Yahoo Finance. The same null-
result pattern was recently fixed in _fetch_info (ranaroussi#2869) and
_fetch_complementary (ranaroussi#2863, ranaroussi#2877).

- _fetch_sec_filings: wrap bare dict access in try/except(KeyError,
  IndexError, TypeError); return None on any malformed payload.
- _fetch_calendar: add TypeError to the existing except clause so a
  null result list (not just a missing key or empty list) is handled by
  the YFDataException path instead of propagating uncaught.

Add three network-free regression tests covering the null/empty cases
and a happy-path round-trip for sec_filings.
@ValueRaider

Copy link
Copy Markdown
Collaborator

When does Yahoo returns a non-None payload?

@8910work-cell

Copy link
Copy Markdown
Author

Good question. _fetch() returns the parsed JSON whenever the HTTP request itself succeeds — it only returns None on an HTTPError (with hide_exceptions). So the existing if result is None guard at the top of both methods catches a failed request, not a successful HTTP 200 whose body has quoteSummary.result: null.

Yahoo returns that shape for symbols/modules it has no data for (delisted or invalid tickers, region-restricted symbols, or a module that simply returns nothing):

{"quoteSummary": {"result": null, "error": null}}

result["quoteSummary"]["result"] is then None, and [0] raises TypeError: 'NoneType' object is not subscriptable. It's the same "Yahoo returns an empty payload" class already fixed for the sibling methods in #2863 and #2877, and reported for _fetch_info in #2865.

Reproduced on current dev (f9eb690), network-free:

from unittest.mock import patch, MagicMock
from yfinance.scrapers.quote import Quote

null_payload = {"quoteSummary": {"result": None, "error": None}}
for name in ("_fetch_sec_filings", "_fetch_calendar"):
    q = Quote(MagicMock(), "DELISTED")
    with patch.object(Quote, "_fetch", return_value=null_payload):
        getattr(q, name)()
# _fetch_sec_filings -> TypeError: 'NoneType' object is not subscriptable
# _fetch_calendar    -> TypeError: 'NoneType' object is not subscriptable

Note _fetch_calendar already caught (KeyError, IndexError) — the []/missing-key cases — so this PR only adds the TypeError that the None case raises; _fetch_sec_filings had no guard at all. After the change _fetch_sec_filings returns None and _fetch_calendar raises YFDataException (its existing error path), matching how sustainability / recommendations / upgrades_downgrades already handle the same access chain.

@ValueRaider

Copy link
Copy Markdown
Collaborator

My point was - I prefer checking for specific values instead of exception. Maybe when that keyerror happens, there is another key with information.

Also I expect to speak with a human not a bot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants