Skip to content

Commit

Permalink
Merge pull request #201 from pittcsc/mypy-sports
Browse files Browse the repository at this point in the history
Refactor `sports.py` to use `NamedTuple`, fix `mypy` errors
  • Loading branch information
azharichenko authored Dec 24, 2024
2 parents cbe748b + 32c88e9 commit e8c62c0
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 48 deletions.
72 changes: 42 additions & 30 deletions pittapi/sports.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,39 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""

from __future__ import annotations

import requests

from typing import Any, NamedTuple

JSON = dict[str, Any]

FOOTBALL_URL = "http://site.api.espn.com/apis/site/v2/sports/football/college-football/teams/pitt"
MENS_BASKETBALL_URL = "http://site.api.espn.com/apis/site/v2/sports/basketball/mens-college-basketball/teams/pittsburgh"


class GameInfo(NamedTuple):
timestamp: str | None = None
opponent: dict[str, str] | None = None
home_away: str | None = None
location: dict[str, str] | None = None
status: str | None = None


def get_mens_basketball_record() -> str:
"""returns the current record of the men's basketball team"""
basketball_data = _get_mens_basketball_data()

try:
record_summary = basketball_data["team"]["record"]["items"][0]["summary"]

record_summary: str = basketball_data["team"]["record"]["items"][0]["summary"]
except KeyError:
record_summary = "There's no record right now."

return record_summary


def get_next_mens_basketball_game() -> dict:
def get_next_mens_basketball_game() -> GameInfo:
"""returns a dict containing details of the next scheduled men's basketball game."""
basketball_data = _get_mens_basketball_data()
next_game = None
Expand All @@ -55,30 +68,29 @@ def get_next_mens_basketball_game() -> dict:
else:
opponent = next_game["competitions"][0]["competitors"][1]
homeaway = next_game["competitions"][0]["competitors"][1]["homeAway"]
return {
"timestamp": next_game["date"],
"opponent": {
return GameInfo(
timestamp=next_game["date"],
opponent={
"id": opponent["team"]["id"],
"school": opponent["team"]["nickname"],
"name": opponent["team"]["displayName"],
},
"home_away": homeaway,
"location": {
home_away=homeaway,
location={
"full_name": next_game["competitions"][0]["venue"]["fullName"],
"address": next_game["competitions"][0]["venue"]["address"],
},
"status": status,
}
status=status,
)
except IndexError:
# IndexError occurs when a next game on the schedule is not present
return {"status": "NO_GAME_SCHEDULED"}
return GameInfo(status="NO_GAME_SCHEDULED")


def get_mens_basketball_standings() -> str:
"""returns a string describing the placement of the men's basketball team. eg: '14th in ACC'"""
basketball_data = _get_mens_basketball_data()

return_value = basketball_data["team"]["standingSummary"]
return_value: str = basketball_data["team"]["standingSummary"]
return return_value


Expand All @@ -87,15 +99,14 @@ def get_football_record() -> str:
football_data = _get_football_data()

try:
record_summary = football_data["team"]["record"]["items"][0]["summary"]

record_summary: str = football_data["team"]["record"]["items"][0]["summary"]
except KeyError:
record_summary = "There's no record right now."

return record_summary


def get_next_football_game() -> dict:
def get_next_football_game() -> GameInfo:
football_data = _get_football_data()
next_game = None
try:
Expand All @@ -113,36 +124,37 @@ def get_next_football_game() -> dict:
else:
opponent = next_game["competitions"][0]["competitors"][0]
homeaway = next_game["competitions"][0]["competitors"][1]["homeAway"]
return {
"timestamp": next_game["date"],
"opponent": {
return GameInfo(
timestamp=next_game["date"],
opponent={
"id": opponent["team"]["id"],
"school": opponent["team"]["nickname"],
"name": opponent["team"]["displayName"],
},
"home_away": homeaway,
"location": {
home_away=homeaway,
location={
"full_name": next_game["competitions"][0]["venue"]["fullName"],
"address": next_game["competitions"][0]["venue"]["address"],
},
"status": status,
}
status=status,
)
except IndexError:
# IndexError occurs when a next game on the schedule is not present
return {"status": "NO_GAME_SCHEDULED"}
return GameInfo(status="NO_GAME_SCHEDULED")


def get_football_standings() -> str:
"""returns a string describing the placement of the football team. eg: '14th in ACC'"""
football_data = _get_football_data()

return_value = football_data["team"]["standingSummary"]
return_value: str = football_data["team"]["standingSummary"]
return return_value


def _get_mens_basketball_data() -> dict:
return requests.get(MENS_BASKETBALL_URL).json()
def _get_mens_basketball_data() -> JSON:
json_data: JSON = requests.get(MENS_BASKETBALL_URL).json()
return json_data


def _get_football_data() -> dict:
return requests.get(FOOTBALL_URL).json()
def _get_football_data() -> JSON:
json_data: JSON = requests.get(FOOTBALL_URL).json()
return json_data
30 changes: 12 additions & 18 deletions tests/sports_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,36 +170,30 @@ def test_get_football_standings(self):

def test_get_next_mens_basketball_game(self):
next_game_details = sports.get_next_mens_basketball_game()
self.assertIn("timestamp", next_game_details)
self.assertIn("opponent", next_game_details)
self.assertIn("home_away", next_game_details)
self.assertIn("location", next_game_details)
self.assertIn("status", next_game_details)
self.assertNotEqual("NO_GAME_SCHEDULED", next_game_details["status"])
self.assertNotEqual("NO_GAME_SCHEDULED", next_game_details.status)

def test_get_next_football_game(self):
next_game_details = sports.get_next_football_game()
self.assertIn("timestamp", next_game_details)
self.assertIn("opponent", next_game_details)
self.assertIn("home_away", next_game_details)
self.assertIn("location", next_game_details)
self.assertIn("status", next_game_details)
self.assertNotEqual("NO_GAME_SCHEDULED", next_game_details["status"])
self.assertNotEqual("NO_GAME_SCHEDULED", next_game_details.status)

def test_get_next_mens_basketball_game_offseason(self):
offseason_data = {"team": {"nextEvent": []}}
sports._get_mens_basketball_data = MagicMock(return_value=offseason_data)

next_game_details = sports.get_next_mens_basketball_game()
self.assertEqual(1, len(next_game_details))
self.assertIn("status", next_game_details)
self.assertEqual("NO_GAME_SCHEDULED", next_game_details["status"])
self.assertIsNone(next_game_details.timestamp)
self.assertIsNone(next_game_details.opponent)
self.assertIsNone(next_game_details.home_away)
self.assertIsNone(next_game_details.location)
self.assertEqual("NO_GAME_SCHEDULED", next_game_details.status)

def test_get_next_football_game_offseason(self):
offseason_data = {"team": {"nextEvent": []}}
sports._get_football_data = MagicMock(return_value=offseason_data)

next_game_details = sports.get_next_football_game()
self.assertEqual(1, len(next_game_details))
self.assertIn("status", next_game_details)
self.assertEqual("NO_GAME_SCHEDULED", next_game_details["status"])
self.assertIsNone(next_game_details.timestamp)
self.assertIsNone(next_game_details.opponent)
self.assertIsNone(next_game_details.home_away)
self.assertIsNone(next_game_details.location)
self.assertEqual("NO_GAME_SCHEDULED", next_game_details.status)

0 comments on commit e8c62c0

Please sign in to comment.