├── docs ├── league.md ├── player.md ├── team.md └── index.md ├── requirements.txt ├── AUTHORS.txt ├── oauth.json.enc ├── fantasy_sport ├── __init__.py ├── utils.py ├── roster.py └── fantasy_sport.py ├── run_tests.sh ├── mkdocs.yml ├── dev_requirements.txt ├── .travis.yml ├── .gitignore ├── README.rst ├── LICENSE ├── README.md ├── setup.py └── tests.py /docs/league.md: -------------------------------------------------------------------------------- 1 | ## League 2 | -------------------------------------------------------------------------------- /docs/player.md: -------------------------------------------------------------------------------- 1 | ## Player 2 | -------------------------------------------------------------------------------- /docs/team.md: -------------------------------------------------------------------------------- 1 | ## Team 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | yahoo-oauth==0.1.4 2 | six==1.9.0 3 | -------------------------------------------------------------------------------- /AUTHORS.txt: -------------------------------------------------------------------------------- 1 | Josue Kouka - josuebrunel@gmail.com 2 | Paul Singman - 3 | -------------------------------------------------------------------------------- /oauth.json.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josuebrunel/yahoo-fantasy-sport/HEAD/oauth.json.enc -------------------------------------------------------------------------------- /fantasy_sport/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from fantasy_sport.fantasy_sport import FantasySport 4 | from fantasy_sport.roster import Player, Roster 5 | from fantasy_sport import utils 6 | -------------------------------------------------------------------------------- /run_tests.sh: -------------------------------------------------------------------------------- 1 | if [ ! -z $1 ]; then 2 | TestCase=".${1}" 3 | else 4 | TestCase='' 5 | fi 6 | 7 | if [ ! -z $2 ]; then 8 | Test=".${2}" 9 | else 10 | Test='' 11 | fi 12 | 13 | coverage run --source=fantasy_sport -m unittest tests$TestCase$Test 14 | coverage report 15 | 16 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: Yahoo Fantasy Sport 2 | repo_url: https://github.com/josuebrunel/yahoo-fantasy-sport 3 | site_url: http://yahoo-fantasy-sport.readthedocs.org/en/latest/ 4 | site_description: Yahoo Fantasy Sport Python Wrapper 5 | site_author: Josue Kouka 6 | pages: 7 | - Home : index.md 8 | - Team : team.md 9 | - League : league.md 10 | - Player : player.md 11 | theme: readthedocs 12 | -------------------------------------------------------------------------------- /dev_requirements.txt: -------------------------------------------------------------------------------- 1 | Jinja2==2.7.3 2 | Markdown==2.6.2 3 | MarkupSafe==0.23 4 | PyYAML==3.11 5 | argparse==1.2.1 6 | backports.ssl-match-hostname==3.4.0.2 7 | certifi==2015.04.28 8 | click==4.0 9 | distribute==0.6.24 10 | livereload==2.4.0 11 | mkdocs==0.14.0 12 | myql==1.2.3 13 | oauthlib==0.7.2 14 | rauth==0.7.1 15 | requests==2.7.0 16 | requests-oauthlib==0.5.0 17 | six==1.9.0 18 | tornado==4.2 19 | yahoo-oauth==0.1.4 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - '2.7' 4 | - '3.2' 5 | - '3.3' 6 | - '3.4' 7 | - pypy 8 | - pypy3 9 | install: 10 | - pip install -r requirements.txt 11 | - pip install coverage coveralls 12 | script: 13 | - coverage run --source=fantasy_sport -m unittest discover 14 | after_success: 15 | - coverage report 16 | - coveralls 17 | before_install: 18 | - openssl aes-256-cbc -K $encrypted_aa858aa3cffd_key -iv $encrypted_aa858aa3cffd_iv 19 | -in oauth.json.enc -out oauth.json -d 20 | -------------------------------------------------------------------------------- /fantasy_sport/utils.py: -------------------------------------------------------------------------------- 1 | import json 2 | from xml.dom import minidom 3 | 4 | 5 | def pretty_json(data): 6 | """Return a pretty formatted json 7 | """ 8 | data = json.loads(data.decode('utf-8')) 9 | return json.dumps(data, indent=4, sort_keys=True) 10 | 11 | 12 | def pretty_xml(data): 13 | """Return a pretty formated xml 14 | """ 15 | parsed_string = minidom.parseString(data.decode('utf-8')) 16 | return parsed_string.toprettyxml(indent='\t', encoding='utf-8') 17 | 18 | 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .coverage.* 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | *,cover 45 | 46 | # Translations 47 | *.mo 48 | *.pot 49 | 50 | # Django stuff: 51 | *.log 52 | 53 | # Sphinx documentation 54 | docs/_build/ 55 | 56 | # PyBuilder 57 | target/ 58 | 59 | oauth.json 60 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Yahoo Fantasy Sport API 2 | ======================= 3 | 4 | `|Build 5 | Status| `_ 6 | `|Coverage 7 | Status| `_ 8 | `|Code 9 | Health| `_ 10 | 11 | Authors 12 | ------- 13 | 14 | - `Josue Kouka `_ 15 | - `Paul Singman `_ 16 | 17 | Quickstart 18 | ---------- 19 | 20 | :: 21 | 22 | How to contribute 23 | ----------------- 24 | 25 | - Open an issue 26 | - Fork the repository 27 | - Make your changes 28 | - Test your changes 29 | - Add yourself to the AUTHORS.txt file 30 | - Submit a pull request 31 | 32 | .. |Build 33 | Status| image:: https://travis-ci.org/josuebrunel/yahoo-fantasy-sport.svg?branch=master 34 | .. |Coverage 35 | Status| image:: https://coveralls.io/repos/josuebrunel/yahoo-fantasy-sport/badge.svg?branch=master 36 | .. |Code 37 | Health| image:: https://landscape.io/github/josuebrunel/yahoo-fantasy-sport/master/landscape.svg?style=flat 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Josue Kouka 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 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Yahoo Fantasy Sport API 2 | 3 | [![Build Status](https://travis-ci.org/josuebrunel/yahoo-fantasy-sport.svg?branch=master)](https://travis-ci.org/josuebrunel/yahoo-fantasy-sport) 4 | [![Coverage Status](https://coveralls.io/repos/josuebrunel/yahoo-fantasy-sport/badge.svg?branch=master)](https://coveralls.io/r/josuebrunel/yahoo-fantasy-sport?branch=master) 5 | [![Code Health](https://landscape.io/github/josuebrunel/yahoo-fantasy-sport/master/landscape.svg?style=flat)](https://landscape.io/github/josuebrunel/yahoo-fantasy-sport/master) 6 | 7 | ## Authors 8 | 9 | * [Josue Kouka](https://github.com/josuebrunel) 10 | * [Paul Singman](https://github.com/unpairestgood) 11 | 12 | ## Quickstart 13 | 14 | ```python 15 | >>> from yahoo_oauth import OAuth1 16 | >>> oauth = OAuth1(None, None, from_file='oauth.json') 17 | >>> from fantasy_sport import FantasySport 18 | >>> yfs = FantasySport(oauth, fmt='json') 19 | ``` 20 | 21 | ### Games Resources 22 | 23 | ### Leagues Resources 24 | 25 | ### Players Resources 26 | 27 | ## How to contribute 28 | 29 | - Open an issue 30 | - Fork the repository 31 | - Make your changes 32 | - Test your changes 33 | - Add yourself into the AUTHORS.txt file 34 | - Submit a pull request 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Yahoo Fantasy Sport API 2 | 3 | [![Build Status](https://travis-ci.org/josuebrunel/yahoo-fantasy-sport.svg?branch=master)](https://travis-ci.org/josuebrunel/yahoo-fantasy-sport) 4 | [![Documentation Status](https://readthedocs.org/projects/yahoo-fantasy-sport/badge/?version=latest)](https://readthedocs.org/projects/yahoo-fantasy-sport/?badge=latest) 5 | [![Coverage Status](https://coveralls.io/repos/josuebrunel/yahoo-fantasy-sport/badge.svg?branch=master)](https://coveralls.io/r/josuebrunel/yahoo-fantasy-sport?branch=master) 6 | [![Code Health](https://landscape.io/github/josuebrunel/yahoo-fantasy-sport/master/landscape.svg?style=flat)](https://landscape.io/github/josuebrunel/yahoo-fantasy-sport/master) 7 | 8 | ## Authors 9 | 10 | * [Josue Kouka](https://github.com/josuebrunel) 11 | * [Paul Singman](https://github.com/unpairestgood) 12 | 13 | ## Installation 14 | 15 | ```shell 16 | $ pip install yahoo-fantasy-sport 17 | ``` 18 | 19 | ## Quickstart 20 | 21 | ```python 22 | >>> from yahoo_oauth import OAuth1 23 | >>> oauth = OAuth1(None, None, from_file='oauth.json', base_url='http://fantasysports.yahooapis.com/fantasy/v2/') 24 | >>> from fantasy_sport import FantasySport 25 | >>> yfs = FantasySport(oauth, fmt='json') 26 | ``` 27 | 28 | ### Games Resources 29 | 30 | ### Leagues Resources 31 | 32 | ### Players Resources 33 | 34 | ## How to contribute 35 | 36 | - Open an issue 37 | - Fork the repository 38 | - Make your changes 39 | - Test your changes 40 | - Add yourself into the AUTHORS.txt file 41 | - Submit a pull request 42 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | from setuptools import setup, find_packages 3 | 4 | __author__ = 'Josue Kouka' 5 | __email__ = 'josuebrunel@gmail.com' 6 | __version__ = "0.1.1" 7 | 8 | #requirements.txt 9 | with open('requirements.txt') as f: 10 | required = f.read().splitlines() 11 | 12 | def read(fname): 13 | return open(os.path.join(os.path.dirname(__file__), fname)).read() 14 | 15 | setup( 16 | name = "yahoo-fantasy-sports", 17 | version = __version__, 18 | description = "Python Yahoo Fantasy Sports Wrapper", 19 | long_description = read("README.rst"), 20 | author = __author__, 21 | author_email = __email__, 22 | url = "https://github.com/josuebrunel/yahoo-fantasy-sport", 23 | download_url = "https://github.com/josuebrunel/myql/archive/{0}.tar.gz".format(__version__), 24 | keywords = ['fantasy sports', 'yahoo'], 25 | packages = find_packages(), 26 | tests_suite="tests", 27 | classifiers = [ 28 | 'Programming Language :: Python', 29 | 'Programming Language :: Python :: 2', 30 | 'Programming Language :: Python :: 2.7', 31 | 'Programming Language :: Python :: 3', 32 | 'Programming Language :: Python :: 3.2', 33 | 'Programming Language :: Python :: 3.3', 34 | 'Programming Language :: Python :: 3.4', 35 | 'Programming Language :: Python :: Implementation :: CPython', 36 | 'Programming Language :: Python :: Implementation :: PyPy', 37 | 'Development Status :: 5 - Production/Stable', 38 | 'Topic :: Software Development :: Libraries :: Python Modules', 39 | 'Environment :: Console', 40 | 'Intended Audience :: Developers', 41 | 'License :: OSI Approved :: MIT License' 42 | ], 43 | platforms=['Any'], 44 | license='MIT', 45 | install_requires = required 46 | ) 47 | -------------------------------------------------------------------------------- /fantasy_sport/roster.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, unicode_literals 2 | 3 | import six 4 | import abc 5 | import json 6 | 7 | from xml.etree import cElementTree as ctree 8 | 9 | @six.add_metaclass(abc.ABCMeta) 10 | class Base(object): 11 | """Base class for Roster and Player 12 | """ 13 | 14 | @abc.abstractmethod 15 | def xml_builder(self,): 16 | raise NotImplementedError 17 | 18 | @abc.abstractmethod 19 | def json_builder(self,): 20 | raise NotImplementedError 21 | 22 | def to_json(self,): 23 | """Return object as a json string 24 | """ 25 | return json.dumps(self.json, ensure_ascii=True).encode('ascii') 26 | 27 | def to_xml(self,): 28 | """Return object as a xml string 29 | """ 30 | return ctree.tostring(self.xml) 31 | 32 | 33 | class Roster(Base): 34 | """Roster class 35 | """ 36 | 37 | def __init__(self, players, week=None, date=None): 38 | """Initialize a roster class 39 | """ 40 | super(Base, self).__init__() 41 | 42 | self.players = players 43 | 44 | if week: 45 | self.coverage = week 46 | self.coverage_type = 'week' 47 | else: 48 | self.coverage = date 49 | self.coverage_type = 'date' 50 | 51 | self.json_builder() 52 | self.xml_builder() 53 | 54 | def xml_builder(self,): 55 | """Convert object to xml 56 | """ 57 | content = ctree.Element('fantasy_content') 58 | roster = ctree.SubElement(content, 'roster') 59 | 60 | coverage_type = ctree.SubElement(roster, 'coverage_type') 61 | coverage_type.text = self.coverage_type 62 | 63 | coverage = ctree.SubElement(roster, self.coverage_type) 64 | coverage.text = self.coverage 65 | 66 | players = ctree.SubElement(roster, 'players') 67 | for player in self.players : 68 | players.append(player.xml) 69 | 70 | self.xml = content 71 | 72 | def json_builder(self,): 73 | """Convert object to json 74 | """ 75 | self.json = { 76 | 'fantasy_content':{ 77 | 'roster':{ 78 | 'coverage_type': self.coverage_type, 79 | self.coverage_type : self.coverage, 80 | 'players': [ player.json for player in self.players ] 81 | } 82 | } 83 | } 84 | return self.json 85 | 86 | 87 | class Player(Base): 88 | """player class 89 | - player_key 90 | - position 91 | """ 92 | 93 | def __init__(self, player_key, position): 94 | """Initialize a player object 95 | """ 96 | super(Base, self).__init__() 97 | 98 | self.player_key = player_key 99 | self.position = position 100 | self.xml_builder() 101 | self.json_builder() 102 | 103 | def xml_builder(self,): 104 | """Convert object into a xml object 105 | """ 106 | player = ctree.Element('player') 107 | for key in sorted(vars(self).keys()): 108 | tag = ctree.SubElement(player, key) 109 | tag.text = vars(self).get(key) 110 | 111 | self.xml = player 112 | return self.xml 113 | 114 | def json_builder(self, ): 115 | """Kind of convert object to json 116 | """ 117 | self.json = { 118 | 'player_key': self.player_key, 119 | 'position': self.position 120 | } 121 | 122 | return self.json 123 | 124 | -------------------------------------------------------------------------------- /tests.py: -------------------------------------------------------------------------------- 1 | import pdb 2 | import json 3 | import logging 4 | import unittest 5 | 6 | from xml.etree import cElementTree as ctree 7 | 8 | from yahoo_oauth import OAuth1 9 | 10 | from fantasy_sport import FantasySport 11 | from fantasy_sport.roster import Player, Roster 12 | from fantasy_sport.utils import pretty_json, pretty_xml 13 | 14 | logging.getLogger('yahoo_oauth').setLevel(logging.WARNING) 15 | 16 | logging.basicConfig(level=logging.DEBUG,format="[%(asctime)s %(levelname)s] [%(name)s.%(module)s.%(funcName)s] %(message)s \n") 17 | logging.getLogger('test-fantasy-sports') 18 | 19 | class TestFantasySportGame(unittest.TestCase): 20 | 21 | def setUp(self,): 22 | oauth = OAuth1(None, None, from_file='oauth.json',base_url='http://fantasysports.yahooapis.com/fantasy/v2/') 23 | self.yfs = FantasySport(oauth) 24 | 25 | def test_get_games_info(self,): 26 | response = self.yfs.get_games_info(['346']) 27 | #response = self.yfs.get_games_info(['nfl']) 28 | #logging.debug(pretty_json(response.content)) 29 | self.assertEqual(response.status_code, 200) 30 | 31 | def test_get_games_withleague(self,): 32 | response = self.yfs.get_games_info(['328'], leagues='328.l.56628') 33 | self.assertEqual(response.status_code, 200) 34 | #logging.debug(pretty_json(response.content)) 35 | 36 | def test_get_games_withplayer(self,): 37 | response = self.yfs.get_games_info(['328'], players='328.p.8180') 38 | self.assertEqual(response.status_code, 200) 39 | #logging.debug(pretty_json(response.content)) 40 | 41 | def test_get_games_with_login_teams(self,): 42 | self.yfs.use_login = True 43 | response = self.yfs.get_games_info(['346'], teams=True) 44 | self.yfs.use_login = False 45 | self.assertEqual(response.status_code, 200) 46 | #logging.debug(pretty_json(response.content)) 47 | 48 | def test_get_games_info_with_login(self,): 49 | self.yfs.use_login = True 50 | response = self.yfs.get_games_info(['mlb']) 51 | self.yfs.use_login = False 52 | #logging.debug(pretty_json(response.content)) 53 | self.assertEqual(response.status_code, 200) 54 | 55 | class TestFantasySportLeague(unittest.TestCase): 56 | 57 | def setUp(self,): 58 | oauth = OAuth1(None, None, from_file='oauth.json',base_url='http://fantasysports.yahooapis.com/fantasy/v2/') 59 | self.yfs = FantasySport(oauth) 60 | 61 | def test_get_leagues(self): 62 | response = self.yfs.get_leagues(['346.l.1328']) 63 | self.assertEqual(response.status_code, 200) 64 | #logging.debug(pretty_json(response.content)) 65 | 66 | def test_get_leagues_with_multiple_keys(self,): 67 | self.yfs.fmt = 'xml' 68 | response = self.yfs.get_leagues(('238.l.627060','238.l.627062')) 69 | self.yfs.fmt = 'json' 70 | self.assertEqual(response.status_code, 200) 71 | #logging.debug(pretty_xml(response.content)) 72 | 73 | def test_get_leagues_scoreboard(self): 74 | response = self.yfs.get_leagues_scoreboard(['238.l.627060']) 75 | self.assertEqual(response.status_code, 200) 76 | #logging.debug(pretty_json(response.content)) 77 | 78 | def test_get_leagues_scoreboard_week_2(self): 79 | response = self.yfs.get_leagues_scoreboard(['238.l.178574'], week=2) 80 | self.assertEqual(response.status_code, 200) 81 | #logging.debug(pretty_json(response.content)) 82 | 83 | def test_get_leagues_settings(self): 84 | response = self.yfs.get_leagues_settings(['238.l.627060','238.l.627062']) 85 | self.assertEqual(response.status_code, 200) 86 | #logging.debug(pretty_json(response.content)) 87 | 88 | def test_get_leagues_standings(self): 89 | response = self.yfs.get_leagues_standings(['346.l.1328']) 90 | self.assertEqual(response.status_code, 200) 91 | #logging.debug(pretty_json(response.content)) 92 | 93 | def test_get_leagues_standings_withteam_androsterplayers(self): 94 | response = self.yfs.get_leagues_standings(['346.l.1328'], teams='roster', players='ownership') 95 | self.assertEqual(response.status_code, 200) 96 | #logging.debug(pretty_json(response.content)) 97 | 98 | def test_get_leagues_transactions(self): 99 | response = self.yfs.get_leagues_transactions(['238.l.627060','238.l.627062']) 100 | self.assertEqual(response.status_code, 200) 101 | #logging.debug(pretty_json(response.content)) 102 | 103 | def test_get_leagues_teams(self,): 104 | response = self.yfs.get_leagues_teams(['238.l.627060']) 105 | self.assertEqual(response.status_code, 200) 106 | #logging.debug(pretty_json(response.content)) 107 | 108 | def test_get_leagues_draftresults(self,): 109 | response = self.yfs.get_leagues_draftresults(['238.l.627060']) 110 | self.assertEqual(response.status_code, 200) 111 | #logging.debug(pretty_json(response.content)) 112 | 113 | def test_get_collections(self,): 114 | response = self.yfs.get_collections('leagues;league_keys', ['238.l.627060','238.l.627062'],['settings','standings']) 115 | #logging.debug(pretty_json(response.content)) 116 | self.assertEqual(response.status_code, 200) 117 | 118 | class TestFantasySportPlayer(unittest.TestCase): 119 | 120 | def setUp(self,): 121 | oauth = OAuth1(None, None, from_file='oauth.json',base_url='http://fantasysports.yahooapis.com/fantasy/v2/') 122 | self.yfs = FantasySport(oauth) 123 | 124 | def test_get_players(self,): 125 | response = self.yfs.get_players(['223.p.5479']) 126 | #logging.debug(pretty_json(response.content)) 127 | self.assertEqual(response.status_code, 200) 128 | 129 | def test_get_playerswithfilter(self,): 130 | response = self.yfs.get_players(['346.p.8180', '346.p.8544'], filters='position=P') 131 | #logging.debug(pretty_json(response.content)) 132 | self.assertEqual(response.status_code, 200) 133 | 134 | def test_get_players_stats(self,): 135 | response = self.yfs.get_players_stats(['223.p.5479'], week=3) 136 | #logging.debug(pretty_json(response.content)) 137 | self.assertEqual(response.status_code, 200) 138 | 139 | def test_get_players_draft_analysis(self,): 140 | response = self.yfs.get_players_draft_analysis(['44.p.6619']) 141 | #logging.debug(pretty_json(response.content)) 142 | self.assertEqual(response.status_code, 200) 143 | 144 | def test_get_players_percent_owned(self,): 145 | response = self.yfs.get_players_percent_owned(['253.p.6619']) 146 | #logging.debug(pretty_json(response.content)) 147 | self.assertEqual(response.status_code, 200) 148 | 149 | class TestFantasySportTeam(unittest.TestCase): 150 | 151 | def setUp(self,): 152 | oauth = OAuth1(None, None, from_file='oauth.json',base_url='http://fantasysports.yahooapis.com/fantasy/v2/') 153 | self.yfs = FantasySport(oauth) 154 | 155 | def test_get_teams(self,): 156 | response = self.yfs.get_teams(['346.l.1328.t.12']) 157 | #logging.debug(pretty_json(response.content)) 158 | self.assertEqual(response.status_code, 200) 159 | 160 | def test_get_teams_players(self,): 161 | response = self.yfs.get_teams_players(['346.l.1328.t.12']) 162 | #logging.debug(pretty_json(response.content)) 163 | self.assertEqual(response.status_code, 200) 164 | 165 | def test_get_teams_stats(self,): 166 | response = self.yfs.get_teams_stats(['238.l.627062.t.1'], week=10) 167 | #logging.debug(pretty_json(response.content)) 168 | self.assertEqual(response.status_code, 200) 169 | 170 | def test_get_teams_standings(self,): 171 | response = self.yfs.get_teams_standings(['346.l.1328.t.12']) 172 | #logging.debug(pretty_json(response.content)) 173 | self.assertEqual(response.status_code, 200) 174 | 175 | def test_get_teams_roster(self,): 176 | response = self.yfs.get_teams_roster(['346.l.1328.t.12']) 177 | #logging.debug(pretty_json(response.content)) 178 | self.assertEqual(response.status_code, 200) 179 | 180 | #def test_get_teams_roster_with_filter(self,): 181 | # response = self.yfs.get_teams_roster(['346.l.1328.t.12'], players='draft_analysis', filters='position=3B') 182 | # #logging.debug(pretty_json(response.content)) 183 | # self.assertEqual(response.status_code, 200) 184 | 185 | def test_get_teams_roster_week(self,): 186 | response = self.yfs.get_teams_roster(['223.l.431.t.9'], week=1) 187 | #logging.debug(pretty_json(response.content)) 188 | self.assertEqual(response.status_code, 200) 189 | 190 | def test_get_teams_roster_weekplayer(self,): 191 | response = self.yfs.get_teams_roster(['223.l.431.t.9'], week=1, players='draft_analysis') 192 | #logging.debug(pretty_json(response.content)) 193 | self.assertEqual(response.status_code, 200) 194 | 195 | def test_get_teams_roster_players(self,): 196 | response = self.yfs.get_teams_roster(['346.l.1328.t.12'], players='draft_analysis') 197 | #logging.debug(pretty_json(response.content)) 198 | self.assertEqual(response.status_code, 200) 199 | 200 | def test_get_teams_roster_filter(self,): 201 | response = self.yfs.get_teams_roster(['346.l.1328.t.12'], filters='position=3B') 202 | #logging.debug(pretty_json(response.content)) 203 | self.assertEqual(response.status_code, 200) 204 | 205 | def test_get_teams_draftresults(self,): 206 | response = self.yfs.get_teams_draftresults(['346.l.1328.t.12']) 207 | #logging.debug(pretty_json(response.content)) 208 | self.assertEqual(response.status_code, 200) 209 | 210 | def test_get_teams_matchups(self,): 211 | response = self.yfs.get_teams_matchups(['238.l.627062.t.1'], weeks=['1,2']) 212 | #logging.debug(pretty_json(response.content)) 213 | self.assertEqual(response.status_code, 200) 214 | 215 | class TestFantasySportRoster(unittest.TestCase): 216 | 217 | def setUp(self,): 218 | oauth = OAuth1(None, None, from_file='oauth.json', base_url='http://fantasysports.yahooapis.com/fantasy/v2/') 219 | self.yfs = FantasySport(oauth) 220 | 221 | def test_get_roster_players(self,): 222 | response = self.yfs.get_roster_players(['346.l.1328.t.12']) 223 | #logging.debug(pretty_json(response.content)) 224 | self.assertEqual(response.status_code, 200) 225 | 226 | def test_get_roster_players_by_week(self,): 227 | response = self.yfs.get_roster_players(['346.l.1328.t.12'], week=10) 228 | #logging.debug(pretty_json(response.content)) 229 | self.assertEqual(response.status_code, 200) 230 | 231 | def test_get_roster_players_by_date(self,): 232 | response = self.yfs.get_roster_players(['346.l.1328.t.12'], date='2011-05-01') 233 | #logging.debug(pretty_json(response.content)) 234 | self.assertEqual(response.status_code, 200) 235 | 236 | #def test_set_roster_players(self,): 237 | # response = self.yfs.set_roster_players(['346.l.1328.t.12']) 238 | # self.assertEqual(response.status_code, 200) 239 | 240 | 241 | class TestFantasySportTransaction(unittest.TestCase): 242 | 243 | def setUp(self,): 244 | oauth = OAuth1(None, None, from_file='oauth.json',base_url='http://fantasysports.yahooapis.com/fantasy/v2/') 245 | self.yfs = FantasySport(oauth) 246 | 247 | def test_get_transactions(self,): 248 | response = self.yfs.get_transactions(['346.l.1328.tr.100'], players='draft_analysis') 249 | #logging.debug(pretty_json(response.content)) 250 | self.assertEqual(response.status_code, 200) 251 | 252 | 253 | class TestPlayer(unittest.TestCase): 254 | 255 | def setUp(self,): 256 | self.player = Player('242.p.8332','WR') 257 | 258 | def test_player_in_xml(self,): 259 | expected = b'242.p.8332WR' 260 | logging.debug(pretty_xml(self.player.to_xml())) 261 | self.assertEqual(expected, self.player.to_xml()) 262 | 263 | def test_player_in_json(self,): 264 | expected = {"player_key": "242.p.8332","position":"WR"} 265 | logging.debug(pretty_json(self.player.to_json())) 266 | self.assertEqual(expected, self.player.json) 267 | 268 | 269 | class TestRoster(unittest.TestCase): 270 | 271 | def setUp(self,): 272 | players = [Player('242.p.8332', 'WR'), Player('242.p.8334','LR')] 273 | self.roster = Roster(players, date='2015-01-01') 274 | 275 | def test_roster_in_json(self,): 276 | expected = { 277 | 'fantasy_content': { 278 | 'roster': { 279 | 'coverage_type':'date', 280 | 'date':'2015-01-01', 281 | 'players':[ 282 | {"player_key": "242.p.8332","position":"WR"}, 283 | {"player_key": "242.p.8334","position":"LR"} 284 | ] 285 | } 286 | } 287 | } 288 | logging.debug(pretty_json(self.roster.to_json())) 289 | self.assertEqual(expected, self.roster.json) 290 | 291 | def test_roster_in_xml(self,): 292 | expected = b'date2015-01-01242.p.8332WR242.p.8334LR' 293 | logging.debug(pretty_xml(self.roster.to_xml())) 294 | self.assertEqual(expected, self.roster.to_xml()) 295 | -------------------------------------------------------------------------------- /fantasy_sport/fantasy_sport.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | 4 | class FantasySport(object): 5 | """FantasySport Class 6 | """ 7 | 8 | url = 'http://fantasysports.yahooapis.com/fantasy/v2/' 9 | 10 | def __init__(self, oauth, fmt=None, use_login=False): 11 | """Initialize a FantasySport object 12 | """ 13 | self.oauth = oauth 14 | self.fmt = 'json' if not fmt else fmt # JSON as default format 15 | self.use_login = use_login 16 | 17 | 18 | def __repr__(self,): 19 | return "<{0}> <{1}>".format(self.url, self.fmt) 20 | 21 | def _check_token_validity(self,): 22 | """Check wether or not the access token is still valid, if not, renews it 23 | """ 24 | if not self.oauth.token_is_valid(): 25 | self.oauth.refresh_access_token 26 | return True 27 | 28 | def _get(self, uri): 29 | """ 30 | """ 31 | 32 | if not self.oauth.oauth.base_url : 33 | self.oauth.oauth.base_url = self.url 34 | 35 | self._check_token_validity() 36 | 37 | response = self.oauth.session.get(uri, params={'format': self.fmt}) 38 | 39 | return response 40 | 41 | def _put(self, uri, roster): 42 | """ 43 | - uri : roster resource uri 44 | - roster : roster object 45 | """ 46 | headers = {'Content-Type':'application/{0}'.format(self.fmt)} 47 | data = roster.to_json() if self.fmt == 'json' else roster.to_xml() # Getting roster xml or json according to self.fmt 48 | 49 | response = self.oauth.session.put(uri, data=data, headers=headers) 50 | 51 | 52 | def _add_login(self, uri): 53 | """Add users;use_login=1/ to the uri 54 | """ 55 | uri = "users;use_login=1/{0}".format(uri) 56 | 57 | return uri 58 | 59 | def _format_resources_key(self, keys): 60 | """Format resources keys 61 | """ 62 | return ','.join(str(e) for e in keys) 63 | 64 | def _build_uri(self, resources, keys, sub=None): 65 | """Build uri 66 | """ 67 | if resources: 68 | uri = "{0}={1}".format(resources, self._format_resources_key(keys)) 69 | else: 70 | uri = '{0}'.format(self._format_resources_key(keys)) 71 | 72 | if sub and isinstance(sub, str) : 73 | uri += "/{0}".format(sub) 74 | if sub and not isinstance(sub, str): 75 | uri += ";out={0}".format(','.join([e for e in sub])) 76 | 77 | if self.use_login: 78 | uri = self._add_login(uri) 79 | 80 | return uri 81 | 82 | def get_collections(self, resource_type, resource_ids, sub_resources): 83 | """Generic method to get collections 84 | """ 85 | uri = self._build_uri(resource_type, resource_ids, sub=sub_resources) 86 | response = self._get(uri) 87 | return response 88 | 89 | ################################# 90 | # 91 | # GAMES 92 | # 93 | ################################# 94 | 95 | def get_games_info(self, game_keys, leagues=None, teams=False, players=None): 96 | """Return game info 97 | >>> yfs.get_games_info('mlb') 98 | Must set use_login to True to pull teams data 99 | """ 100 | uri = self._build_uri('games;game_keys', game_keys) 101 | 102 | if leagues: 103 | uri += '/leagues;league_keys={0}'.format(leagues) 104 | 105 | if teams: 106 | uri += '/teams' 107 | 108 | if players: 109 | uri += '/players;player_keys={0}'.format(players) 110 | 111 | response = self._get(uri) 112 | 113 | return response 114 | 115 | 116 | #################################### 117 | # 118 | # LEAGUES 119 | # 120 | #################################### 121 | def get_leagues(self, league_keys): 122 | """Return league data 123 | >>> yfs.get_leagues(['league_key']) 124 | """ 125 | uri = self._build_uri('leagues;league_keys',league_keys) 126 | response = self._get(uri) 127 | return response 128 | 129 | def get_leagues_teams(self, league_keys): 130 | """Return leagues teams 131 | >>> yfs.get_leagues_teams(['238.l.627062']) 132 | """ 133 | uri = self._build_uri('leagues;league_keys', league_keys, sub='teams') 134 | response = self._get(uri) 135 | return response 136 | 137 | def get_leagues_players(self, league_keys): 138 | """Return leagues players 139 | >>> yfs.get_leagues_teams(['238.l.627062']) 140 | """ 141 | uri = self._build_uri('leagues;league_keys', league_keys, sub='players') 142 | response = self._get(uri) 143 | return response 144 | 145 | def get_leagues_scoreboard(self, league_keys, week=None): 146 | """Return leagues scoreboard 147 | >>> yfs.get_leagues_scoreboard(['league_key']) 148 | """ 149 | uri = self._build_uri('leagues;league_keys',league_keys, sub='scoreboard') 150 | 151 | if week: 152 | uri += ';week={0}'.format(week) 153 | 154 | response = self._get(uri) 155 | return response 156 | 157 | def get_leagues_settings(self, league_keys): 158 | """Return leagues settings 159 | >>> yfs.get_leagues_settings(['238.l.627062','238.l.627062']) 160 | """ 161 | uri = self._build_uri('leagues;league_keys', league_keys, sub='settings') 162 | response = self._get(uri) 163 | return response 164 | 165 | def get_leagues_standings(self, league_keys, teams=None, players=None): 166 | """Return leagues settings 167 | >>> yfs.get_leagues_settings(['238.l.627062','238.l.627062']) 168 | """ 169 | uri = self._build_uri('leagues;league_keys', league_keys, sub='standings') 170 | 171 | if teams: 172 | uri += '/teams/{0}'.format(teams) 173 | 174 | if teams=='roster' and players: 175 | uri += '/players/{0}'.format(players) 176 | 177 | response = self._get(uri) 178 | return response 179 | 180 | def get_leagues_transactions(self, league_keys): 181 | """Return leagues settings 182 | >>> yfs.get_leagues_transactions(['238.l.627062']) 183 | """ 184 | uri = self._build_uri('leagues;league_keys', league_keys, sub='transactions') 185 | response = self._get(uri) 186 | return response 187 | 188 | def get_leagues_draftresults(self, league_keys): 189 | """Return leagues draftresults 190 | >>> yfs.get_leagues_draftresults(['238.l.627062']) 191 | """ 192 | uri = self._build_uri('leagues;league_keys', league_keys, sub='draftresults') 193 | response = self._get(uri) 194 | return response 195 | 196 | 197 | ######################################### 198 | # 199 | # PLAYERS (not league specific) 200 | # 201 | ######################################### 202 | 203 | def get_players(self, player_keys, filters=None): 204 | """Return player data 205 | >>> yfs.get_players(['player_key']) 206 | """ 207 | uri = self._build_uri('players;player_keys', player_keys) 208 | 209 | if filters and isinstance(filters, str): 210 | uri += ';{0}'.format(filters) 211 | if filters and not isinstance(filters, str): 212 | uri += ";{0}".format(','.join([e for e in filters])) 213 | 214 | response = self._get(uri) 215 | return response 216 | 217 | def get_players_stats(self, player_keys, week=None): 218 | """Return player stats (not league specific) 219 | >>> yfs.get_players_stats(['223.p.5479'], week=3) 220 | """ 221 | uri = self._build_uri('players;player_keys', player_keys, sub='stats') 222 | 223 | if week: 224 | uri += ';type=week;week={0}'.format(week) 225 | 226 | response = self._get(uri) 227 | return response 228 | 229 | def get_players_percent_owned(self, player_keys): 230 | """Return ownership percentage of player (not league specific) 231 | >>> yfs.get_players_percent_owned([223.p.5479]) 232 | """ 233 | uri = self._build_uri('players;player_keys', player_keys, sub='percent_owned') 234 | response = self._get(uri) 235 | return response 236 | 237 | def get_players_draft_analysis(self, player_keys): 238 | """Return draft metrics for player (not league specific) 239 | >>> yfs.get_players_draft_analysis([223.p.5479]) 240 | """ 241 | uri = self._build_uri('players;player_keys', player_keys, sub='draft_analysis') 242 | response = self._get(uri) 243 | return response 244 | 245 | ################################### 246 | # 247 | # TEAMS 248 | # 249 | ################################### 250 | 251 | 252 | def get_teams(self, team_keys): 253 | """Return team data 254 | >>> yfs.get_teams(['league_key']) 255 | """ 256 | uri = self._build_uri('teams;team_keys',team_keys) 257 | response = self._get(uri) 258 | return response 259 | 260 | def get_teams_players(self, team_keys): 261 | """Return teams players 262 | >>> yfs.get_teams_players(['238.l.627062']) 263 | """ 264 | uri = self._build_uri('teams;team_keys', team_keys, sub='players') 265 | response = self._get(uri) 266 | return response 267 | 268 | def get_teams_stats(self, team_keys, week=None): 269 | """Return team stats (week only for H2H league) 270 | >>> yfs.get_teams_stats(['238.l.627062.t.1'], week=3) 271 | """ 272 | uri = self._build_uri('teams;team_keys',team_keys, sub='stats') 273 | 274 | if week: 275 | uri += ';type=week;week={0}'.format(week) 276 | 277 | response = self._get(uri) 278 | return response 279 | 280 | def get_teams_standings(self, team_keys): 281 | """Return team standings 282 | >>> yfs.get_teams_standings(['238.l.627062.t.1']) 283 | """ 284 | uri = self._build_uri('teams;team_keys',team_keys, sub='standings') 285 | response = self._get(uri) 286 | return response 287 | 288 | def get_teams_roster(self, team_keys, week=None, players=None, filters=None): 289 | """Return team roster 290 | >>> yfs.get_teams_roster(['238.l.627062.t.1'], week=3) 291 | """ 292 | uri = self._build_uri('teams;team_keys',team_keys, sub='roster') 293 | 294 | if week: 295 | uri += ';week={0}'.format(week) 296 | 297 | if players and filters: 298 | uri += '/players;{1}/{0}'.format(filters, players) 299 | 300 | elif filters and not players: 301 | uri += '/players;{0}'.format(filters) 302 | 303 | elif players and not filters: 304 | uri += '/players/{0}'.format(players) 305 | 306 | response = self._get(uri) 307 | return response 308 | 309 | def get_teams_draftresults(self, team_keys): 310 | """Return a team's draft results 311 | >>> yfs.get_teams_draftresults(['238.l.627062.t.1']) 312 | """ 313 | uri = self._build_uri('teams;team_keys',team_keys, sub='draftresults') 314 | response = self._get(uri) 315 | return response 316 | 317 | def get_teams_matchups(self, team_keys, weeks=None): 318 | """Return team matchups (H2H leagues only) 319 | >>> yfs.get_teams_matchups(['238.l.627062.t.1'], weeks='1,3,6') 320 | """ 321 | uri = self._build_uri('teams;team_keys',team_keys, sub='matchups') 322 | 323 | if weeks and isinstance(weeks, str): 324 | uri += ';weeks={0}'.format(weeks) 325 | if weeks and not isinstance(weeks, str): 326 | uri += ";weeks{0}".format(','.join([e for e in weeks])) 327 | 328 | response = self._get(uri) 329 | return response 330 | 331 | 332 | 333 | ############################################## 334 | # 335 | # ROSTERS (team specific player info) 336 | # 337 | ############################################## 338 | 339 | def get_roster_players(self, team_keys, week=None, date=None): 340 | """Access roster info, with player sub option 341 | >>> yfs.get_roster_players(['238.l.627062']) 342 | """ 343 | uri = self._build_uri(None, team_keys, sub='roster/players') 344 | uri = 'team/{0}'.format(uri) # Done to avoid having 'team=238.l.627062', which doesn't work for this resource 345 | 346 | if week: 347 | uri += ';week={0}'.format(week) 348 | if date: 349 | uri += ';date={0}'.format(date) 350 | 351 | response = self._get(uri) 352 | return response 353 | 354 | def set_roster_players(self, team_keys, roster): 355 | """ 356 | >>> from fantasy_sport import Roster, Player 357 | >>> p1 = Player('242.p.8332','WR') 358 | >>> p2 = Player('242.p.8334','WL') 359 | >>> roster = Roster([p1, p2], date='2015-01-11') 360 | >>> ysf.set_roster_players(['238.l.627062'], roster) 361 | """ 362 | uri = self._build_uri(None, team_keys, sub='roster/players') 363 | uri = 'team/{0}'.format(uri) 364 | 365 | response = self._put(uri, roster) 366 | return response 367 | 368 | 369 | ############################################## 370 | # 371 | # TRANSACTIONS 372 | # 373 | ############################################## 374 | 375 | def get_transactions(self, transaction_keys, players=None): 376 | """Return transaction data 377 | >>> yfs.get_transaction(['transaction_key']) 378 | """ 379 | 380 | if players: 381 | subtext = 'players/{0}'.format(players) 382 | uri = self._build_uri('transactions;transaction_keys', transaction_keys, sub=subtext) 383 | else: 384 | uri = self._build_uri('transactions;transaction_keys', transaction_keys) 385 | 386 | response = self._get(uri) 387 | return response 388 | --------------------------------------------------------------------------------