-
-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
QueryBuilder. Adds more filter support for positions, franchise, game…
… type. Test coverage update
- Loading branch information
Showing
16 changed files
with
292 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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.2.7" | ||
__version__ = "2.3.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,33 @@ | ||
from typing import List | ||
import logging | ||
|
||
from nhlpy.api.query.filters import QueryBase | ||
|
||
|
||
class QueryContext: | ||
def __init__(self, query: str, filters: List[QueryBase]): | ||
self.query_str = query | ||
self.filters = filters | ||
|
||
|
||
class QueryBuilder: | ||
pass | ||
def __init__(self, verbose: bool = False): | ||
self._verbose = verbose | ||
if self._verbose: | ||
logging.basicConfig(level=logging.INFO) | ||
|
||
def build(self, filters: List[QueryBase]) -> QueryContext: | ||
output: str = "" | ||
for f in filters: | ||
if not isinstance(f, QueryBase): | ||
if self._verbose: | ||
logging.info(f"Input filter is not of type QueryBase: {f.__name__}") | ||
|
||
continue | ||
|
||
_q = f.to_query() | ||
output += f"{_q} and " | ||
else: | ||
output = output[:-5] | ||
|
||
return QueryContext(query=output, filters=filters) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,5 +3,5 @@ | |
|
||
class QueryBase(ABC): | ||
@abstractmethod | ||
def to_query(self): | ||
def to_query(self) -> str: | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from nhlpy.api.query.builder import QueryBase | ||
|
||
|
||
class FranchiseQuery(QueryBase): | ||
def __init__(self, franchise_id: str): | ||
self.franchise_id = franchise_id | ||
self._franchise_q = "franchiseId" | ||
|
||
def to_query(self) -> str: | ||
return f"{self._franchise_q}={self.franchise_id}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from nhlpy.api.query.builder import QueryBase | ||
|
||
|
||
class GameTypeQuery(QueryBase): | ||
def __init__(self, game_type: str): | ||
self.game_type = game_type | ||
self._game_type_q = "gameTypeId" | ||
|
||
def to_query(self) -> str: | ||
return f"{self._game_type_q}={self.game_type}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from enum import Enum | ||
|
||
from nhlpy.api.query.builder import QueryBase | ||
|
||
|
||
class PositionTypes(str, Enum): | ||
ALL_FORWARDS = "F" | ||
CENTER = "C" | ||
LEFT_WING = "L" | ||
RIGHT_WING = "R" | ||
DEFENSE = "D" | ||
|
||
|
||
class PositionQuery(QueryBase): | ||
def __init__(self, position: PositionTypes): | ||
self.position = position | ||
self._position_q = "positionCode" | ||
|
||
def to_query(self) -> str: | ||
# All forwards require an OR clause | ||
if self.position == PositionTypes.ALL_FORWARDS: | ||
return ( | ||
f"({self._position_q}='{PositionTypes.LEFT_WING.value}' " | ||
f"or {self._position_q}='{PositionTypes.RIGHT_WING.value}' " | ||
f"or {self._position_q}='{PositionTypes.CENTER.value}')" | ||
) | ||
|
||
return f"{self._position_q}='{self.position.value}'" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,14 @@ | ||
from nhlpy.api.query.builder import QueryBase | ||
|
||
|
||
class ShootCatches(QueryBase): | ||
class ShootCatchesQuery(QueryBase): | ||
def __init__(self, shoot_catch: str): | ||
""" | ||
Shoot / catch filter. L or R, for both I believe its nothing. | ||
:param shoot_catch: L, R | ||
""" | ||
self.shoot_catch = shoot_catch | ||
self.shoot_catch_q = "shootsCatches" | ||
|
||
def to_query(self) -> str: | ||
return f"{self.shoot_catch_q}={self.shoot_catch}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" | |
|
||
[tool.poetry] | ||
name = "nhl-api-py" | ||
version = "2.2.7" | ||
version = "2.3.0" | ||
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 <[email protected]>"] | ||
readme = "README.md" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from nhlpy.api.query.filters.franchise import FranchiseQuery | ||
|
||
|
||
def test_franchise_query(): | ||
franchise_query = FranchiseQuery(franchise_id="1") | ||
assert franchise_query.to_query() == "franchiseId=1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from nhlpy.api.query.filters.game_type import GameTypeQuery | ||
|
||
|
||
def test_game_type_preseason(): | ||
game_type = GameTypeQuery(game_type="1") | ||
assert game_type.to_query() == "gameTypeId=1" | ||
|
||
|
||
def test_game_type_regular(): | ||
game_type = GameTypeQuery(game_type="2") | ||
assert game_type.to_query() == "gameTypeId=2" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
from nhlpy.api.query.filters.position import PositionQuery, PositionTypes | ||
|
||
|
||
def test_centers(): | ||
position = PositionQuery(position=PositionTypes.CENTER) | ||
assert position.to_query() == "positionCode='C'" | ||
|
||
|
||
def test_left_wings(): | ||
position = PositionQuery(position=PositionTypes.LEFT_WING) | ||
assert position.to_query() == "positionCode='L'" | ||
|
||
|
||
def test_right_wings(): | ||
position = PositionQuery(position=PositionTypes.RIGHT_WING) | ||
assert position.to_query() == "positionCode='R'" | ||
|
||
|
||
def test_forwards(): | ||
position = PositionQuery(position=PositionTypes.ALL_FORWARDS) | ||
assert position.to_query() == "(positionCode='L' or positionCode='R' or positionCode='C')" | ||
|
||
|
||
def test_defense(): | ||
position = PositionQuery(position=PositionTypes.DEFENSE) | ||
assert position.to_query() == "positionCode='D'" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from nhlpy.api.query.filters.shoot_catch import ShootCatchesQuery | ||
|
||
|
||
def test_shoot_catch_l(): | ||
shoot_catch = ShootCatchesQuery(shoot_catch="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" |
Oops, something went wrong.