├── .gitignore ├── LICENSE ├── README.md ├── circle.yml ├── fantasy_data ├── FantasyData.py └── __init__.py ├── requirements.txt ├── setup.cfg ├── setup.py └── tests ├── __init__.py ├── test_api.py └── test_nba.py /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | *~ 3 | *.py[cod] 4 | *.egg-info 5 | .env 6 | .coverage 7 | dist 8 | *.egg 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Fantasy Football Calculator 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fantasydata-python 2 | A Python wrapper around the Fantasy Data API. 3 | 4 | Currently support V3 of the FantasyData API. 5 | 6 | ## Example Usage 7 | ``` 8 | from fantasy_data.FantasyData import FantasyData 9 | fantasy_data = FantasyData("my_api_key") 10 | player = fantasy_data.get_player(732) 11 | print player 12 | {u'InjuryStartDate': None, u'FirstName': u'Matt', u'PlayerID': 732, u'LastName': u'Ryan', ....} 13 | 14 | ``` 15 | 16 | ## Supported Methods 17 | Not all of the FantasyData API is implemented yet. Pull requests welcome! 18 | 19 | ### NFL 20 | * `get_upcoming_season()` 21 | * `get_schedules_for_season(season, season_type="REG")` 22 | * `get_free_agents()` 23 | * `get_current_week()` 24 | * `get_team_roster_and_depth_charts(team_name)` 25 | * `get_players_game_stats_for_season_for_week(season, week, season_type="REG")` 26 | * `get_teams_active()` 27 | * `get_player(player_id)` 28 | * `get_projected_player_game_stats_by_player(season, week, player_id)` 29 | * `get_projected_player_game_stats_by_team(season, week, team)` 30 | * `get_projected_player_game_stats_by_week(season, week)` 31 | * `get_projected_fantasy_defense_game_stats_by_week(season, week)` 32 | * `get_player_season_projected_stats(season)` 33 | * `get_fantasy_defense_projections_by_season(season)` 34 | * `get_rotoballer_premium_news()` 35 | * `get_rotoballer_premium_news_by_date(date)` 36 | * `get_rotoballer_premium_news_by_player(player_id)` 37 | * `get_rotoballer_premium_news_by_team(team)` 38 | * `get_injuries(season, week)` 39 | * `get_injuries_by_team(season, week, team)` 40 | * `get_box_score_by_team(season, week, team)` 41 | * `get_bye_weeks(season)` 42 | 43 | ### NBA 44 | * `get_current_season()` 45 | * `get_games_by_season(season)` 46 | * `get_games_by_date(game_date)` 47 | * `get_players_game_stats_by_date(game_date)` 48 | * `get_team_game_stats_by_date(game_date)` 49 | * `get_standings(season)` 50 | * `get_teams_active()` 51 | 52 | ### Run tests 53 | To run tests, set an environment variable named FANTASYDATA_API_KEY like this: 54 | 55 | ```export FANTASYDATA_API_KEY=yourapikeyhere``` 56 | 57 | and for NBA tests: 58 | 59 | ```export FANTASYDATA_NBA_API_KEY=yourapikeyhere``` 60 | 61 | Then run the tests with: 62 | 63 | ```python setup.py test``` 64 | 65 | or for python 3: 66 | 67 | ```python3 setup.py test``` 68 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | override: 3 | - pip install -r requirements.txt 4 | test: 5 | override: 6 | - py.test tests 7 | 8 | -------------------------------------------------------------------------------- /fantasy_data/FantasyData.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | import requests 3 | from six.moves import urllib 4 | 5 | 6 | class FantasyDataError(Exception): 7 | def __init__(self, errorstr): 8 | self.errorstr = errorstr 9 | 10 | def __str__(self): 11 | return repr(self.errorstr) 12 | 13 | 14 | class FantasyDataBase(object): 15 | """ 16 | Base class for all Fantasy Data APIs 17 | """ 18 | _api_schema = "https://" 19 | _api_address = "api.fantasydata.net" # API hostname 20 | _api_key = None # api key for requests 21 | _get_params = None # request GET params with API key 22 | _headers = None # request additional headers 23 | _response_format = "json" # default response format 24 | 25 | def __init__(self, api_key): 26 | """ 27 | Object contructor. Set key for API requests 28 | """ 29 | self._api_key = api_key 30 | # uses six 31 | self._get_params = urllib.parse.urlencode({'subscription-key': api_key}) 32 | 33 | self._headers = { 34 | # Basic Authorization Sample 35 | # 'Authorization': 'Basic %s' % base64.encodestring('{username}:{password}'), 36 | } 37 | 38 | def _method_call(self, method, category, **kwargs): 39 | """ 40 | Call API method. Generate request. Parse response. Process errors 41 | `method` str API method url for request. Contains parameters 42 | `params` dict parameters for method url 43 | """ 44 | session = requests.Session() 45 | try: 46 | response = session.get("http://" + self._api_address) 47 | except requests.exceptions.ConnectionError: 48 | raise FantasyDataError('Error: Cannot connect to the FantasyData API') 49 | 50 | method = method.format(format=self._response_format, **kwargs) 51 | request_url = "/v3/{game_type}/{category}/{format}/{method}?{get_params}".format( 52 | game_type=self.game_type, 53 | category=category, 54 | format=self._response_format, 55 | method=method, 56 | get_params=self._get_params) 57 | response = session.get(self._api_schema + self._api_address + request_url, 58 | headers=self._headers) 59 | result = response.json() 60 | 61 | if isinstance(result, dict) and response.status_code: 62 | if response.status_code == 401: 63 | raise FantasyDataError('Error: Invalid API key') 64 | elif response.status_code == 200: 65 | # for NBA everything is ok here. 66 | pass 67 | else: 68 | raise FantasyDataError('Error: Failed to get response') 69 | 70 | return result 71 | 72 | 73 | class FantasyData(FantasyDataBase): 74 | """ 75 | Class provide Fantasy Data API calls (NFL) 76 | """ 77 | game_type = 'nfl' 78 | 79 | def get_upcoming_season(self): 80 | """ 81 | Year of the current NFL season, if we are in the mid-season. 82 | If we are in the off-season, then year of the next upcoming season. 83 | This value changes immediately after the Super Bowl. 84 | The earliest season for Fantasy data is 2001. The earliest season for Team data is 1985. 85 | """ 86 | result = self._method_call("UpcomingSeason", "stats") 87 | return int(result) 88 | 89 | def get_schedules_for_season(self, season, season_type="REG"): 90 | """ 91 | Game schedule for a specified season. 92 | """ 93 | try: 94 | season = int(season) 95 | if season_type not in ["REG", "PRE", "POST"]: 96 | raise ValueError 97 | except (ValueError, TypeError): 98 | raise FantasyDataError('Error: Invalid method parameters') 99 | 100 | season_param = "{0}{1}".format(season, season_type) 101 | result = self._method_call("Schedules/{season}", "stats", season=season_param) 102 | return result 103 | 104 | def get_free_agents(self): 105 | """ 106 | """ 107 | result = self._method_call("FreeAgents", "stats") 108 | return result 109 | 110 | def get_current_week(self): 111 | """ 112 | Number of the current week of the NFL season. 113 | This value usually changes on Tuesday nights or Wednesday mornings at midnight EST. 114 | Week number is an integer between 1 and 21 or the word current. 115 | Weeks 1 through 17 are regular season weeks. Weeks 18 through 21 are post-season weeks. 116 | """ 117 | result = self._method_call("CurrentWeek", "stats") 118 | return int(result) 119 | 120 | def get_team_roster_and_depth_charts(self, team_name): 121 | """ 122 | `team_name` str Team short name 123 | """ 124 | result = self._method_call("Players/{team}", "stats", team=team_name) 125 | return result 126 | 127 | def get_players_game_stats_for_season_for_week(self, season, week, season_type="REG"): 128 | """ 129 | Game stats for a specified season and week. 130 | `season` int 131 | `week` int 132 | `season_type` str Valid value one of ("REG", "PRE", "POST") 133 | """ 134 | try: 135 | season = int(season) 136 | week = int(week) 137 | if season_type not in ["REG", "PRE", "POST"]: 138 | raise ValueError 139 | except (TypeError, ValueError): 140 | raise FantasyDataError('Error: Invalid method parameters') 141 | 142 | season_param = "{0}{1}".format(season, season_type) 143 | result = self._method_call("PlayerGameStatsByWeek/{season}/{week}", "stats", season=season_param, week=week) 144 | return result 145 | 146 | def get_teams_active(self): 147 | """ 148 | Gets all active teams. 149 | """ 150 | result = self._method_call("Teams", "stats") 151 | return result 152 | 153 | def get_player(self, player_id): 154 | """ 155 | Player profile information for one specific player. 156 | `player_id` int 157 | """ 158 | result = self._method_call("Player/{player_id}", "stats", player_id=player_id) 159 | return result 160 | 161 | def get_projected_player_game_stats_by_player(self, season, week, player_id): 162 | """ 163 | Projected Player Game Stats by Player 164 | """ 165 | result = self._method_call("PlayerGameProjectionStatsByPlayerID/{season}/{week}/{player_id}", "projections", season=season, week=week, player_id=player_id) 166 | return result 167 | 168 | def get_projected_player_game_stats_by_team(self, season, week, team_id): 169 | """ 170 | Projected Player Game Stats by Team 171 | """ 172 | result = self._method_call("PlayerGameProjectionStatsByTeam/{season}/{week}/{team_id}", "projections", season=season, week=week, team_id=team_id) 173 | return result 174 | 175 | def get_projected_player_game_stats_by_week(self, season, week): 176 | """ 177 | Projected Player Game Stats by Week 178 | """ 179 | result = self._method_call("PlayerGameProjectionStatsByWeek/{season}/{week}", "projections", season=season, week=week) 180 | return result 181 | 182 | def get_projected_fantasy_defense_game_stats_by_week(self, season, week): 183 | """ 184 | Projected Fantasy Defense Game Stats by Week 185 | """ 186 | result = self._method_call("FantasyDefenseProjectionsByGame/{season}/{week}", "projections", season=season, week=week) 187 | return result 188 | 189 | def get_player_season_projected_stats(self, season): 190 | """ 191 | Projected Stats By Player By Season 192 | """ 193 | result = self._method_call("PlayerSeasonProjectionStats/{season}", "projections", season=season) 194 | return result 195 | 196 | def get_fantasy_defense_projections_by_season(self, season): 197 | """ 198 | Projected Fantasy Defense Projections By Season 199 | """ 200 | result = self._method_call("FantasyDefenseProjectionsBySeason/{season}", "projections", season=season) 201 | return result 202 | 203 | def get_rotoballer_premium_news(self): 204 | """ 205 | RotoBaller Premium News 206 | """ 207 | result = self._method_call("RotoBallerPremiumNews", "news-rotoballer") 208 | return result 209 | 210 | def get_rotoballer_premium_news_by_date(self, date): 211 | """ 212 | RotoBaller Premium News By Date 213 | Date format: 2017-JUL-31 214 | """ 215 | result = self._method_call("RotoBallerPremiumNewsByDate/{date}", "news-rotoballer", date=date) 216 | return result 217 | 218 | def get_rotoballer_premium_news_by_player(self, player_id): 219 | """ 220 | RotoBaller Premium News By Player ID 221 | """ 222 | result = self._method_call("RotoBallerPremiumNewsByPlayerID/{player_id}", "news-rotoballer", player_id=player_id) 223 | return result 224 | 225 | def get_rotoballer_premium_news_by_team(self, team_id): 226 | """ 227 | RotoBaller Premium News By Team ID 228 | """ 229 | result = self._method_call("RotoBallerPremiumNewsByTeam/{team_id}", "news-rotoballer", team_id=team_id) 230 | return result 231 | 232 | def get_injuries(self, season, week): 233 | """ 234 | Injuries by week 235 | """ 236 | result = self._method_call("Injuries/{season}/{week}", "stats", season=season, week=week) 237 | return result 238 | 239 | def get_injuries_by_team(self, season, week, team_id): 240 | """ 241 | Injuries by week and team 242 | """ 243 | result = self._method_call("Injuries/{season}/{week}/{team_id}", "stats", season=season, week=week, team_id=team_id) 244 | return result 245 | 246 | def get_box_score_by_team(self, season, week, team_id): 247 | """ 248 | Box score by week and team 249 | """ 250 | result = self._method_call("BoxScoreV3/{season}/{week}/{team_id}", "stats", season=season, week=week, team_id=team_id) 251 | return result 252 | 253 | def get_bye_weeks(self, season): 254 | """ 255 | Bye weeks 256 | """ 257 | result = self._method_call("Byes/{season}", "stats", season=season) 258 | return result 259 | 260 | class FantasyDataNBA(FantasyDataBase): 261 | """ 262 | Class provide Fantasy Data API calls (NFL) 263 | """ 264 | game_type = 'nba' 265 | 266 | def get_current_season(self): 267 | """ 268 | Year of the current NBA season. 269 | The year is the year of the playoffs. 270 | I.e. result=2016 is 2015/2016 271 | """ 272 | result = self._method_call("CurrentSeason", "stats") 273 | return int(result.get('Season')) 274 | 275 | def get_games_by_season(self, season): 276 | """ 277 | Game schedule for a specified season. 278 | """ 279 | try: 280 | season = int(season) 281 | except ValueError: 282 | raise FantasyDataError('Error: Invalid method parameters') 283 | 284 | result = self._method_call("Games/{season}", "stats", season=season) 285 | return result 286 | 287 | def get_games_by_date(self, game_date): 288 | """ 289 | Game schedule for a specified day. 290 | """ 291 | result = self._method_call("GamesByDate/{game_date}", "scores", game_date=game_date) 292 | return result 293 | 294 | def get_players_game_stats_by_date(self, game_date): 295 | """ 296 | Game stats for each player at a specified date. 297 | """ 298 | result = self._method_call("PlayerGameStatsByDate/{game_date}", "stats", game_date=game_date) 299 | return result 300 | 301 | def get_team_game_stats_by_date(self, game_date): 302 | """ 303 | Game stats for each team at a specified date. 304 | """ 305 | result = self._method_call("TeamGameStatsByDate/{game_date}", "stats", game_date=game_date) 306 | return result 307 | 308 | def get_standings(self, season): 309 | """ 310 | Get standings for season 311 | """ 312 | result = self._method_call("Standings/{season}", "stats", season=season) 313 | return result 314 | 315 | def get_teams_active(self): 316 | """ 317 | Gets all active teams. 318 | """ 319 | result = self._method_call("Teams", "stats") 320 | return result 321 | 322 | def get_stadiums(self): 323 | """ 324 | Get all stadiums. 325 | """ 326 | result = self._method_call("Stadiums") 327 | return result 328 | -------------------------------------------------------------------------------- /fantasy_data/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leftbrainsports/fantasydata-python/af90cac1e80d8356cffaa80621ee513201f6c661/fantasy_data/__init__.py -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pytest 2 | mock 3 | pytest-cov 4 | six 5 | requests 6 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | import sys 3 | from distutils.core import setup 4 | 5 | from setuptools.command.test import test as TestCommand 6 | 7 | 8 | class PyTest(TestCommand): 9 | user_options = [('pytest-args=', 'a', "Arguments to pass to py.test")] 10 | 11 | def initialize_options(self): 12 | TestCommand.initialize_options(self) 13 | self.pytest_args = [] 14 | 15 | def finalize_options(self): 16 | TestCommand.finalize_options(self) 17 | self.test_args = ['tests/'] 18 | self.test_suite = True 19 | 20 | def run_tests(self): 21 | #import here, cause outside the eggs aren't loaded 22 | import pytest 23 | errno = pytest.main(self.pytest_args) 24 | sys.exit(errno) 25 | 26 | 27 | setup( 28 | name='fantasy_data', 29 | version='2.1.4', 30 | description='FantasyData Python', 31 | author='Fantasy Football Calculator', 32 | author_email='support@fantasyfootballcalculator.com', 33 | url='https://fantasyfootballcalculator.com/fantasydata-python', 34 | packages=['fantasy_data'], 35 | keywords=['fantasy', 'sports', 'football', 'nba'], 36 | install_requires=[ 37 | "requests", 38 | "six", 39 | ], 40 | tests_require=['pytest'], 41 | cmdclass = {'test': PyTest}, 42 | download_url='https://github.com/ffcalculator/fantasydata-python/archive/v2.1.4.tar.gz' 43 | ) 44 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leftbrainsports/fantasydata-python/af90cac1e80d8356cffaa80621ee513201f6c661/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_api.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | import datetime 3 | import os 4 | import six 5 | 6 | import pytest 7 | 8 | from fantasy_data.FantasyData import FantasyData, FantasyDataError 9 | 10 | 11 | @pytest.fixture(scope="module") 12 | def api_key(): 13 | """ 14 | """ 15 | return os.environ.get('FANTASYDATA_API_KEY') 16 | 17 | 18 | @pytest.fixture(scope="module") 19 | def season(): 20 | """ 21 | Season for calls which use season in parameters 22 | """ 23 | return 2014 24 | 25 | 26 | @pytest.fixture(scope="module") 27 | def team(): 28 | """ 29 | Team short name for API calls 30 | """ 31 | return "WAS" 32 | 33 | 34 | @pytest.fixture(scope="module") 35 | def week(): 36 | """ 37 | Week number for API calls 38 | """ 39 | return 5 40 | 41 | 42 | class TestFantasyData: 43 | """ 44 | """ 45 | def test_get_upcoming_season_api_is_unavailable(self): 46 | """ 47 | API is unavailable 48 | 49 | Given 50 | The FantasyData API is not available over the network 51 | A valid API key 52 | When 53 | I call get_upcoming_season() on a FantasyData object 54 | Then 55 | It throws an exception stating "Error: Cannot connect to the FantasyData API" 56 | """ 57 | invalid_api_key = 'invalid api key' 58 | with pytest.raises(FantasyDataError): 59 | FantasyData(invalid_api_key).get_upcoming_season() 60 | 61 | def test_get_upcoming_season_invalid_api_key(self): 62 | """ 63 | Invalid API key 64 | 65 | Given 66 | The FantasyData API is available 67 | A invalid API key 68 | When 69 | I call get_upcoming_season() on a FantasyData object 70 | Then 71 | It throws an exception stating "Error: Invalid API key" 72 | """ 73 | invalid_api_key = 'invalid api key' 74 | with pytest.raises(FantasyDataError): 75 | FantasyData(invalid_api_key).get_upcoming_season() 76 | 77 | def test_get_upcoming_season(self, api_key): 78 | """ 79 | API call get_upcoming_season 80 | """ 81 | assert isinstance(FantasyData(api_key).get_upcoming_season(), int), "Invalid value type" 82 | 83 | def test_get_current_week(self, api_key): 84 | """ 85 | API call get_current_week 86 | """ 87 | assert isinstance(FantasyData(api_key).get_current_week(), int), "Invalid value type" 88 | 89 | def test_get_schedules_for_season(self, api_key, season): 90 | """ 91 | API call get_schedules_for_season. 92 | Test response type and items structure 93 | """ 94 | response = FantasyData(api_key).get_schedules_for_season(season) 95 | 96 | assert isinstance(response, list), "response not list" 97 | assert len(response), "response empty list" 98 | 99 | # item = response[0] 100 | required_fields = {"AwayTeam", "Channel", "Date", "HomeTeam", "OverUnder", "PointSpread", "Season", "Week"} 101 | for item in response: 102 | item_keys = set(map(str, item.keys())) 103 | assert item_keys & required_fields == required_fields, "incorrect structure in response item" 104 | 105 | item["Date"] and self._check_date(item["Date"], "unexpected type of key 'Date'") 106 | assert isinstance(item["AwayTeam"], six.text_type), "unexpected type of key 'AwayTeam'" 107 | assert item["Channel"] is None or isinstance(item["Channel"], six.text_type), "unexpected type of key 'Channel'" 108 | assert isinstance(item["HomeTeam"], six.text_type), "unexpected type of key 'HomeTeam'" 109 | assert item["OverUnder"] is None or isinstance(item["OverUnder"], (float, int)), "unexpected type of key 'OverUnder'" 110 | assert item["PointSpread"] is None or isinstance(item["PointSpread"], (float, int)), "unexpected type of key 'PointSpread'" 111 | assert isinstance(item["Season"], int), "unexpected type of key 'Season'" 112 | assert isinstance(item["Week"], int), "unexpected type of key 'Week'" 113 | 114 | def test_get_team_roster_and_depth_charts(self, api_key, team): 115 | """ 116 | API call get_team_roster_and_depth_charts 117 | Test response type and items structure 118 | """ 119 | response = FantasyData(api_key).get_team_roster_and_depth_charts(team) 120 | 121 | assert isinstance(response, list), "response not list" 122 | assert len(response), "response empty list" 123 | 124 | # item = response[0] 125 | required_fields = {"Active", "Age", "AverageDraftPosition", "BirthDate", "BirthDateString", "ByeWeek", 126 | "College", "DepthDisplayOrder", "DepthOrder", "DepthPosition", "DepthPositionCategory", 127 | "Experience", "ExperienceString", "FantasyPosition", "FirstName", "Height", "InjuryStatus", 128 | "LastName", "LatestNews", "Name", "Number", "PhotoUrl", "PlayerID", "Position", 129 | "PositionCategory", "ShortName", "Status", "Team", "UpcomingGameOpponent", 130 | "UpcomingGameWeek", "Weight", "PlayerSeason"} 131 | for item in response: 132 | item_keys = set(map(str, item.keys())) 133 | assert item_keys & required_fields == required_fields, "incorrect structure in response item" 134 | 135 | item["BirthDate"] and self._check_date(item["BirthDate"], "unexpected type of key 'BirthDate'") 136 | assert isinstance(item["Active"], bool), "unexpected type of key 'Active'" 137 | assert item["Age"] is None or isinstance(item["Age"], int), "unexpected type of key 'Age'" 138 | assert item["BirthDateString"] is None or isinstance(item["BirthDateString"], six.text_type), "unexpected type of key 'BirthDateString'" 139 | assert isinstance(item["ByeWeek"], int), "unexpected type of key 'ByeWeek'" 140 | assert isinstance(item["College"], six.text_type), "unexpected type of key 'College'" 141 | assert isinstance(item["Experience"], int), "unexpected type of key 'Experience'" 142 | assert isinstance(item["ExperienceString"], six.text_type), "unexpected type of key 'ExperienceString'" 143 | assert isinstance(item["FantasyPosition"], six.text_type), "unexpected type of key 'FantasyPosition'" 144 | assert isinstance(item["FirstName"], six.text_type), "unexpected type of key 'FirstName'" 145 | assert item["Height"] is None or isinstance(item["Height"], six.text_type), "unexpected type of key 'Height'" 146 | assert isinstance(item["LastName"], six.text_type), "unexpected type of key 'LastName'" 147 | assert isinstance(item["LatestNews"], list), "unexpected type of key 'LatestNews'" 148 | assert isinstance(item["Name"], six.text_type), "unexpected type of key 'Name'" 149 | assert item["Number"] is None or isinstance(item["Number"], int), "unexpected type of key 'Number'" 150 | assert isinstance(item["PhotoUrl"], six.text_type), "unexpected type of key 'PhotoUrl'" 151 | assert isinstance(item["PlayerID"], int), "unexpected type of key 'PlayerID'" 152 | assert item["PlayerSeason"] is None or isinstance(item["PlayerSeason"], dict), "unexpected type of key 'PlayerSeason'" 153 | assert isinstance(item["Position"], six.text_type), "unexpected type of key 'Position'" 154 | assert isinstance(item["PositionCategory"], six.text_type), "unexpected type of key 'PositionCategory'" 155 | assert isinstance(item["ShortName"], six.text_type), "unexpected type of key 'ShortName'" 156 | assert isinstance(item["Status"], six.text_type), "unexpected type of key 'Status'" 157 | assert isinstance(item["Team"], six.text_type), "unexpected type of key 'Team'" 158 | assert isinstance(item["UpcomingGameOpponent"], six.text_type), "unexpected type of key 'UpcomingGameOpponent'" 159 | assert isinstance(item["UpcomingGameWeek"], int), "unexpected type of key 'UpcomingGameWeek'" 160 | assert item["Weight"] is None or isinstance(item["Weight"], int), "unexpected type of key 'Weight'" 161 | 162 | def test_get_players_game_stats_for_season_for_week(self, api_key, season, week): 163 | """ 164 | API call players_game_stats_for_season_for_week 165 | Test response type and items structure 166 | """ 167 | response = FantasyData(api_key).get_players_game_stats_for_season_for_week(season, week) 168 | 169 | assert isinstance(response, list), "response not list" 170 | assert len(response), "response empty list" 171 | 172 | # item = response[0] 173 | required_fields = {"Started", "Week", "Stadium", "ShortName", "Name", "HomeOrAway", "PlayerGameID", "GameDate", 174 | "Played", "IsGameOver", "GameKey", "Position", "PlayerID", "Opponent", "Team", "SeasonType", 175 | "Season", "ScoringDetails"} 176 | for item in response: 177 | item_keys = set(map(str, item.keys())) 178 | assert item_keys & required_fields == required_fields, "incorrect structure in response item" 179 | 180 | self._check_date(item["GameDate"], "unexpected type of key 'GameDate'") 181 | assert isinstance(item["ScoringDetails"], list), "unexpected type of key 'ScoringDetails'" 182 | assert isinstance(item["Started"], int), "unexpected type of key 'Started'" 183 | assert isinstance(item["Week"], int), "unexpected type of key 'Week'" 184 | assert isinstance(item["Stadium"], six.text_type), "unexpected type of key 'Stadium'" 185 | assert isinstance(item["ShortName"], six.text_type), "unexpected type of key 'ShortName'" 186 | assert isinstance(item["Name"], six.text_type), "unexpected type of key 'Name'" 187 | assert isinstance(item["HomeOrAway"], six.text_type), "unexpected type of key 'HomeOrAway'" 188 | assert isinstance(item["PlayerGameID"], int), "unexpected type of key 'PlayerGameID'" 189 | assert isinstance(item["Played"], int), "unexpected type of key 'Played'" 190 | assert isinstance(item["IsGameOver"], bool), "unexpected type of key 'IsGameOver'" 191 | assert isinstance(item["GameKey"], six.text_type), "unexpected type of key 'GameKey'" 192 | assert isinstance(item["Position"], six.text_type), "unexpected type of key 'Position'" 193 | assert isinstance(item["PlayerID"], int), "unexpected type of key 'PlayerID'" 194 | assert isinstance(item["Opponent"], six.text_type), "unexpected type of key 'Opponent'" 195 | assert isinstance(item["Team"], six.text_type), "unexpected type of key 'Team'" 196 | assert isinstance(item["SeasonType"], int), "unexpected type of key 'SeasonType'" 197 | assert isinstance(item["Season"], int), "unexpected type of key 'Season'" 198 | 199 | def test_get_free_agents(self, api_key): 200 | """ 201 | API call get_free_agents 202 | Test response type and items structure 203 | """ 204 | response = FantasyData(api_key).get_free_agents() 205 | 206 | assert isinstance(response, list), "response not list" 207 | assert len(response), "response empty list" 208 | 209 | # item = response[0] 210 | required_fields = {"Active", "Age", "AverageDraftPosition", "BirthDate", "BirthDateString", "ByeWeek", 211 | "College", "DepthDisplayOrder", "DepthOrder", "DepthPosition", "DepthPositionCategory", 212 | "Experience", "ExperienceString", "FantasyPosition", "FirstName", "Height", "InjuryStatus", 213 | "LastName", "LatestNews", "Name", "Number", "PhotoUrl", "PlayerID", "PlayerSeason", 214 | "Position", "PositionCategory", "ShortName", "Status", "Team", "UpcomingGameOpponent", 215 | "UpcomingGameWeek", "Weight"} 216 | for item in response: 217 | item_keys = set(map(str, item.keys())) 218 | assert item_keys & required_fields == required_fields, "incorrect structure in response item" 219 | 220 | item["BirthDate"] and self._check_date(item["BirthDate"], "unexpected type of key 'BirthDate'") 221 | assert isinstance(item["Active"], bool), "unexpected type of key 'Active'" 222 | assert item["Age"] is None or isinstance(item["Age"], int), "unexpected type of key 'Age'" 223 | assert item["BirthDateString"] is None or isinstance(item["BirthDateString"], six.text_type), "unexpected type of key 'BirthDateString'" 224 | assert item["College"] is None or isinstance(item["College"], six.text_type), "unexpected type of key 'College'" 225 | assert item["Experience"] is None or isinstance(item["Experience"], int), "unexpected type of key 'Experience'" 226 | assert item["ExperienceString"] is None or isinstance(item["ExperienceString"], six.text_type), "unexpected type of key 'ExperienceString'" 227 | assert isinstance(item["FantasyPosition"], six.text_type), "unexpected type of key 'FantasyPosition'" 228 | assert isinstance(item["FirstName"], six.text_type), "unexpected type of key 'FirstName'" 229 | assert item["Height"] is None or isinstance(item["Height"], six.text_type), "unexpected type of key 'Height'" 230 | assert isinstance(item["LastName"], six.text_type), "unexpected type of key 'LastName'" 231 | assert isinstance(item["LatestNews"], list), "unexpected type of key 'LatestNews'" 232 | assert isinstance(item["Name"], six.text_type), "unexpected type of key 'Name'" 233 | assert isinstance(item["Number"], int), "unexpected type of key 'Number'" 234 | assert isinstance(item["PhotoUrl"], six.text_type), "unexpected type of key 'PhotoUrl'" 235 | assert isinstance(item["PlayerID"], int), "unexpected type of key 'PlayerID'" 236 | assert isinstance(item["Position"], six.text_type), "unexpected type of key 'Position'" 237 | assert isinstance(item["PositionCategory"], six.text_type), "unexpected type of key 'PositionCategory'" 238 | assert isinstance(item["ShortName"], six.text_type), "unexpected type of key 'ShortName'" 239 | assert isinstance(item["Status"], six.text_type), "unexpected type of key 'Status'" 240 | assert isinstance(item["Team"], six.text_type), "unexpected type of key 'Team'" 241 | assert item["Weight"] is None or isinstance(item["Weight"], int), "unexpected type of key 'Weight'" 242 | 243 | def test_get_teams_active(self, api_key): 244 | """ 245 | API call get_current_week 246 | """ 247 | response = FantasyData(api_key).get_teams_active() 248 | 249 | assert isinstance(response, list), "response not list" 250 | assert len(response), "response empty list" 251 | 252 | assert isinstance(response[0]["City"], six.text_type), "unexpected type of key 'City'" 253 | 254 | def _check_date(self, value, error_msg): 255 | """ 256 | Check date value. Parse datetime or throw assert exception 257 | """ 258 | datetime.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S") 259 | -------------------------------------------------------------------------------- /tests/test_nba.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | import datetime 3 | import os 4 | import six 5 | 6 | import pytest 7 | 8 | from fantasy_data.FantasyData import FantasyDataNBA, FantasyDataError 9 | 10 | 11 | @pytest.fixture(scope="module") 12 | def api_key(): 13 | """ 14 | use different key for NBA 15 | """ 16 | return os.environ.get('FANTASYDATA_NBA_API_KEY') 17 | 18 | 19 | @pytest.fixture(scope="module") 20 | def season(): 21 | """ 22 | """ 23 | return 2016 24 | 25 | 26 | @pytest.fixture(scope="module") 27 | def game_date(): 28 | """ 29 | """ 30 | return "2015-12-05" 31 | 32 | 33 | class TestFantasyData: 34 | """ 35 | """ 36 | def test_get_current_season_api_is_unavailable(self): 37 | """ 38 | API is unavailable 39 | 40 | Given 41 | The FantasyData API is not available over the network 42 | A valid API key 43 | When 44 | I call get_current_season() on a FantasyData object 45 | Then 46 | It throws an exception stating "Error: Cannot connect to the FantasyData API" 47 | """ 48 | invalid_api_key = 'invalid api key' 49 | with pytest.raises(FantasyDataError): 50 | FantasyDataNBA(invalid_api_key).get_current_season() 51 | 52 | def test_get_current_season_invalid_api_key(self): 53 | """ 54 | Invalid API key 55 | 56 | Given 57 | The FantasyData API is available 58 | A invalid API key 59 | When 60 | I call get_current_season() on a FantasyData object 61 | Then 62 | It throws an exception stating "Error: Invalid API key" 63 | """ 64 | invalid_api_key = 'invalid api key' 65 | with pytest.raises(FantasyDataError): 66 | FantasyDataNBA(invalid_api_key).get_current_season() 67 | 68 | def test_get_current_season(self, api_key): 69 | """ 70 | API call get_current_season 71 | """ 72 | assert isinstance(FantasyDataNBA(api_key).get_current_season(), int), "Invalid value type" 73 | 74 | def test_get_games_by_season(self, api_key, season): 75 | """ 76 | API call get_schedules_for_season. 77 | Test response type and items structure 78 | """ 79 | response = FantasyDataNBA(api_key).get_games_by_season(season) 80 | assert isinstance(response, list), "response not list" 81 | assert len(response), "response empty list" 82 | 83 | # item = response[0] 84 | required_fields = {"AwayTeam", "Status", "DateTime", "HomeTeam", "OverUnder", "PointSpread", "Season", "Day"} 85 | for item in response: 86 | item_keys = set(map(str, item.keys())) 87 | assert item_keys & required_fields == required_fields, "incorrect structure in response item" 88 | 89 | item["DateTime"] and self._check_date(item["DateTime"], "unexpected type of key 'DateTime'") 90 | assert isinstance(item["AwayTeam"], six.text_type), "unexpected type of key 'AwayTeam'" 91 | assert isinstance(item["Status"], six.text_type), "unexpected type of key 'Status'" 92 | assert isinstance(item["HomeTeam"], six.text_type), "unexpected type of key 'HomeTeam'" 93 | assert item["OverUnder"] is None or isinstance(item["OverUnder"], (float, int)), "unexpected type of key 'OverUnder'" 94 | assert item["PointSpread"] is None or isinstance(item["PointSpread"], (float, int)), "unexpected type of key 'PointSpread'" 95 | assert isinstance(item["Season"], int), "unexpected type of key 'Season'" 96 | 97 | def test_get_games_by_date(self, api_key, game_date): 98 | response = FantasyDataNBA(api_key).get_games_by_date(game_date) 99 | 100 | assert isinstance(response, list), "response not list" 101 | assert len(response), "response empty list" 102 | 103 | assert isinstance(response[0]["StadiumID"], int), "unexpected type of key 'StadiumID'" 104 | 105 | def test_get_player_game_stats_by_date(self, api_key, game_date): 106 | response = FantasyDataNBA(api_key).get_players_game_stats_by_date(game_date) 107 | 108 | assert isinstance(response, list), "response not list" 109 | assert len(response), "response empty list" 110 | 111 | assert isinstance(response[0]["GameID"], int), "unexpected type of key 'GameID'" 112 | assert isinstance(response[0]["PlayerID"], int), "unexpected type of key 'PlayerID'" 113 | assert isinstance(response[0]["Name"], six.text_type), "unexpected type of key 'name'" 114 | 115 | def test_get_team_game_stats_by_date(self, api_key, game_date): 116 | response = FantasyDataNBA(api_key).get_team_game_stats_by_date(game_date) 117 | 118 | assert isinstance(response, list), "response not list" 119 | assert len(response), "response empty list" 120 | 121 | assert isinstance(response[0]["GameID"], int), "unexpected type of key 'GameID'" 122 | assert isinstance(response[0]["TeamID"], int), "unexpected type of key 'TeamID'" 123 | assert isinstance(response[0]["Name"], six.text_type), "unexpected type of key 'name'" 124 | 125 | def test_get_standings(self, api_key, season): 126 | response = FantasyDataNBA(api_key).get_standings(season) 127 | 128 | assert isinstance(response, list), "response not list" 129 | assert len(response), "response empty list" 130 | 131 | assert isinstance(response[0]["TeamID"], int), "unexpected type of key 'TeamID'" 132 | assert isinstance(response[0]["Name"], six.text_type), "unexpected type of key 'name'" 133 | assert isinstance(response[0]["Wins"], int), "unexpected type of key 'Wins'" 134 | assert isinstance(response[0]["Losses"], int), "unexpected type of key 'Losses'" 135 | 136 | def test_get_teams_active(self, api_key): 137 | response = FantasyDataNBA(api_key).get_teams_active() 138 | 139 | assert isinstance(response, list), "response not list" 140 | assert len(response), "response empty list" 141 | 142 | assert isinstance(response[0]["City"], six.text_type), "unexpected type of key 'City'" 143 | 144 | def test_get_stadiums(self, api_key): 145 | response = FantasyDataNBA(api_key).get_stadiums() 146 | 147 | assert isinstance(response, list), "response not list" 148 | assert len(response), "response empty list" 149 | 150 | assert isinstance(response[0]["City"], six.text_type), "unexpected type of key 'City'" 151 | assert isinstance(response[0]["StadiumID"], int), "unexpected type of key 'StadiumID'" 152 | assert isinstance(response[0]["Capacity"], int), "unexpected type of key 'Capacity'" 153 | 154 | def _check_date(self, value, error_msg): 155 | """ 156 | Check date value. Parse datetime or throw assert exception 157 | """ 158 | datetime.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S") 159 | --------------------------------------------------------------------------------