Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Division Support #105

Merged
merged 79 commits into from
Jun 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
101feea
added division model
joeyagreco May 17, 2023
59ea168
stuff
joeyagreco May 17, 2023
a3cf94e
stuff
joeyagreco May 17, 2023
fbbc1f9
stuff
joeyagreco May 17, 2023
f8567b2
formatting
joeyagreco May 17, 2023
20894e6
added test
joeyagreco May 17, 2023
37a6657
stuff
joeyagreco May 17, 2023
44204b2
stuff
joeyagreco May 17, 2023
78404ce
added main batch file
joeyagreco May 17, 2023
98aa63a
stuff
joeyagreco May 17, 2023
0f0abf0
added test
joeyagreco May 18, 2023
ef6c202
added untested validation
joeyagreco May 18, 2023
be92a1d
stuff
joeyagreco May 18, 2023
f706ed0
stuff
joeyagreco May 18, 2023
e05ae74
stuff
joeyagreco May 18, 2023
3a824be
added test
joeyagreco May 20, 2023
947fc43
added tests
joeyagreco May 20, 2023
a72447b
better type checks
joeyagreco May 20, 2023
b79311c
tests
joeyagreco May 20, 2023
810c52f
tests
joeyagreco May 20, 2023
f036e84
updated changelog
joeyagreco May 20, 2023
172acf7
added support for espn divisions in league loader. tests failing. need
joeyagreco May 20, 2023
ee10faa
fixed tests
joeyagreco May 20, 2023
9852468
cleanup
joeyagreco May 20, 2023
1c649c2
FF divisions for LL. tests failing(thats ok)
joeyagreco May 21, 2023
fecbd08
comments
joeyagreco May 21, 2023
bf98c9d
stuff
joeyagreco May 21, 2023
ecc0964
better error messages for divisions
joeyagreco May 21, 2023
4a0b9ae
tested fleaflicker league loader with divisions
joeyagreco May 21, 2023
acaadc5
mfl league loader now loads divisions. tests failing thats ok
joeyagreco May 21, 2023
a992cc4
stuff
joeyagreco May 21, 2023
1e5c00b
fixes
joeyagreco May 22, 2023
d3b09fa
stuff
joeyagreco May 22, 2023
66c7797
fixed 1 test commented out the others
joeyagreco May 23, 2023
9023da1
fixed another test
joeyagreco May 23, 2023
d9ee041
fixed another test
joeyagreco May 23, 2023
ecf387b
fixed test
joeyagreco May 23, 2023
2eca0bc
all sleeper tests fixed
joeyagreco May 23, 2023
d49451a
added new equality check function and implemented in Team.py
joeyagreco May 25, 2023
b3cce71
cleanup
joeyagreco May 25, 2023
e2706ff
stuff
joeyagreco May 25, 2023
9011782
stuff
joeyagreco May 25, 2023
f1d8952
stuff
joeyagreco May 25, 2023
4460703
owner equals
joeyagreco May 25, 2023
ecbc681
equals for matchup
joeyagreco May 26, 2023
786f333
tested week
joeyagreco May 26, 2023
c81abe5
week
joeyagreco May 26, 2023
964db12
division equals
joeyagreco May 26, 2023
2dd675f
rename
joeyagreco May 27, 2023
de0c5f6
added base id field as a thing
joeyagreco May 27, 2023
25d004f
stuff
joeyagreco May 27, 2023
954aa93
stuff
joeyagreco May 27, 2023
94b9714
stuff
joeyagreco May 27, 2023
1d9291a
stuff
joeyagreco May 27, 2023
9e88d3d
stuff
joeyagreco May 27, 2023
bcb0de3
stuff
joeyagreco May 27, 2023
b5ec956
s
joeyagreco May 27, 2023
b080456
stuff
joeyagreco May 27, 2023
6393ccb
stuff
joeyagreco May 27, 2023
0573da9
stuff
joeyagreco May 27, 2023
dd0acae
fixed tests
joeyagreco May 27, 2023
30dacd2
fixed all tests
joeyagreco May 27, 2023
cfeb99f
stuff
joeyagreco May 27, 2023
f5c957f
renamed and added doc
joeyagreco May 27, 2023
24859cd
stuff
joeyagreco May 27, 2023
fead20c
updated changelog
joeyagreco May 27, 2023
f0bb78c
stuff
joeyagreco May 28, 2023
d1ce58d
added yn method and tests
joeyagreco May 28, 2023
18c0336
stuff
joeyagreco May 28, 2023
57e7d9a
made black formatter quiet
joeyagreco May 29, 2023
ca24ad0
changed kwarg to actual kwarg
joeyagreco May 30, 2023
f25b94b
readme
joeyagreco Jun 4, 2023
e9d3729
kwargs helper fix:x
joeyagreco Jun 4, 2023
0959413
stuff
joeyagreco Jun 4, 2023
d9ebd15
stuff
joeyagreco Jun 4, 2023
7892cf9
fixes
joeyagreco Jun 4, 2023
31d9625
now pass league name from all league loaders
joeyagreco Jun 4, 2023
73bf497
added tests
joeyagreco Jun 4, 2023
35a3e44
naming
joeyagreco Jun 4, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ All notable changes to this project will be documented in this file.

