From 3dda70baf239f5ab4c5056becf962e6a337fa0a3 Mon Sep 17 00:00:00 2001 From: ***** <721466+soodoku@users.noreply.github.com> Date: Wed, 21 Oct 2026 11:50:11 -0700 Subject: [PATCH] Fix Player initialization using core team references --- espncricinfo/player.py | 35 ++++++++++++++++++----------------- tests/test_player.py | 41 ++++++++++++++++++++++++++++++++++------- 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/espncricinfo/player.py b/espncricinfo/player.py index 1cc1f28..910c528 100644 --- a/espncricinfo/player.py +++ b/espncricinfo/player.py @@ -16,13 +16,9 @@ def __init__(self, player_id): self.json_url = "http://core.espnuk.org/v2/sports/cricket/athletes/{0}".format( str(player_id) ) - self.new_json_url = "https://hs-consumer-api.espncricinfo.com/v1/pages/player/home?playerId={0}".format( - str(player_id) - ) self.headers = {"user-agent": "Mozilla/5.0"} - self.parsed_html = self.get_html() self.json = self.get_json() - self.new_json = self.get_new_json() + self._major_teams_cache = None self.cricinfo_id = str(player_id) self.__unicode__ = self._full_name() self.name = self._name() @@ -33,7 +29,6 @@ def __init__(self, player_id): self.playing_role = self._playing_role() self.batting_style = self._batting_style() self.bowling_style = self._bowling_style() - self.major_teams = self._major_teams() def get_html(self): r = requests.get(self.url, headers=self.headers) @@ -46,15 +41,8 @@ def get_json(self): r = requests.get(self.json_url, headers=self.headers) if r.status_code == 404: raise PlayerNotFoundError - else: - return r.json() - - def get_new_json(self): - r = requests.get(self.new_json_url, headers=self.headers) - if r.status_code == 404: - raise PlayerNotFoundError - else: - return r.json() + r.raise_for_status() + return r.json() def _name(self): return self.json["name"] @@ -77,8 +65,21 @@ def _date_of_birth(self): def _current_age(self): return self.json["age"] - def _major_teams(self): - return [x["team"]["longName"] for x in self.new_json["content"]["teams"]] + @property + def major_teams(self): + if self._major_teams_cache is None: + teams = [] + for reference in self.json.get("majorTeams", []): + response = requests.get(reference["$ref"], headers=self.headers) + response.raise_for_status() + team = response.json() + name = ( + team.get("longName") or team.get("displayName") or team.get("name") + ) + if name: + teams.append(name) + self._major_teams_cache = teams + return self._major_teams_cache def _playing_role(self): return self.json["position"] diff --git a/tests/test_player.py b/tests/test_player.py index 14a7884..ba686eb 100644 --- a/tests/test_player.py +++ b/tests/test_player.py @@ -5,6 +5,7 @@ from unittest.mock import MagicMock, patch import pytest +from requests import HTTPError, Response from espncricinfo.exceptions import PlayerNotFoundError from espncricinfo.player import Player @@ -31,18 +32,18 @@ def _mock_response(json_data=None, text=None, status_code=200): def _make_player(): json_data = _load("player_253802.json") - new_json = _load("player_253802_new.json") def side_effect(url, headers=None): - if "hs-consumer-api" in url: - return _mock_response(json_data=new_json) - elif "espnuk.org" in url: + if "/athletes/" in url: return _mock_response(json_data=json_data) - else: - return _mock_response(text="") + if "/teams/" in url: + return _mock_response(json_data={"name": f"Team {url.rsplit('/', 1)[-1]}"}) + raise AssertionError(f"Unexpected request: {url}") with patch("espncricinfo.player.requests.get", side_effect=side_effect): - return Player(253802) + player = Player(253802) + _ = player.major_teams + return player class TestPlayerAttributes(unittest.TestCase): @@ -91,6 +92,24 @@ def test_major_teams_are_strings(self): for team in self.player.major_teams: self.assertIsInstance(team, str) + def test_major_teams_resolve_core_references_once(self): + player_data = _load("player_253802.json") + player_data["majorTeams"] = [ + {"$ref": "http://core.espnuk.org/v2/sports/cricket/teams/6"}, + {"$ref": "http://core.espnuk.org/v2/sports/cricket/teams/1668"}, + ] + responses = [ + _mock_response(json_data=player_data), + _mock_response(json_data={"displayName": "India"}), + _mock_response(json_data={"name": "Delhi"}), + ] + with patch("espncricinfo.player.requests.get", side_effect=responses) as get: + player = Player(253802) + self.assertEqual(get.call_count, 1) + self.assertEqual(player.major_teams, ["India", "Delhi"]) + self.assertEqual(player.major_teams, ["India", "Delhi"]) + self.assertEqual(get.call_count, 3) + class TestPlayerErrors(unittest.TestCase): def test_404_raises_player_not_found(self): @@ -99,6 +118,14 @@ def test_404_raises_player_not_found(self): with self.assertRaises(PlayerNotFoundError): Player(999999) + def test_non_404_http_error_is_not_decoded_as_json(self): + denied = Response() + denied.status_code = 403 + denied._content = b"Access Denied" + with patch("espncricinfo.player.requests.get", return_value=denied): + with self.assertRaises(HTTPError): + Player(253802) + class TestPlayerIntegration: @pytest.mark.integration