From 40318625a6d8e5d079222f1976ab324c9d81a2f9 Mon Sep 17 00:00:00 2001 From: Bill Mill Date: Fri, 27 Mar 2026 10:35:31 -0400 Subject: [PATCH] feat: raise exception on non-2xx responses It can be difficult to diagnose issues happening inside the library when it doesn't throw exceptions on exceptional responses. Use the raise_for_status method of requests to throw on non-2xx responses --- src/nba_api/library/http.py | 1 + tests/unit/http/test_legacy_debug_usage.py | 45 ++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/nba_api/library/http.py b/src/nba_api/library/http.py index aeac18ee..8365d0fd 100644 --- a/src/nba_api/library/http.py +++ b/src/nba_api/library/http.py @@ -161,6 +161,7 @@ def send_api_request( proxies=proxies, timeout=timeout, ) + response.raise_for_status() url = response.url status_code = response.status_code contents = response.text diff --git a/tests/unit/http/test_legacy_debug_usage.py b/tests/unit/http/test_legacy_debug_usage.py index f72a1700..088c70c5 100644 --- a/tests/unit/http/test_legacy_debug_usage.py +++ b/tests/unit/http/test_legacy_debug_usage.py @@ -266,3 +266,48 @@ def test_debug_storage_caching(is_file_cached, monkeypatch): assistleaders.AssistLeaders() assert (not mock_get.called) if is_file_cached else mock_get.called + + +# Test raise_for_status +@pytest.mark.parametrize( + "status_code", + [400, 403, 404, 500, 502, 503], + ids=["400", "403", "404", "500", "502", "503"], +) +def test_stats_endpoint_raises_on_http_error(status_code): + """An HTTP error response (4xx/5xx) raises requests.HTTPError via raise_for_status.""" + error_response = Mock() + error_response.status_code = status_code + error_response.url = "https://nba.com/stats/assistleaders" + error_response.raise_for_status.side_effect = requests.HTTPError( + f"{status_code} Error", response=error_response + ) + + with ( + patch.object(requests.Session, "get", return_value=error_response), + pytest.raises(requests.HTTPError, match=f"{status_code} Error"), + ): + assistleaders.AssistLeaders() + + +@pytest.mark.parametrize( + "status_code", + [400, 403, 404, 500, 502, 503], + ids=["400", "403", "404", "500", "502", "503"], +) +def test_live_endpoint_raises_on_http_error(status_code): + """An HTTP error response (4xx/5xx) raises requests.HTTPError via raise_for_status.""" + error_response = Mock() + error_response.status_code = status_code + error_response.url = ( + "https://cdn.nba.com/static/json/liveData/scoreboard/todaysScoreboard_00.json" + ) + error_response.raise_for_status.side_effect = requests.HTTPError( + f"{status_code} Error", response=error_response + ) + + with ( + patch.object(requests.Session, "get", return_value=error_response), + pytest.raises(requests.HTTPError, match=f"{status_code} Error"), + ): + scoreboard.ScoreBoard()