## Unreleased

- N/A
- Fixed a bug in the MyFantasyLeague League Loader where playoff Matchups could be ignored
- Fixed a bug in the Sleeper League Loader where leagues with 1-week playoff rounds could be loaded incorrectly
- Integration Divisions into league models
- Added Divisions to all League Loader flows
- Added Division column to Excel sheets
- Added an .equals() method to each league model object, allowing for more customized model comparisons
- Added the ability to pass a custom league name for each League Loader
- Added better validation for league models

## [2.4.0]

Expand All @@ -21,7 +28,7 @@ All notable changes to this project will be documented in this file.
- Added better tests for the Sleeper League Loader
- Added better tests for the Yahoo League Loader
- Added better validation to all League Loaders
- Added human-readable info logging with differences when comparing league models with "=="
- Added human-readable info logging with differences when comparing League models with "=="
- Updated League Loader examples

## [2.3.0]
Expand Down
25 changes: 13 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ TypeError: dataclass() got an unexpected keyword argument 'kw_only'
This error occurs when the Python version you are using is not 3.10 or greater.\
Make sure you are using Python version 3.10 or a newer version.

___
**Q:**
How do I use this library to pull stats from my online fantasy league?

Expand Down Expand Up @@ -180,14 +181,6 @@ If a fantasy site you use is not listed here and you would like it to be, please
Stats used in this library are
documented [here](https://github.com/joeyagreco/leeger/blob/main/doc/stats.md).

## Running Tests

To run tests, run the following command:

```bash
pytest
```

## Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Expand All @@ -196,11 +189,19 @@ Please make sure to update tests as appropriate.

## Development

### Formatting
_Run these commands from the root folder_
- Format Code: `./main fmt`
- Run Unit Tests: `./main test`
- Generate Coverage Report: `./main cov`

### Running Tests

Run the following command from the root folder:

```bash
pytest
```

_Run these commands from the root folder (leeger) before committing._\
**General Format:** `black --config=pyproject.toml . `\
**Import/Variable Format:** `autoflake --config=pyproject.toml .`

## License

Expand Down
7 changes: 7 additions & 0 deletions batch/coverage.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@echo off

cd test
coverage run -m pytest
coverage xml -o coverage.xml
coverage html
cd ..
4 changes: 4 additions & 0 deletions batch/format.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@echo off

black --config=pyproject.toml .
autoflake --config=pyproject.toml .
4 changes: 4 additions & 0 deletions batch/test.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@echo off

cd test
pytest
23 changes: 23 additions & 0 deletions example/league/comparingLeagueObjects.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from leeger.league_loader.ESPNLeagueLoader import ESPNLeagueLoader

from leeger.model.league import League

if __name__ == "__main__":
# to compare a League model (or any of its child models) you can use .equals()

# 1. take any model (let's get a dummy League) for an example
espnLeagueLoader = ESPNLeagueLoader("12345678", [2019, 2020])
league: League = espnLeagueLoader.loadLeague()

# 2. lets compare it
league.equals(league) # compares models with all fields
league.equals(league, ignoreBaseIds=True) # ignores the base "id" field in each object
league.equals(
league, ignoreIds=True
) # ignores fields that hold an id but not the base "id" fields
league.equals(
league, logDifferences=True
) # logs all differences IF the equality check is False

# 3. you can also use "=="
league == league # compares models using all of the .equals() defaults
4 changes: 4 additions & 0 deletions leeger/exception/InvalidDivisionFormatException.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class InvalidDivisionFormatException(Exception):
"""
Raised when an Division model is not formatted correctly.
"""
1 change: 1 addition & 0 deletions leeger/exception/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .DoesNotExistException import DoesNotExistException
from .InvalidDivisionFormatException import InvalidDivisionFormatException
from .InvalidFilterException import InvalidFilterException
from .InvalidLeagueFormatException import InvalidLeagueFormatException
from .InvalidMatchupFormatException import InvalidMatchupFormatException
Expand Down
28 changes: 24 additions & 4 deletions leeger/league_loader/ESPNLeagueLoader.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from leeger.enum.MatchupType import MatchupType
from leeger.league_loader.LeagueLoader import LeagueLoader
from leeger.model.league.Division import Division
from leeger.model.league.League import League
from leeger.model.league.Matchup import Matchup
from leeger.model.league.Owner import Owner
Expand Down Expand Up @@ -40,17 +41,23 @@ def __init__(
espnS2: str = None,
swid: str = None,
ownerNamesAndAliases: Optional[dict[str, list[str]]] = None,
leagueName: Optional[str] = None,
):
# validation
try:
int(leagueId)
except ValueError:
raise ValueError(f"League ID '{leagueId}' could not be turned into an int.")
super().__init__(leagueId, years, ownerNamesAndAliases=ownerNamesAndAliases)
super().__init__(
leagueId, years, ownerNamesAndAliases=ownerNamesAndAliases, leagueName=leagueName
)

self.__espnS2 = espnS2
self.__swid = swid
self.__espnTeamIdToTeamMap: dict[str, Team] = dict()
self.__espnDivisionIdToDivisionMap: dict[
int, Division
] = dict() # holds the division info for ONLY the current year

def __getAllLeagues(self) -> list[ESPNLeague]:
espnLeagueYears = list()
Expand Down Expand Up @@ -90,7 +97,6 @@ def __buildLeague(self, espnLeagues: list[ESPNLeague]) -> League:
self._leagueNameByYear[espnLeague.year] = espnLeague.settings.name
self.__loadOwners(espnLeague.teams)
years.append(self.__buildYear(espnLeague))
# use the league name from the most recent year
return League(
name=self._getLeagueName(), owners=self._owners, years=self._getValidYears(years)
)
Expand All @@ -106,9 +112,21 @@ def __loadOwners(self, espnTeams: list[ESPNTeam]) -> None:
self._owners = owners

def __buildYear(self, espnLeague: ESPNLeague) -> Year:
# save division info
for espnDivisionId, espnDivisionName in espnLeague.settings.division_map.items():
self.__espnDivisionIdToDivisionMap[espnDivisionId] = Division(name=espnDivisionName)
teams = self.__buildTeams(espnLeague.teams)
weeks = self.__buildWeeks(espnLeague)
return Year(yearNumber=espnLeague.year, teams=teams, weeks=weeks)
# TODO: see if there are cases where ESPN leagues do NOT have divisions
year = Year(
yearNumber=espnLeague.year,
teams=teams,
weeks=weeks,
divisions=list(self.__espnDivisionIdToDivisionMap.values()),
)
# clear division info
self.__espnDivisionIdToDivisionMap = dict()
return year

def __buildWeeks(self, espnLeague: ESPNLeague) -> list[Week]:
weeks = list()
Expand Down Expand Up @@ -205,8 +223,10 @@ def __getESPNTeamByESPNId(espnTeamId: int, espnTeams: list[ESPNTeam]) -> ESPNTea
def __buildTeams(self, espnTeams: list[ESPNTeam]) -> list[Team]:
teams = list()
for espnTeam in espnTeams:
# TODO: see if there are cases where ESPN leagues do NOT have divisions
divisionId = self.__espnDivisionIdToDivisionMap[espnTeam.division_id].id
owner = self._getOwnerByName(espnTeam.owner)
team = Team(ownerId=owner.id, name=espnTeam.team_name)
team = Team(ownerId=owner.id, name=espnTeam.team_name, divisionId=divisionId)
teams.append(team)
self.__espnTeamIdToTeamMap[espnTeam.team_id] = team
return teams
30 changes: 27 additions & 3 deletions leeger/league_loader/FleaflickerLeagueLoader.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from leeger.model.league.Week import Week
from leeger.model.league.Year import Year
from leeger.validate import leagueValidation
from leeger.model.league.Division import Division


class FleaflickerLeagueLoader(LeagueLoader):
Expand All @@ -27,16 +28,22 @@ def __init__(
years: list[int],
*,
ownerNamesAndAliases: Optional[dict[str, list[str]]] = None,
leagueName: Optional[str] = None,
):
# validation
try:
int(leagueId)
except ValueError:
raise ValueError(f"League ID '{leagueId}' could not be turned into an int.")
super().__init__(leagueId, years, ownerNamesAndAliases=ownerNamesAndAliases)
super().__init__(
leagueId, years, ownerNamesAndAliases=ownerNamesAndAliases, leagueName=leagueName
)

self.__fleaflickerTeamIdToOwnerMap: dict[int, Owner] = dict()
self.__fleaflickerTeamIdToTeamMap: dict[int, Team] = dict()
self.__fleaflickerDivisionIdToDivisionMap: dict[
int, Division
] = dict() # holds the division info for ONLY the current year

def __getAllLeagues(self) -> list[dict]:
# return a list of all leagues
Expand Down Expand Up @@ -82,9 +89,22 @@ def __buildLeague(self, fleaflickerLeagues: list[dict]) -> League:
return League(name=self._getLeagueName(), owners=owners, years=self._getValidYears(years))

def __buildYear(self, fleaflickerLeague: dict) -> Year:
# save division info
for fleaflickerDivision in fleaflickerLeague["divisions"]:
self.__fleaflickerDivisionIdToDivisionMap[fleaflickerDivision["id"]] = Division(
name=fleaflickerDivision["name"]
)
teams = self.__buildTeams(fleaflickerLeague)
weeks = self.__buildWeeks(fleaflickerLeague)
return Year(yearNumber=int(fleaflickerLeague["season"]), teams=teams, weeks=weeks)
year = Year(
yearNumber=int(fleaflickerLeague["season"]),
teams=teams,
weeks=weeks,
divisions=list(self.__fleaflickerDivisionIdToDivisionMap.values()),
)
# clear division info
self.__fleaflickerDivisionIdToDivisionMap = dict()
return year

def __buildWeeks(self, fleaflickerLeague: dict) -> list[Week]:
weeks = list()
Expand Down Expand Up @@ -160,7 +180,11 @@ def __buildTeams(self, fleaflickerLeague: dict) -> list[Team]:
teamName = team["name"]
teamId = team["id"]
owner = self.__fleaflickerTeamIdToOwnerMap[teamId]
team = Team(ownerId=owner.id, name=teamName)
team = Team(
ownerId=owner.id,
name=teamName,
divisionId=self.__fleaflickerDivisionIdToDivisionMap[division["id"]].id,
)
teams.append(team)
self.__fleaflickerTeamIdToTeamMap[teamId] = team
return teams
Expand Down
Loading