From 86889e3709b9ad8e2a9600d1b687f2ce7650f0e8 Mon Sep 17 00:00:00 2001 From: Jonathan Zaturensky Date: Thu, 22 Aug 2024 19:07:26 -0700 Subject: [PATCH] Update day parameter in team.change_positions() to time_frame (#50) Position change for NFL leagues requires week rather than date, see documentation below: ![image](https://github.com/user-attachments/assets/367b2221-148e-45ee-9585-cb1a5f871c47) This pull request replaces the day parameter with a more generic time_frame in the change_positions method in the Team class. This argument may be either a datetime.date or week number for use in NFL leagues. --------- Co-authored-by: Matt Spilchen --- setup.py | 2 +- yahoo_fantasy_api/team.py | 29 ++++++++++++++++-------- yahoo_fantasy_api/tests/mock_yhandler.py | 6 +++++ yahoo_fantasy_api/tests/test_team.py | 18 +++++++++++++++ 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/setup.py b/setup.py index e82cb88..26918e9 100755 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ def readme(): setup(name='yahoo_fantasy_api', - version='2.8.0', + version='2.9.0', description='Python bindings to access the Yahoo! Fantasy APIs', long_description=readme(), url='http://github.com/spilchen/yahoo_fantasy_api', diff --git a/yahoo_fantasy_api/team.py b/yahoo_fantasy_api/team.py index 02e7155..7ffc806 100644 --- a/yahoo_fantasy_api/team.py +++ b/yahoo_fantasy_api/team.py @@ -2,6 +2,7 @@ from yahoo_fantasy_api import yhandler import objectpath +import datetime from xml.dom.minidom import Document from yahoo_fantasy_api.utils import create_element @@ -113,15 +114,15 @@ def _compact_eligible_pos(j): pass return roster - def change_positions(self, day, modified_lineup): + def change_positions(self, time_frame, modified_lineup): """Change the starting position of a subset of players in your lineup This raises a RuntimeError if any error occurs when communicating with Yahoo! - :param day: The day that the new positions take affect. This should be - the starting day of the week. - :type day: :class:`datetime.date` + :param time_frame: The time frame that the new positions take affect. This should be + the starting day of the week (MLB, NBA, or NHL) or the week number (NFL). + :type time_frame: :class:`datetime.date` | int :param modified_lineup: List of players to modify. Each entry should have a dict with the following keys: player_id - player ID of the player to change; selected_position - new position of the player. @@ -134,7 +135,7 @@ def change_positions(self, day, modified_lineup): {'player_id': 4558, 'selected_position': 'BN'}] tm.change_positions(cd, plyrs) """ - xml = self._construct_change_roster_xml(day, modified_lineup) + xml = self._construct_change_roster_xml(time_frame, modified_lineup) self.yhandler.put_roster(self.team_key, xml) def add_player(self, player_id): @@ -377,16 +378,24 @@ def _construct_trade_proposal_xml(self, tradee_team_key: str, your_player_keys: return doc.toprettyxml() - def _construct_change_roster_xml(self, day, modified_lineup): + def _construct_change_roster_xml(self, time_frame, modified_lineup): """Construct XML to pass to Yahoo! that will modified the positions""" doc = Document() roster = doc.appendChild(doc.createElement('fantasy_content')) \ .appendChild(doc.createElement('roster')) - roster.appendChild(doc.createElement('coverage_type')) \ - .appendChild(doc.createTextNode('date')) - roster.appendChild(doc.createElement('date')) \ - .appendChild(doc.createTextNode(day.strftime("%Y-%m-%d"))) + if isinstance(time_frame, datetime.date): + roster.appendChild(doc.createElement('coverage_type')) \ + .appendChild(doc.createTextNode('date')) + roster.appendChild(doc.createElement('date')) \ + .appendChild(doc.createTextNode(time_frame.strftime("%Y-%m-%d"))) + elif isinstance(time_frame, int): + roster.appendChild(doc.createElement('coverage_type')) \ + .appendChild(doc.createTextNode('week')) + roster.appendChild(doc.createElement('week')) \ + .appendChild(doc.createTextNode(str(time_frame))) + else: + raise RuntimeError("Invalid time_frame format. Must be datetime.date or int.") plyrs = roster.appendChild(doc.createElement('players')) for plyr in modified_lineup: diff --git a/yahoo_fantasy_api/tests/mock_yhandler.py b/yahoo_fantasy_api/tests/mock_yhandler.py index 065b01b..1892346 100644 --- a/yahoo_fantasy_api/tests/mock_yhandler.py +++ b/yahoo_fantasy_api/tests/mock_yhandler.py @@ -189,3 +189,9 @@ def get_transactions_raw(self, league_id, tran_types, count): """ with open(self.dir_path + "/sample.transactions.json", "r") as f: return json.load(f) + + def put_roster(self, team_key, xml): + # This produces no output. Just save the xml for inspection by the + # test. + self.roster_xml = xml + diff --git a/yahoo_fantasy_api/tests/test_team.py b/yahoo_fantasy_api/tests/test_team.py index a15de5b..d4cb175 100644 --- a/yahoo_fantasy_api/tests/test_team.py +++ b/yahoo_fantasy_api/tests/test_team.py @@ -1,6 +1,8 @@ #!/bin/python import os +import datetime +import pytest def test_matchup(mock_team): @@ -79,3 +81,19 @@ def test__construct_trade_proposal_xml(mock_team): actual_xml = mock_team._construct_trade_proposal_xml(tradee_team_key, your_player_keys, their_player_keys, trade_note) assert actual_xml == expected_xml + + +def test_change_roster(mock_team): + plyrs = [{'player_id': 5981, 'selected_position': 'BN'}, + {'player_id': 4558, 'selected_position': 'BN'}] + cd = datetime.date(2019, 10, 7) + mock_team.change_positions(cd, plyrs) + assert mock_team.yhandler.roster_xml is not None + assert "2019-10-07" in mock_team.yhandler.roster_xml + + mock_team.change_positions(2, plyrs) + assert "2019-10-07" not in mock_team.yhandler.roster_xml + assert "2" in mock_team.yhandler.roster_xml + + with pytest.raises(Exception): + mock_team.change_positions("3", plyrs)