diff --git a/README.md b/README.md index 90c0cbc..15f7bc8 100644 --- a/README.md +++ b/README.md @@ -35,4 +35,15 @@ or using pipx 2) `poetry install --with dev` -3) `poetry shell` to run commands such as `pytest` \ No newline at end of file +3) `poetry shell` + +```python + +$ poetry shell + +# You can then run the following +$ pytest +$ ruff . +$ black . + +``` \ No newline at end of file diff --git a/nhlpy/_version.py b/nhlpy/_version.py index ccb0988..934168d 100644 --- a/nhlpy/_version.py +++ b/nhlpy/_version.py @@ -1,3 +1,3 @@ # Should this be driven by the main pyproject.toml file? yes, is it super convoluted? yes, can it wait? sure -__version__ = "2.0.1" +__version__ = "2.0.2" diff --git a/nhlpy/api/core.py b/nhlpy/api/core.py deleted file mode 100644 index 9d28a5a..0000000 --- a/nhlpy/api/core.py +++ /dev/null @@ -1,29 +0,0 @@ -from httpx import request - -from nhlpy.api import BaseNHLAPIClient - - -class Core(BaseNHLAPIClient): - def get_configurations(self) -> dict: - """ - Returns a list of configuration items that can be used in other endpoints - :return: - """ - r: request = self._get(resource="configurations") - return r.json() - - def get_game_types(self) -> dict: - """ - Returns a list of game types that can be used in other endpoints - :return: - """ - r: request = self._get(resource="gameTypes") - return r.json() - - def get_standings_types(self) -> dict: - """ - - :return: - """ - r: request = self._get(resource="standingsTypes") - return r.json() diff --git a/nhlpy/api/game_center.py b/nhlpy/api/game_center.py new file mode 100644 index 0000000..b34032f --- /dev/null +++ b/nhlpy/api/game_center.py @@ -0,0 +1,36 @@ +from nhlpy.api import BaseNHLAPIClient + + +class GameCenter(BaseNHLAPIClient): + def boxscore(self, game_id: str) -> dict: + """ + Get the boxscore for the game_id. GameIds can be retrieved from the schedule endpoint. + :param game_id: The game_id for the game you want the boxscore for. + :return: dict + """ + return self._get(resource=f"gamecenter/{game_id}/boxscore").json() + + def play_by_play(self, game_id: str) -> dict: + """ + Get the play by play for the game_id. GameIds can be retrieved from the schedule endpoint. + :param game_id: The game_id for the game you want the play by play for. + :return: dict + """ + return self._get(resource=f"gamecenter/{game_id}/play-by-play").json() + + def landing(self, game_id: str) -> dict: + """ + Get verbose information about the matchup for the given game. + + GameIds can be retrieved from the schedule endpoint. + :param game_id: The game_id for the game you want the landing page for. + :return: dict + """ + return self._get(resource=f"gamecenter/{game_id}/landing").json() + + def score_now(self) -> dict: + """ + Get the current score of all games in progress. I think, not totally sure. + :return: dict + """ + return self._get(resource="score/now").json() diff --git a/nhlpy/api/games.py b/nhlpy/api/games.py deleted file mode 100644 index 4bc055d..0000000 --- a/nhlpy/api/games.py +++ /dev/null @@ -1,104 +0,0 @@ -import warnings -from typing import Union, List -from nhlpy.api import BaseNHLAPIClient - - -class Games(BaseNHLAPIClient): - """ - This class is used to access the NHL API for game data. - """ - - def get_game_types(self) -> dict: - """ - Returns a list of game types that can be used in other endpoints - :return: - """ - return self._get(resource="gameTypes").json() - - def get_game_play_types(self) -> dict: - """ - Returns a list of play types that can be used in other endpoints - :return: - """ - return self._get(resource="playTypes").json() - - def get_game_status_codes(self) -> dict: - """ - Returns a list of game status codes that can be used in other endpoints - example: - [{ - "code": "1", - "abstractGameState": "Preview", - "detailedState": "Scheduled", - "baseballCode": "S", - "startTimeTBD": false - }...] - :return: dict - """ - return self._get(resource="gameStatus").json() - - def get_game_live_feed(self, game_id: Union[str, int]) -> dict: - """ - Returns a live feed for the game with the id supplied. WARNING, this tends to be a large response. - :param game_id: int, NHL game id, - - GameIDS are in the format {Season}{GameType}{GameNumber}. For example, the first game of the 2020-2021 - season would be 2020020001. This is also the gamePk field that can be found in the team schedule endpoints. - - For playoffs the {GameNumber} portion will be formatted as RRMG where RR is the round (01, 02, 03, 04), - M is the matchup and G is the game out of 7. So 2022030412 is the 2022-2023 NHL season, 03 means playoffs - 04 means fourth round, 1 means matchup (I really cant 100% figure this out) - and 2 is the second game out of 7 - - {Season} is the first 4 digits of the season year, so for 20222023 it would be 2022. - - {GameType} are the following: 01=preseason, 02=regular season, 03=playoffs, 04=all-star. - - {GameNumber} is the game number in the season, starting at 0001. - :return: dict - """ - return self._get(resource=f"game/{game_id}/feed/live").json() - - def get_game_live_feed_diff_after_timestamp(self, game_id: Union[str, int], timestamp: str) -> dict: - """ - Returns the difference in the live feed game data, from since the given timestamp: param. - :param game_id: - :param timestamp: - :return: - """ - warnings.warn("This endpoint is still experimental and may not work as expected") - return self._get(resource=f"game/{game_id}/feed/live/diffPath").json() - - def get_game_boxscore(self, game_id: Union[str, int]) -> List[dict]: - """ - Less detail than get_game_live_feed() but still a large response, contains lots of information about - the game. - - See documentation for get_game_live_feed() for more verbose explanation of game_id. - :param game_id: - :return: - """ - return self._get(resource=f"game/{game_id}/boxscore").json() - - def get_game_linescore(self, game_id: Union[str, int]) -> dict: - """ - Returns the linescore for the game with the id supplied. - - See documentation for get_game_live_feed() for more verbose explanation of game_id. - - :param game_id: - :return: - """ - return self._get(resource=f"game/{game_id}/linescore").json() - - def get_game_content(self, game_id: Union[str, int]) -> dict: - """ - Returns the content for the game with the id supplied. Can contain links to videos, goals, shots, - headlines, description, etc. A very large response payload. - - See documentation for get_game_live_feed() for more verbose explanation of game_id. - - :param game_id: - :return: - """ - return self._get(resource=f"game/{game_id}/content").json() diff --git a/nhlpy/api/players.py b/nhlpy/api/players.py deleted file mode 100644 index 6f62fbf..0000000 --- a/nhlpy/api/players.py +++ /dev/null @@ -1,38 +0,0 @@ -from nhlpy.api import BaseNHLAPIClient - - -class Players(BaseNHLAPIClient): - def get_player(self, person_id: str) -> dict: - """ - Returns a player based on the person_id. - :param person_id: - :return: - """ - return self._get(resource=f"people/{person_id}").json()["people"] - - def get_player_stats(self, person_id: str, season: str = None, stat_type: str = "statsSingleSeason") -> dict: - """ - This returns a players statistics based on the param stat_type: and season: An example of this - may be client.players.get_player_stats(stat_type="yearByYear", season="20202021"). In some instances season: - does not matter, such as yearByYear. - :param person_id: int - Player ID - :param season: str - Season in format of 20202021 - :param stat_type: str - These can be accessed programmatically via get_player_stat_types() - or are limited to the following yearByYear, yearByYearRank, yearByYearPlayoffs, - yearByYearPlayoffsRank, careerRegularSeason, careerPlayoffs, gameLog, playoffGameLog, - vsTeam, vsTeamPlayoffs, vsDivision, vsDivisionPlayoffs, vsConference, vsConferencePlayoffs, - byMonth, byMonthPlayoffs, byDayOfWeek, byDayOfWeekPlayoffs, homeAndAway, homeAndAwayPlayoffs, - winLoss, winLossPlayoffs, onPaceRegularSeason, regularSeasonStatRankings, playoffStatRankings, - goalsByGameSituation, goalsByGameSituationPlayoffs, statsSingleSeason, statsSingleSeasonPlayoffs - - :return: - """ - query = f"stats={stat_type}" if stat_type else "" - return self._get(resource=f"people/{person_id}/stats?season={season}&{query}").json()["stats"] - - def get_player_stat_types(self) -> dict: - """ - Returns the full list of stat(types) that can be used in get_player_stats()'s stat_type param - :return: - """ - return self._get(resource="statTypes").json() diff --git a/nhlpy/nhl_client.py b/nhlpy/nhl_client.py index 137cb72..497054b 100644 --- a/nhlpy/nhl_client.py +++ b/nhlpy/nhl_client.py @@ -1,4 +1,4 @@ -from nhlpy.api import teams, standings, schedule +from nhlpy.api import teams, standings, schedule, game_center class NHLClient: @@ -8,14 +8,11 @@ class NHLClient: You can instantiate this class and then access the various endpoints of the API, such as: client = NHLClient() - client.teams.all() """ def __init__(self) -> None: - # self.core = core.Core() self.teams = teams.Teams() self.standings = standings.Standings() self.schedule = schedule.Schedule() - # self.players = players.Players() - # self.games = games.Games() + self.game_center = game_center.GameCenter() # self.helpers = helpers.Helpers() diff --git a/pyproject.toml b/pyproject.toml index 94f0126..b83b6f4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "nhl-api-py" -version = "2.0.1" +version = "2.0.2" description = "NHL API. For standings, team stats, outcomes, player information. Contains each individual API endpoint as well as convience methods for easy data loading in Pandas or any ML applications." authors = ["Corey Schaf "] readme = "README.md" diff --git a/tests/test_game_center.py b/tests/test_game_center.py new file mode 100644 index 0000000..7a1bbb4 --- /dev/null +++ b/tests/test_game_center.py @@ -0,0 +1,29 @@ +from unittest import mock + + +@mock.patch("httpx.get") +def test_boxscore(h_m, nhl_client): + nhl_client.game_center.boxscore(game_id="2020020001") + h_m.assert_called_once() + assert h_m.call_args[1]["url"] == "https://api-web.nhle.com/v1/gamecenter/2020020001/boxscore" + + +@mock.patch("httpx.get") +def test_play_by_play(h_m, nhl_client): + nhl_client.game_center.play_by_play(game_id="2020020001") + h_m.assert_called_once() + assert h_m.call_args[1]["url"] == "https://api-web.nhle.com/v1/gamecenter/2020020001/play-by-play" + + +@mock.patch("httpx.get") +def test_landing_page(h_m, nhl_client): + nhl_client.game_center.landing(game_id="2020020001") + h_m.assert_called_once() + assert h_m.call_args[1]["url"] == "https://api-web.nhle.com/v1/gamecenter/2020020001/landing" + + +@mock.patch("httpx.get") +def test_score_now(h_m, nhl_client): + nhl_client.game_center.score_now() + h_m.assert_called_once() + assert h_m.call_args[1]["url"] == "https://api-web.nhle.com/v1/score/now"