Improve balldontlie query flow and dev container write stability
This commit is contained in:
@ -9,7 +9,7 @@ import requests
|
||||
from apps.providers.adapters.balldontlie_provider import BalldontlieProviderAdapter
|
||||
from apps.providers.adapters.mvp_provider import MvpDemoProviderAdapter
|
||||
from apps.providers.clients.balldontlie import BalldontlieClient
|
||||
from apps.providers.exceptions import ProviderRateLimitError, ProviderTransientError
|
||||
from apps.providers.exceptions import ProviderRateLimitError, ProviderTransientError, ProviderUnauthorizedError
|
||||
from apps.providers.registry import get_default_provider_namespace, get_provider
|
||||
from apps.providers.services.balldontlie_mappings import map_seasons
|
||||
|
||||
@ -28,8 +28,10 @@ class _FakeResponse:
|
||||
class _FakeSession:
|
||||
def __init__(self, responses: list[Any]):
|
||||
self._responses = responses
|
||||
self.calls: list[dict[str, Any]] = []
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
self.calls.append(kwargs)
|
||||
item = self._responses.pop(0)
|
||||
if isinstance(item, Exception):
|
||||
raise item
|
||||
@ -69,6 +71,9 @@ class _FakeBalldontlieClient:
|
||||
}
|
||||
]
|
||||
if path == "stats":
|
||||
requested_ids = (params or {}).get("game_ids[]") or []
|
||||
if requested_ids and 9902 not in requested_ids:
|
||||
return []
|
||||
return [
|
||||
{
|
||||
"pts": 20,
|
||||
@ -83,7 +88,7 @@ class _FakeBalldontlieClient:
|
||||
"min": "35:12",
|
||||
"player": {"id": 237},
|
||||
"team": {"id": 14},
|
||||
"game": {"season": 2024},
|
||||
"game": {"id": 9901, "season": 2024},
|
||||
},
|
||||
{
|
||||
"pts": 30,
|
||||
@ -98,9 +103,14 @@ class _FakeBalldontlieClient:
|
||||
"min": "33:00",
|
||||
"player": {"id": 237},
|
||||
"team": {"id": 14},
|
||||
"game": {"season": 2024},
|
||||
"game": {"id": 9902, "season": 2024},
|
||||
},
|
||||
]
|
||||
if path == "games":
|
||||
return [
|
||||
{"id": 9901, "season": 2024},
|
||||
{"id": 9902, "season": 2024},
|
||||
]
|
||||
return []
|
||||
|
||||
|
||||
@ -165,6 +175,30 @@ def test_balldontlie_map_seasons_marks_latest_as_current():
|
||||
assert [row["external_id"] for row in seasons] == ["season-2022", "season-2023", "season-2024"]
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_balldontlie_adapter_degrades_when_stats_unauthorized(settings):
|
||||
class _UnauthorizedStatsClient(_FakeBalldontlieClient):
|
||||
def list_paginated(self, path: str, *, params=None, per_page=100, page_limit=1):
|
||||
if path == "stats":
|
||||
raise ProviderUnauthorizedError(
|
||||
provider="balldontlie",
|
||||
path="stats",
|
||||
status_code=401,
|
||||
detail="Unauthorized",
|
||||
)
|
||||
return super().list_paginated(path, params=params, per_page=per_page, page_limit=page_limit)
|
||||
|
||||
settings.PROVIDER_BALLDONTLIE_SEASONS = [2024]
|
||||
settings.PROVIDER_BALLDONTLIE_STATS_STRICT = False
|
||||
adapter = BalldontlieProviderAdapter(client=_UnauthorizedStatsClient())
|
||||
|
||||
payload = adapter.sync_all()
|
||||
assert payload["players"]
|
||||
assert payload["teams"]
|
||||
assert payload["player_stats"] == []
|
||||
assert payload["player_careers"] == []
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_balldontlie_client_retries_after_rate_limit(monkeypatch, settings):
|
||||
monkeypatch.setattr(time, "sleep", lambda _: None)
|
||||
@ -212,3 +246,26 @@ def test_balldontlie_client_raises_rate_limit_after_max_retries(monkeypatch, set
|
||||
|
||||
with pytest.raises(ProviderRateLimitError):
|
||||
client.get_json("players")
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_balldontlie_client_cursor_pagination(settings):
|
||||
session = _FakeSession(
|
||||
responses=[
|
||||
_FakeResponse(
|
||||
status_code=200,
|
||||
payload={"data": [{"id": 1}], "meta": {"next_cursor": 101}},
|
||||
),
|
||||
_FakeResponse(
|
||||
status_code=200,
|
||||
payload={"data": [{"id": 2}], "meta": {"next_cursor": None}},
|
||||
),
|
||||
]
|
||||
)
|
||||
client = BalldontlieClient(session=session)
|
||||
rows = client.list_paginated("players", per_page=1, page_limit=5)
|
||||
|
||||
assert rows == [{"id": 1}, {"id": 2}]
|
||||
assert session.calls[0]["params"]["page"] == 1
|
||||
assert "cursor" not in session.calls[0]["params"]
|
||||
assert session.calls[1]["params"]["cursor"] == 101
|
||||
|
||||
Reference in New Issue
Block a user