From 1993bffde4c51811d6feafa9cfe7018389f8483d Mon Sep 17 00:00:00 2001 From: Corey Schaf Date: Fri, 8 Nov 2024 15:07:44 -0500 Subject: [PATCH] Fix: ShootCatchQuery - Filter now properly serializes L or R values. (#78) * Fix: ShootCatchQuery - Filter now properly serializes L or R values. - Fixes test for this change. - Refactors goalie default sorts into init. * patch increase --- .github/workflows/python-app.yml | 2 +- README.md | 2 +- nhlpy/api/query/filters/__init__.py | 60 +++++++++++++++++++++++- nhlpy/api/query/filters/shoot_catch.py | 2 +- nhlpy/api/stats.py | 61 ++----------------------- pyproject.toml | 2 +- tests/query/filters/test_shoot_catch.py | 4 +- 7 files changed, 68 insertions(+), 65 deletions(-) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index de3ad7c..734e622 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -13,7 +13,7 @@ permissions: contents: read jobs: - test: + test-ruff-black: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/README.md b/README.md index 8489a8a..a5de49f 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ filters = [ ShootCatchesQuery(shoot_catch="L"), HomeRoadQuery(home_road="H"), FranchiseQuery(franchise_id="1"), - StatusQuery(is_active=True) #for active players OR for HOF players StatusQuery(is_hall_of_fame=True), + StatusQuery(is_active=True),#for active players OR for HOF players StatusQuery(is_hall_of_fame=True), OpponentQuery(opponent_franchise_id="2"), ExperienceQuery(is_rookie=True), # for rookies || ExperienceQuery(is_rookie=False) #for veteran DecisionQuery(decision="W") # OR DecisionQuery(decision="L") OR DecisionQuery(decision="O") diff --git a/nhlpy/api/query/filters/__init__.py b/nhlpy/api/query/filters/__init__.py index 43cd8a6..e09a59b 100644 --- a/nhlpy/api/query/filters/__init__.py +++ b/nhlpy/api/query/filters/__init__.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from typing import Union +from typing import Union, List class QueryBase(ABC): @@ -10,3 +10,61 @@ def to_query(self) -> str: @abstractmethod def validate(self) -> Union[bool, None]: return True + + +def _goalie_stats_sorts(report: str) -> List[dict]: + """ + This is default criteria for sorting on goalie stats. I hate this method + :param report: + :return: + """ + if report == "summary": + return [ + {"property": "wins", "direction": "DESC"}, + {"property": "gamesPlayed", "direction": "ASC"}, + {"property": "playerId", "direction": "ASC"}, + ] + elif report == "advanced": + return [ + {"property": "qualityStart", "direction": "DESC"}, + {"property": "goalsAgainstAverage", "direction": "ASC"}, + {"property": "playerId", "direction": "ASC"}, + ] + elif report == "bios": + return [ + {"property": "lastName", "direction": "ASC_CI"}, + {"property": "goalieFullName", "direction": "ASC_CI"}, + {"property": "playerId", "direction": "ASC"}, + ] + elif report == "daysrest": + return [ + {"property": "wins", "direction": "DESC"}, + {"property": "savePct", "direction": "DESC"}, + {"property": "playerId", "direction": "ASC"}, + ] + elif report == "penaltyShots": + return [ + {"property": "penaltyShotsSaves", "direction": "DESC"}, + {"property": "penaltyShotSavePct", "direction": "DESC"}, + {"property": "playerId", "direction": "ASC"}, + ] + elif report == "savesByStrength": + return [ + {"property": "wins", "direction": "DESC"}, + {"property": "savePct", "direction": "DESC"}, + {"property": "playerId", "direction": "ASC"}, + ] + elif report == "shootout": + return [ + {"property": "shootoutWins", "direction": "DESC"}, + {"property": "shootoutSavePct", "direction": "DESC"}, + {"property": "playerId", "direction": "ASC"}, + ] + elif report == "startedVsRelieved": + return [ + {"property": "gamesStarted", "direction": "DESC"}, + {"property": "gamesStartedSavePct", "direction": "DESC"}, + {"property": "playerId", "direction": "ASC"}, + ] + else: + return [{}] diff --git a/nhlpy/api/query/filters/shoot_catch.py b/nhlpy/api/query/filters/shoot_catch.py index 88ba473..857caa0 100644 --- a/nhlpy/api/query/filters/shoot_catch.py +++ b/nhlpy/api/query/filters/shoot_catch.py @@ -13,7 +13,7 @@ def __init__(self, shoot_catch: str): self.shoot_catch_q = "shootsCatches" def to_query(self) -> str: - return f"{self.shoot_catch_q}={self.shoot_catch}" + return f"{self.shoot_catch_q}='{self.shoot_catch}'" def validate(self) -> Union[bool, None]: return True diff --git a/nhlpy/api/stats.py b/nhlpy/api/stats.py index 421d0bd..855ff37 100644 --- a/nhlpy/api/stats.py +++ b/nhlpy/api/stats.py @@ -3,6 +3,7 @@ from typing import List from nhlpy.api.query.builder import QueryContext +from nhlpy.api.query.filters import _goalie_stats_sorts from nhlpy.api.query.sorting.sorting_options import SortingOptions from nhlpy.http_client import HttpClient @@ -11,63 +12,6 @@ class Stats: def __init__(self, http_client: HttpClient): self.client = http_client - def _goalie_stats_sorts(self, report: str) -> List[dict]: - """ - This is default criteria for sorting on goalie stats. I hate this method. Ill fix it soon. - :param report: - :return: - """ - if report == "summary": - return [ - {"property": "wins", "direction": "DESC"}, - {"property": "gamesPlayed", "direction": "ASC"}, - {"property": "playerId", "direction": "ASC"}, - ] - elif report == "advanced": - return [ - {"property": "qualityStart", "direction": "DESC"}, - {"property": "goalsAgainstAverage", "direction": "ASC"}, - {"property": "playerId", "direction": "ASC"}, - ] - elif report == "bios": - return [ - {"property": "lastName", "direction": "ASC_CI"}, - {"property": "goalieFullName", "direction": "ASC_CI"}, - {"property": "playerId", "direction": "ASC"}, - ] - elif report == "daysrest": - return [ - {"property": "wins", "direction": "DESC"}, - {"property": "savePct", "direction": "DESC"}, - {"property": "playerId", "direction": "ASC"}, - ] - elif report == "penaltyShots": - return [ - {"property": "penaltyShotsSaves", "direction": "DESC"}, - {"property": "penaltyShotSavePct", "direction": "DESC"}, - {"property": "playerId", "direction": "ASC"}, - ] - elif report == "savesByStrength": - return [ - {"property": "wins", "direction": "DESC"}, - {"property": "savePct", "direction": "DESC"}, - {"property": "playerId", "direction": "ASC"}, - ] - elif report == "shootout": - return [ - {"property": "shootoutWins", "direction": "DESC"}, - {"property": "shootoutSavePct", "direction": "DESC"}, - {"property": "playerId", "direction": "ASC"}, - ] - elif report == "startedVsRelieved": - return [ - {"property": "gamesStarted", "direction": "DESC"}, - {"property": "gamesStartedSavePct", "direction": "DESC"}, - {"property": "playerId", "direction": "ASC"}, - ] - else: - return [{}] - def club_stats_season(self, team_abbr: str) -> dict: """ This seems to return gameTypes for every season the team was in existence. Maybe its useful? @@ -317,7 +261,8 @@ def goalie_stats_summary_simple( end_season = start_season if not sort_expr: - sort_expr = self._goalie_stats_sorts(stats_type) + sort_expr = _goalie_stats_sorts(report=stats_type) + q_params["sort"] = urllib.parse.quote(json.dumps(sort_expr)) if not default_cayenne_exp: diff --git a/pyproject.toml b/pyproject.toml index cde3e4a..aa67fb8 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.12.1" +version = "2.12.2" description = "NHL API (Updated for 2024/2025) and EDGE Stats. For standings, team stats, outcomes, player information. Contains each individual API endpoint as well as convience methods as well as pythonic query builder for more indepth EDGE stats." authors = ["Corey Schaf "] readme = "README.md" diff --git a/tests/query/filters/test_shoot_catch.py b/tests/query/filters/test_shoot_catch.py index b4faf79..2a682e3 100644 --- a/tests/query/filters/test_shoot_catch.py +++ b/tests/query/filters/test_shoot_catch.py @@ -3,9 +3,9 @@ def test_shoot_catch_l(): shoot_catch = ShootCatchesQuery(shoot_catch="L") - assert shoot_catch.to_query() == "shootsCatches=L" + assert shoot_catch.to_query() == "shootsCatches='L'" def test_shoot_catch_r(): shoot_catch = ShootCatchesQuery(shoot_catch="R") - assert shoot_catch.to_query() == "shootsCatches=R" + assert shoot_catch.to_query() == "shootsCatches='R'"