diff --git a/README.md b/README.md
index 15fae40c..523e0199 100644
--- a/README.md
+++ b/README.md
@@ -22,9 +22,11 @@ This package and its authors are not affiliated with MLB or any MLB team. This A
## Getting Started
-*Python-mlb-statsapi* is a Python library that provides developers with access to the MLB Stats API which allows developers to retrieve information related to MLB teams, players, stats, and more. *Python-mlb-statsapi* written in python 3.10+.
+*Python-mlb-statsapi* is a Python library that provides access to the MLB Stats API, allowing developers to retrieve information related to MLB teams, players, stats, and more. Written in Python 3.10+.
-To get started with the library, refer to the information provided in this README. For a more detailed explanation, check out the documentation and the Wiki section. The Wiki contains information on return objects, endpoint structure, usage examples, and more. It is a valuable resource for getting started, working with the library, and finding the information you need.
+All models are built with [Pydantic](https://docs.pydantic.dev/) for robust data validation and serialization. Field names follow Python's `snake_case` convention for a more Pythonic experience.
+
+For detailed documentation, check out the [Wiki](https://github.com/zero-sum-seattle/python-mlb-statsapi/wiki) which contains information on return objects, endpoint structure, usage examples, and more.
@@ -37,29 +39,78 @@ To get started with the library, refer to the information provided in this READM
```python
python3 -m pip install python-mlb-statsapi
```
-## Usage
+
+## Quick Start
```python
-python3
>>> import mlbstatsapi
>>> mlb = mlbstatsapi.Mlb()
+
>>> mlb.get_people_id("Ty France")
[664034]
+
+>>> player = mlb.get_person(664034)
+>>> print(player.full_name)
+Ty France
+
>>> stats = ['season', 'seasonAdvanced']
>>> groups = ['hitting']
>>> params = {'season': 2022}
>>> mlb.get_player_stats(664034, stats, groups, **params)
{'hitting': {'season': Stat, 'seasonadvanced': Stat }}
->>> mlb.get_team_id("Oakland Athletics")
-[133]
+>>> mlb.get_team_id("Seattle Mariners")
+[136]
->>> stats = ['season', 'seasonAdvanced']
->>> groups = ['pitching']
->>> params = {'season': 2022}
->>> mlb.get_team_stats(133, stats, groups, **params)
-{'pitching': {'season': Stat, 'seasonadvanced': Stat }}
+>>> team = mlb.get_team(136)
+>>> print(team.name, team.franchise_name)
+Seattle Mariners Seattle
```
+## Working with Pydantic Models
+
+All returned objects are Pydantic models, giving you access to powerful serialization and validation features.
+
+### Convert to Dictionary
+```python
+>>> player = mlb.get_person(664034)
+>>> player.model_dump()
+{'id': 664034, 'full_name': 'Ty France', 'link': '/api/v1/people/664034', ...}
+
+# Exclude None values
+>>> player.model_dump(exclude_none=True)
+{'id': 664034, 'full_name': 'Ty France', 'link': '/api/v1/people/664034', ...}
+
+# Include only specific fields
+>>> player.model_dump(include={'id', 'full_name', 'primary_position'})
+{'id': 664034, 'full_name': 'Ty France', 'primary_position': Position(...)}
+```
+
+### Convert to JSON
+```python
+>>> player = mlb.get_person(664034)
+>>> player.model_dump_json()
+'{"id": 664034, "full_name": "Ty France", "link": "/api/v1/people/664034", ...}'
+
+# Pretty print with indentation
+>>> print(player.model_dump_json(indent=2))
+{
+ "id": 664034,
+ "full_name": "Ty France",
+ "link": "/api/v1/people/664034",
+ ...
+}
+```
+
+### Access Fields with Snake Case Names
+```python
+>>> player = mlb.get_person(664034)
+>>> player.full_name # Not fullName
+'Ty France'
+>>> player.primary_position # Not primaryPosition
+Position(code='3', name='First Base', ...)
+>>> player.bat_side # Not batSide
+CodeDesc(code='R', description='Right')
+```
## Documentation
@@ -70,7 +121,7 @@ python3
### [Draft](https://github.com/zero-sum-seattle/python-mlb-statsapi/wiki/Data-Types:-Draft(round))
* `Mlb.get_draft(self, year_id: int, **params)` - Return a draft for a given year
### [Awards](https://github.com/zero-sum-seattle/python-mlb-statsapi/wiki/Data-Types:-Award)
-* `Mlb.get_awards(self, award_id: int, **params)` - Return rewards recipinets for a given award
+* `Mlb.get_awards(self, award_id: int, **params)` - Return award recipients for a given award
### [Teams](https://github.com/zero-sum-seattle/python-mlb-statsapi/wiki/Data-Types:-Team)
* `Mlb.get_team_id(self, team_name: str, search_key: str = 'name', **params)` - Return Team Id(s) from name
* `Mlb.get_team(self, team_id: int, **params)` - Return Team Object from Team Id
@@ -90,12 +141,12 @@ python3
* `Mlb.get_venues(self, **params)` - Return all Venues
### [Sports](https://github.com/zero-sum-seattle/python-mlb-statsapi/wiki/Data-Types:-Sport)
* `Mlb.get_sport(self, sport_id: int, **params)` - Return a Sport object from Id
-* `Mlb.get_sports(self, **params)` - Return all teams for Sport Id
+* `Mlb.get_sports(self, **params)` - Return all Sports
* `Mlb.get_sport_id(self, sport_name: str, search_key: str = 'name', **params)`- Return Sport Id from name
### [Schedules](https://github.com/zero-sum-seattle/python-mlb-statsapi/wiki/Data-Types:-Schedule)
* `Mlb.get_schedule(self, date: str, start_date: str, end_date: str, sport_id: int, team_id: int, **params)` - Return a Schedule
### [Divisions](https://github.com/zero-sum-seattle/python-mlb-statsapi/wiki/Data-Types:-Division)
-* `Mlb.get_division(self, division_id: int, **params)` - Return a Divison
+* `Mlb.get_division(self, division_id: int, **params)` - Return a Division
* `Mlb.get_divisions(self, **params)` - Return all Divisions
* `Mlb.get_division_id(self, division_name: str, search_key: str = 'name', **params)` - Return Division Id(s) from name
### [Leagues](https://github.com/zero-sum-seattle/python-mlb-statsapi/wiki/Data-Types:-League)
@@ -171,11 +222,9 @@ If you notice external test failures, please check if the MLB API has changed an
## Examples
-Let's show some examples of getting stat objects from the API. What is baseball with out stats right?
-
-### MLB Stats
+Let's show some examples of getting stat objects from the API. What is baseball without stats, right?
-#### Player Stats
+### Player Stats
Get the Id(s) of the players you want stats for and set stat types and groups.
```python
>>> mlb = mlbstatsapi.Mlb()
@@ -183,442 +232,276 @@ Get the Id(s) of the players you want stats for and set stat types and groups.
>>> stats = ['season', 'career']
>>> groups = ['hitting', 'pitching']
>>> params = {'season': 2022}
-
```
-Use player.id and stat types and groups to return a stats dictionary
+
+Use player id with stat types and groups to return a stats dictionary
```python
>>> stat_dict = mlb.get_player_stats(player_id, stats=stats, groups=groups, **params)
>>> season_hitting_stat = stat_dict['hitting']['season']
>>> career_pitching_stat = stat_dict['pitching']['career']
```
-Print season hitting stats
+
+Print season hitting stats using Pydantic's `model_dump()`
+```python
+>>> for split in season_hitting_stat.splits:
+... print(split.stat.model_dump(exclude_none=True))
+{'games_played': 140, 'groundouts': 163, 'airouts': 148, 'runs': 65, 'doubles': 27, ...}
+```
+
+Or access individual fields directly
```python
>>> for split in season_hitting_stat.splits:
-... for k, v in split.stat.__dict__.items():
-... print(k, v)
-gamesplayed 140
-groundouts 163
-airouts 148
-runs 65
-doubles 27
-triples 1
-homeruns 20
-strikeouts 94
-baseonballs 35
-...
->>> for split in career_pitching_stat.splits:
-... for k, v in split.stat.__dict__.items():
-... print(k, v)
-gamesplayed 2
-gamesstarted 0
-groundouts 2
-airouts 4
-runs 1
-doubles 0
-triples 0
-homeruns 1
-strikeouts 0
-baseonballs 0
-intentionalwalks 0
-hits 2
-hitbypitch 0
-...
-
-```
-#### Team stats
+... print(f"Games: {split.stat.games_played}")
+... print(f"Home Runs: {split.stat.home_runs}")
+... print(f"Batting Avg: {split.stat.avg}")
+Games: 140
+Home Runs: 20
+Batting Avg: .274
+```
+
+### Team Stats
Get the Team Id(s)
```python
-python3
>>> mlb = mlbstatsapi.Mlb()
>>> team_id = mlb.get_team_id('Seattle Mariners')[0]
```
-Set the stat types and groups.
+
+Set the stat types and groups
```python
>>> stats = ['season', 'seasonAdvanced']
>>> groups = ['hitting']
>>> params = {'season': 2022}
-
```
-Use team.id and the stat types and groups to return season hitting stats
+
+Use team id and the stat types and groups to return season hitting stats
```python
-stats = mlb.get_team_stats(team_id, stats=stats, groups=groups, **params)
-season_hitting = stats['hitting']['season']
-advanced_hitting = stats['hitting']['seasonadvanced']
+>>> stats = mlb.get_team_stats(team_id, stats=stats, groups=groups, **params)
+>>> season_hitting = stats['hitting']['season']
+>>> advanced_hitting = stats['hitting']['seasonadvanced']
```
-Print season and seasonadvanced stats
+
+Print stats as JSON
```python
>>> for split in season_hitting.splits:
-... for k, v in split.stat.__dict__.items():
-... print(k, v)
-gamesplayed 162
-groundouts 1273
-airouts 1523
-runs 690
-doubles 229
-triples 19
->>>
->>> for split in advanced_hitting.splits:
-... for k, v in split.stat.__dict__.items():
-... print(k, v)
-...
-plateappearances 6117
-totalbases 2094
-leftonbase 1129
-sacbunts 9
-sacflies 45
-```
-### More stats examples
-#### Expected Stats
-Get player Id's
-```python
->>> player_id = mlb.get_people_id('Ty France')[0]
+... print(split.stat.model_dump_json(indent=2, exclude_none=True))
+{
+ "games_played": 162,
+ "groundouts": 1273,
+ "runs": 690,
+ "doubles": 229,
+ ...
+}
```
-Set the stat type and group
+
+### Expected Stats
```python
+>>> player_id = mlb.get_people_id('Ty France')[0]
>>> stats = ['expectedStatistics']
>>> group = ['hitting']
>>> params = {'season': 2022}
-```
-Get Stats
-```python
>>> stats = mlb.get_player_stats(player_id, stats=stats, groups=group, **params)
->>> expectedstats = stats['hitting']['expectedstatistics']
->>> for split in expectedstats.splits:
-... for k, v in split.stat.__dict__.items():
-... print(k, v)
-avg .259
-slg .394
-woba .317
-wobacon .338
-```
-#### vsPlayer
+>>> expected = stats['hitting']['expectedstatistics']
+>>> for split in expected.splits:
+... print(f"Expected AVG: {split.stat.avg}")
+... print(f"Expected SLG: {split.stat.slg}")
+Expected AVG: .259
+Expected SLG: .394
+```
+
+### vsPlayer Stats
Get pitcher and batter player Ids
```python
>>> ty_france_id = mlb.get_people_id('Ty France')[0]
>>> shohei_ohtani_id = mlb.get_people_id('Shohei Ohtani')[0]
```
+
Set stat type, stat groups, and params
```python
>>> stats = ['vsPlayer']
>>> group = ['hitting']
>>> params = {'opposingPlayerId': shohei_ohtani_id, 'season': 2022}
```
+
Get stats
```python
>>> stats = mlb.get_player_stats(ty_france_id, stats=stats, groups=group, **params)
->>> vs_player_total = stats['hitting']['vsplayertotal']
->>> for split in vs_player_total.splits:
-... for k, v in split.stat.__dict__.items():
-... print(k, v)
-gamesplayed 4
-groundouts 3
-airouts 4
-runs None
-doubles 1
-triples 0
-homeruns 0
-...
>>> vs_player = stats['hitting']['vsplayer']
>>> for split in vs_player.splits:
-... for k, v in split.stat.__dict__.items():
-... print(k, v)
-gamesplayed 2
-groundouts 1
-airouts 2
-runs None
-doubles 1
-triples 0
-homeruns 0
-```
-#### hotColdZones
-Get player Id's
-```python
->>> ty_france_id = mlb.get_people_id('Ty France')[0]
->>> shohei_ohtani_id = mlb.get_people_id('Shohei Ohtani')[0]
+... print(f"Games: {split.stat.games_played}, Hits: {split.stat.hits}")
+Games: 2, Hits: 2
```
-Set the stat types and groups
+
+### Hot/Cold Zones
```python
+>>> ty_france_id = mlb.get_people_id('Ty France')[0]
>>> stats = ['hotColdZones']
>>> hitting_group = ['hitting']
->>> pitching_group = ['pitching']
->>> params = {'season': 2022}
-```
-The stat groups pitching and hitting both return hotColdZones for a pitcher and hitter. hotColdZones are not assigned to a
-stat group because of issues related to the REST API. So hotColdZones will be assigned to the stat key in stats return dict.
-```python
->>> hitting_hotcoldzones = mlb.get_player_stats(ty_france_id stats=stats, groups=hitting_group, **params)
->>> pitching_hotcoldzones = mlb.get_player_stats(shohei_ohtani_id, stats=stats, groups=pitching_group, **params)
-```
-hotColdZones returns a list of the HotColdZones
-```python
->>> ty_france_hotcoldzones = hitting_hotcoldzones['stats']['hotcoldzones']
->>> shohei_ohtani_hotcoldzones = pitching_hotcoldzones['stats']['hotcoldzones']
-```
-Loop through hotColdZone objects for Ty France
-```python
->>> for split in ty_france_hotcoldzones.splits:
-... print(split.stat.name)
-...
-onBasePercentage
-onBasePlusSlugging
-sluggingPercentage
-exitVelocity
-battingAverage
-```
-Loop through hotColdZone objects for Shoei Ohtani
-```python
->>> for split in shohei_ohtani_hotcoldzones.splits:
-... print(split.stat.name)
-...
-onBasePercentage
-onBasePlusSlugging
-sluggingPercentage
-exitVelocity
-battingAverage
-```
-Print zone information for obp
-```python
->>> for split in ty_france_hotcoldzones.splits:
-... if split.stat.name == 'onBasePercentage':
-... for zone in split.stat.zones:
-... print('zone: ', zone.zone)
-... print('value: ', zone.value)
-zone: 01
-value: .226
-zone: 02
-value: .400
-zone: 03
-value: .375
-zone: 04
-```
-#### Passing params
-Get Team Ids
-```python
-python3
->>> mlb = mlbstatsapi.Mlb()
->>> team_id = mlb.get_team_id('Seattle Mariners')[0]
-```
-Set the stat types and groups.
-```python
->>> stats = ['season', 'seasonAdvanced']
->>> groups = ['hitting']
>>> params = {'season': 2022}
-```
-Pass season to get_team_stats()
-```python
-stats = mlb.get_team_stats(team_id, stats=stats, groups=groups, **params)
-season_hitting = stats['hitting']['season']
-advanced_hitting = stats['hitting']['seasonadvanced']
-```
-season should be 2018
-```python
->>> for split in season_hitting.splits:
-... print('Season: ', split.season)
-... for k, v in split.stat.__dict__.items():
-... print(k, v)
-...
-Season: 2018
-gamesplayed 162
-groundouts 1535
-airouts 1425
-runs 677
-...
->>> for split in advanced_hitting.splits:
-... print('Season: ', split.season)
-... for k, v in split.stat.__dict__.items():
-... print(k, v)
-...
-Season: 2018
-plateappearances 6087
-totalbases 2250
-leftonbase 1084
-sacbunts 29
-sacflies 41
-...
-```
-
-### Gamepace examples
-Get pace of game metrics for specific sport, league or team.
-```python
->>> mlb = mlbstatsapi.Mlb()
->>> season = 2021
->>> gamepace = mlb.get_gamepace(season)
+>>> hotcoldzones = mlb.get_player_stats(ty_france_id, stats=stats, groups=hitting_group, **params)
+>>> zones = hotcoldzones['stats']['hotcoldzones']
+
+>>> for split in zones.splits:
+... print(f"Stat: {split.stat.name}")
+... for zone in split.stat.zones:
+... print(f" Zone {zone.zone}: {zone.value}")
+Stat: battingAverage
+ Zone 01: .226
+ Zone 02: .400
+ ...
```
### Schedule Examples
-Get a schedule for given date
+Get a schedule for a given date
```python
>>> mlb = mlbstatsapi.Mlb()
->>> schedule = mlb.get_schedule_date('2022-10-13')
-```
-Get ScheduleDates from Schedule
-```python
-dates = schedule.dates
-```
-Print Game status and Home and Away Teams
-```python
+>>> schedule = mlb.get_schedule(date='2022-10-13')
+>>> dates = schedule.dates
+
>>> for date in dates:
... for game in date.games:
-... print(game.status)
-... print(game.teams.home)
-... print(game.teams.away)
+... print(f"Game: {game.game_pk}")
+... print(f"Status: {game.status.detailed_state}")
+... print(f"Home: {game.teams.home.team.name}")
+... print(f"Away: {game.teams.away.team.name}")
```
+
### Game Examples
Get a Game for a given game id
```python
>>> mlb = mlbstatsapi.Mlb()
>>> game = mlb.get_game(662242)
```
-Get the weather for a game for a given game id
+
+Get the weather for a game
```python
->>> mlb = mlbstatsapi.Mlb()
->>> game = mlb.get_game(662242)
->>> weather = game.gamedata.weather
->>>
->>> print(weather.condition)
->>> print(weather.temp)
->>> print(weather.wind)
+>>> weather = game.game_data.weather
+>>> print(f"Condition: {weather.condition}")
+>>> print(f"Temperature: {weather.temp}")
+>>> print(f"Wind: {weather.wind}")
```
-Get the current status of a game for a given game id
+
+Get the current status of a game
```python
->>> mlb = mlbstatsapi.mlb()
->>> game = mlb.get_game(662242)
->>>
->>> linescore = game.livedata.linescore
->>> hometeaminfo = game.gamedata.teams.home
->>> awayteaminfo = game.gamedata.teams.away
->>> hometeamstatus = linescore.teams.home
->>> awayteamstatus = linescore.teams.away
->>>
->>> print("home: ", hometeaminfo.franchisename, hometeaminfo.clubname)
->>> print(" runs:", hometeamstatus.runs)
->>> print(" hits:", hometeamstatus.hits)
->>> print(" errors:", hometeamstatus.errors)
->>> print("away: ", awayteaminfo.franchisename, awayteaminfo.clubname)
->>> print(" runs:", awayteamstatus.runs)
->>> print(" hits:", awayteamstatus.hits)
->>> print(" errors:", awayteamstatus.errors)
->>> print("")
->>> print("inning:", linescore.inninghalf, linescore.currentinningordinal)
->>> print("balls:", linescore.balls)
->>> print("strikes:", linescore.strikes)
->>> print("Outs:", linescore.outs)
-```
-Get the play by play, line score, and box score objects from a game
+>>> linescore = game.live_data.linescore
+>>> home_info = game.game_data.teams.home
+>>> away_info = game.game_data.teams.away
+>>> home_status = linescore.teams.home
+>>> away_status = linescore.teams.away
+
+>>> print(f"Home: {home_info.franchise_name} {home_info.club_name}")
+>>> print(f" Runs: {home_status.runs}, Hits: {home_status.hits}, Errors: {home_status.errors}")
+>>> print(f"Away: {away_info.franchise_name} {away_info.club_name}")
+>>> print(f" Runs: {away_status.runs}, Hits: {away_status.hits}, Errors: {away_status.errors}")
+>>> print(f"Inning: {linescore.inning_half} {linescore.current_inning_ordinal}")
+```
+
+Get play by play, line score, and box score objects
```python
->>> mlb = mlbstatsapi.Mlb()
->>> game = mlb.get_game(662242)
->>>
->>> play_by_play = game.livedata.plays
->>> line_score = game.livedata.linescore
->>> box_score = game.livedata.boxscore
+>>> play_by_play = game.live_data.plays
+>>> line_score = game.live_data.linescore
+>>> box_score = game.live_data.boxscore
```
+
#### Play by Play
Get only the play by play for a given game id
```python
->>> mlb = mlbstatsapi.Mlb()
->>> playbyplay = mlb.get_play_by_play(662242)
+>>> playbyplay = mlb.get_game_play_by_play(662242)
```
+
#### Line Score
Get only the line score for a given game id
```python
->>> mlb = mlbstatsapi.Mlb()
->>> linescore = mlb.get_line_score(662242)
+>>> linescore = mlb.get_game_line_score(662242)
```
+
#### Box Score
Get only the box score for a given game id
```python
+>>> boxscore = mlb.get_game_box_score(662242)
+```
+
+### Gamepace Examples
+Get pace of game metrics for a specific season
+```python
>>> mlb = mlbstatsapi.Mlb()
->>> boxscore = mlb.get_box_score(662242)
+>>> gamepace = mlb.get_gamepace(season=2021)
+>>> print(f"Hits per game: {gamepace.sports[0].sport_game_pace.hits_per_game}")
```
### People Examples
Get all Players for a given sport id
```python
>>> mlb = mlbstatsapi.Mlb()
->>> sport_id = mlb.get_sport_id()
->>> players = mlb.get_players(sport_id=sport_id)
+>>> players = mlb.get_people(sport_id=1)
>>> for player in players:
-... print(player.id)
+... print(f"{player.id}: {player.full_name}")
```
+
Get a player id
```python
>>> player_id = mlb.get_people_id("Ty France")
>>> print(player_id[0])
->>> [664034]
+664034
```
### Team Examples
Get a Team
```python
>>> mlb = mlbstatsapi.Mlb()
->>> team_ids = mlb.get_team_id("Seattle Mariners")
->>> team_id = team_ids[0]
->>> team = mlb.get_team(team_id.id)
->>> print(team.id)
->>> print(team.name)
+>>> team_id = mlb.get_team_id("Seattle Mariners")[0]
+>>> team = mlb.get_team(team_id)
+>>> print(f"{team.id}: {team.name}")
+>>> print(f"Venue: {team.venue.name}")
```
+
Get a Player Roster
```python
>>> mlb = mlbstatsapi.Mlb()
->>> team_id = 133
->>> players = mlb.get_team_roster(team_id)
+>>> players = mlb.get_team_roster(136)
>>> for player in players:
- print(player.jerseynumber)
+... print(f"#{player.jersey_number} {player.person.full_name}")
```
+
Get a Coach Roster
```python
>>> mlb = mlbstatsapi.Mlb()
->>> team_id = 133
->>> coaches = mlb.get_team_coaches(team_id)
+>>> coaches = mlb.get_team_coaches(136)
>>> for coach in coaches:
- print(coach.title)
+... print(f"{coach.person.full_name}: {coach.title}")
```
### Draft Examples
Get a draft for a year
```python
>>> mlb = mlbstatsapi.Mlb()
->>> draft_year = '2019'
->>> draft = mlb.get_draft(draft_year)
+>>> draft = mlb.get_draft('2019')
```
+
Get Players from Draft
```python
>>> draftpicks = draft[0].picks
->>> for draftpick in draftpicks:
-... print(draftpick.id)
-... print(draftpick.pickround)
+>>> for pick in draftpicks:
+... print(f"Round {pick.pick_round}, Pick {pick.pick_number}: {pick.person.full_name}")
```
### Award Examples
Get awards for a given award id
```python
>>> mlb = mlbstatsapi.Mlb()
->>> retiredjersy = self.mlb.get_awards(award_id='RETIREDUNI_108')
->>> for recipient in retiredjersy.awards:
-... print (recipient.player.nameFirstLast, recipient.name, recipient.date)
+>>> retired_numbers = mlb.get_awards(award_id='RETIREDUNI_108')
+>>> for recipient in retired_numbers.awards:
+... print(f"{recipient.player.full_name}: {recipient.name} ({recipient.date})")
```
### Venue Examples
Get a Venue
```python
>>> mlb = mlbstatsapi.Mlb()
->>> vevue_ids = mlb.get_venue_id('PNC Park')
->>> venue_id = venue_ids[0]
->>> venue = mlb.get_team(venue.id)
->>> print(venue.id)
->>> print(venue.name)
-```
-
-### Sport Examples
-Get a Sport
-```python
->>> mlb = mlbstatsapi.Mlb()
->>> sport_ids = mlb.get_sport_id('Major League Baseball')
->>> sport_id = sport_ids[0]
->>> sport = mlb.get_sport(sport_id)
+>>> venue_id = mlb.get_venue_id('PNC Park')[0]
+>>> venue = mlb.get_venue(venue_id)
+>>> print(f"{venue.name} - {venue.location.city}, {venue.location.state}")
```
### Division Examples
@@ -627,6 +510,7 @@ Get a division
>>> mlb = mlbstatsapi.Mlb()
>>> division = mlb.get_division(200)
>>> print(division.name)
+American League West
```
### League Examples
@@ -635,6 +519,7 @@ Get a league
>>> mlb = mlbstatsapi.Mlb()
>>> league = mlb.get_league(103)
>>> print(league.name)
+American League
```
### Season Examples
@@ -642,12 +527,17 @@ Get a Season
```python
>>> mlb = mlbstatsapi.Mlb()
>>> season = mlb.get_season(2018)
->>> print(season.seasonid)
+>>> print(f"Season: {season.season_id}")
+>>> print(f"Regular Season: {season.regular_season_start_date} to {season.regular_season_end_date}")
```
### Standings Examples
-Get a Standings
+Get Standings
```python
>>> mlb = mlbstatsapi.Mlb()
>>> standings = mlb.get_standings(103, 2018)
+>>> for record in standings:
+... print(f"Division: {record.division.name}")
+... for team in record.team_records:
+... print(f" {team.team.name}: {team.wins}-{team.losses}")
```
diff --git a/mlbstatsapi/mlb_api.py b/mlbstatsapi/mlb_api.py
index 61d7b7b7..ce70f540 100644
--- a/mlbstatsapi/mlb_api.py
+++ b/mlbstatsapi/mlb_api.py
@@ -16,8 +16,8 @@
from mlbstatsapi.models.seasons import Season
from mlbstatsapi.models.drafts import Round
from mlbstatsapi.models.awards import Award
-from mlbstatsapi.models.gamepace import Gamepace
-from mlbstatsapi.models.homerunderby import Homerunderby
+from mlbstatsapi.models.gamepace import GamePace
+from mlbstatsapi.models.homerunderby import HomeRunDerby
from mlbstatsapi.models.standings import Standings
from .mlb_dataadapter import MlbDataAdapter
@@ -1099,7 +1099,7 @@ def get_game_ids(self, date: str = None,
return game_ids
- def get_gamepace(self, season: str, sport_id=1, **params) -> Union[Gamepace, None]:
+ def get_gamepace(self, season: str, sport_id=1, **params) -> Union[GamePace, None]:
"""
Get pace of game metrics for specific sport, league or team.
@@ -1164,7 +1164,7 @@ def get_gamepace(self, season: str, sport_id=1, **params) -> Union[Gamepace, Non
or 'leagues' in mlb_data.data and mlb_data.data['leagues']
or 'sports' in mlb_data.data and mlb_data.data['sports']):
- return Gamepace(**mlb_data.data)
+ return GamePace(**mlb_data.data)
def get_venue(self, venue_id: int, **params) -> Union[Venue, None]:
"""
@@ -2016,7 +2016,7 @@ def get_awards(self, award_id: str, **params) -> List[Award]:
return awards_list
- def get_homerun_derby(self, game_id, **params) -> Union[Homerunderby, None]:
+ def get_homerun_derby(self, game_id, **params) -> Union[HomeRunDerby, None]:
"""
The homerun derby endpoint on the Stats API allows for users to
request information from the MLB database pertaining to the
@@ -2036,7 +2036,7 @@ def get_homerun_derby(self, game_id, **params) -> Union[Homerunderby, None]:
Returns
-------
- Homerunderby object
+ HomeRunDerby object
See Also
--------
@@ -2049,7 +2049,7 @@ def get_homerun_derby(self, game_id, **params) -> Union[Homerunderby, None]:
None
if 'status' in mlb_data.data and mlb_data.data['status']:
- return Homerunderby(**mlb_data.data)
+ return HomeRunDerby(**mlb_data.data)
def get_team_stats(self, team_id: int, stats: list, groups: list, **params) -> dict:
diff --git a/mlbstatsapi/models/__init__.py b/mlbstatsapi/models/__init__.py
index e69de29b..649da909 100644
--- a/mlbstatsapi/models/__init__.py
+++ b/mlbstatsapi/models/__init__.py
@@ -0,0 +1,3 @@
+from .base import MLBBaseModel
+
+__all__ = ["MLBBaseModel"]
diff --git a/mlbstatsapi/models/attendances/attendance.py b/mlbstatsapi/models/attendances/attendance.py
index 5132b4c8..c611c9b8 100644
--- a/mlbstatsapi/models/attendances/attendance.py
+++ b/mlbstatsapi/models/attendances/attendance.py
@@ -1,23 +1,19 @@
-from dataclasses import dataclass, field
-from typing import Union, List
+from typing import List
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from .attributes import AttendanceTotals, AttendanceRecords
-@dataclass
-class Attendance:
+
+class Attendance(MLBBaseModel):
"""
A class to represent attendance.
+
Attributes
----------
- copyright : str
- Copyright message
records : List[AttendanceRecords]
- List of attendance records
- aggregatetotals : AttendanceAggregateTotals
- Attendence aggregate total numbers for query
+ List of attendance records.
+ aggregate_totals : AttendanceTotals
+ Attendance aggregate total numbers for query.
"""
- aggregatetotals: Union[AttendanceTotals, dict]
- records: Union[List[AttendanceRecords], List[dict]] = field(default_factory=list)
-
- def __post_init__(self):
- self.records = [AttendanceRecords(**record) for record in self.records if self.records]
- self.aggregatetotals = AttendanceTotals(**self.aggregatetotals)
\ No newline at end of file
+ aggregate_totals: AttendanceTotals = Field(alias="aggregatetotals")
+ records: List[AttendanceRecords] = []
diff --git a/mlbstatsapi/models/attendances/attributes.py b/mlbstatsapi/models/attendances/attributes.py
index c96e5b48..bdc32510 100644
--- a/mlbstatsapi/models/attendances/attributes.py
+++ b/mlbstatsapi/models/attendances/attributes.py
@@ -1,190 +1,175 @@
-from dataclasses import dataclass, field
-from typing import Optional, Union
+from typing import Optional
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.teams import Team
-@dataclass
-class AttendanceHighLowGameContent:
+class AttendanceHighLowGameContent(MLBBaseModel):
"""
- A class to represent attendance records.
+ A class to represent attendance game content.
+
Attributes
----------
link : str
- games content endpoint link
+ Games content endpoint link.
"""
link: str
-@dataclass
-class AttendanceHighLowGame:
+class AttendanceHighLowGame(MLBBaseModel):
"""
- A class to represent attendance High and Low games.
+ A class to represent attendance high and low games.
+
Attributes
----------
- gamepk : int
- Games Id number
+ game_pk : int
+ Game's ID number.
link : str
- games endpoint link
+ Games endpoint link.
content : AttendanceHighLowGameContent
- Content for this game
- daynight : str
- Type of time of day for game
+ Content for this game.
+ day_night : str
+ Time of day for game (day or night).
"""
- gamepk: int
+ game_pk: int = Field(alias="gamepk")
link: str
- content: Union[AttendanceHighLowGameContent, dict]
- daynight: str
-
- def __post_init__(self):
- self.content = AttendanceHighLowGameContent(**self.content)
+ content: AttendanceHighLowGameContent
+ day_night: str = Field(alias="daynight")
-@dataclass
-class AttendenceGameType:
+class AttendanceGameType(MLBBaseModel):
"""
- A class to represent Attendance Game Type.
+ A class to represent attendance game type.
+
Attributes
----------
id : str
- Game type id
+ Game type ID.
description : str
- Game type description
+ Game type description.
"""
id: str
description: str
-@dataclass(repr=False)
-class AttendanceRecords:
+class AttendanceRecords(MLBBaseModel):
"""
A class to represent attendance records.
+
Attributes
----------
- openingstotal : int
- Total amount of openings
- openingstotalaway : int
- Total amount of opening away games
- openingstotalhome : int
- Total amount of opening home games
- openingstotallost : int
- Total amount of openings lost
- gamestotal : int
- Total amount of games
- gamesawaytotal : int
- Total amount of away games
- gameshometotal : int
- Total amount of home games
+ openings_total : int
+ Total number of openings.
+ openings_total_away : int
+ Total number of opening away games.
+ openings_total_home : int
+ Total number of opening home games.
+ openings_total_lost : int
+ Total number of openings lost.
+ games_total : int
+ Total number of games.
+ games_away_total : int
+ Total number of away games.
+ games_home_total : int
+ Total number of home games.
year : str
- Year as a string
- attendanceaverageaway : int
- Average attendance for away games
- attendanceaveragehome : int
- Average attendance for home games
- attendanceaverageytd : int
- Average attendance year to date
- attendancehigh : int
- Attendance High number
- attendancehighdate : str
- Attendance high date
- attendancehighgame : AttendanceHighLowGame
- Attendance high game
- attendancelow : int
- Attendance low number
- attendancelowdate : str
- Attendance low date
- attendancelowgame : AttendanceHighLowGame
- Attendance low game
- attendanceopeningaverage : int
- Attendance opening average
- attendancetotal : int
- Attendance total
- attendancetotalaway : int
- Attendance total away
- attendancetotalhome : int
- Attendance total home
- gametype : AttendenceGameType
- Game type
+ Year as a string.
+ attendance_average_away : int
+ Average attendance for away games.
+ attendance_average_home : int
+ Average attendance for home games.
+ attendance_average_ytd : int
+ Average attendance year to date.
+ attendance_high : int
+ Attendance high number.
+ attendance_high_date : str
+ Attendance high date.
+ attendance_high_game : AttendanceHighLowGame
+ Attendance high game.
+ attendance_low : int
+ Attendance low number.
+ attendance_low_date : str
+ Attendance low date.
+ attendance_low_game : AttendanceHighLowGame
+ Attendance low game.
+ attendance_opening_average : int
+ Attendance opening average.
+ attendance_total : int
+ Attendance total.
+ attendance_total_away : int
+ Attendance total away.
+ attendance_total_home : int
+ Attendance total home.
+ game_type : AttendanceGameType
+ Game type.
team : Team
- Team
+ Team.
"""
- openingstotal: int
- openingstotalaway: int
- openingstotalhome: int
- openingstotallost: int
- gamestotal: int
- gamesawaytotal: int
- gameshometotal: int
+ openings_total: int = Field(alias="openingstotal")
+ openings_total_away: int = Field(alias="openingstotalaway")
+ openings_total_home: int = Field(alias="openingstotalhome")
+ openings_total_lost: int = Field(alias="openingstotallost")
+ games_total: int = Field(alias="gamestotal")
+ games_away_total: int = Field(alias="gamesawaytotal")
+ games_home_total: int = Field(alias="gameshometotal")
year: str
- attendanceaverageytd: int
- gametype: Union[AttendenceGameType, dict]
- team: Union[Team, dict]
- attendancetotal: Optional[int] = None
- attendanceaverageaway: Optional[int] = None
- attendanceaveragehome: Optional[int] = None
- attendancehigh: Optional[int] = None
- attendancehighdate: Optional[str] = None
- attendancehighgame: Optional[Union[AttendanceHighLowGame, dict]] = None
- attendancelow: Optional[int] = None
- attendancelowdate: Optional[str] = None
- attendancelowgame: Optional[Union[AttendanceHighLowGame, dict]] = None
- attendancetotalaway: Optional[int] = None
- attendancetotalhome: Optional[int] = None
- attendanceopeningaverage: Optional[int] = None
-
- def __post_init__(self):
- self.attendancehighgame = AttendanceHighLowGame(**self.attendancehighgame) if self.attendancehighgame else self.attendancehighgame
- self.attendancelowgame = AttendanceHighLowGame(**self.attendancelowgame) if self.attendancelowgame else self.attendancelowgame
- self.gameType = AttendenceGameType(**self.gametype)
- self.team = Team(**self.team)
+ attendance_average_ytd: int = Field(alias="attendanceaverageytd")
+ game_type: AttendanceGameType = Field(alias="gametype")
+ team: Team
+ attendance_total: Optional[int] = Field(default=None, alias="attendancetotal")
+ attendance_average_away: Optional[int] = Field(default=None, alias="attendanceaverageaway")
+ attendance_average_home: Optional[int] = Field(default=None, alias="attendanceaveragehome")
+ attendance_high: Optional[int] = Field(default=None, alias="attendancehigh")
+ attendance_high_date: Optional[str] = Field(default=None, alias="attendancehighdate")
+ attendance_high_game: Optional[AttendanceHighLowGame] = Field(default=None, alias="attendancehighgame")
+ attendance_low: Optional[int] = Field(default=None, alias="attendancelow")
+ attendance_low_date: Optional[str] = Field(default=None, alias="attendancelowdate")
+ attendance_low_game: Optional[AttendanceHighLowGame] = Field(default=None, alias="attendancelowgame")
+ attendance_total_away: Optional[int] = Field(default=None, alias="attendancetotalaway")
+ attendance_total_home: Optional[int] = Field(default=None, alias="attendancetotalhome")
+ attendance_opening_average: Optional[int] = Field(default=None, alias="attendanceopeningaverage")
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-@dataclass(repr=False)
-class AttendanceTotals:
+class AttendanceTotals(MLBBaseModel):
"""
- A class to represent attendance aggregate toatls.
+ A class to represent attendance aggregate totals.
+
Attributes
----------
- openingstotalaway : int
- Total amount of opening game attendance number
- openingstotalhome : int
- Total amount of opening home game attendance number
- openingstotallost : int
- Total amount of opening games lost
- openingstotalytd : int
- Total amount of opening games year to date
- attendanceaverageaway : int
- Average away game attendance
- attendanceaveragehome : int
- Average home game attendance
- attendanceaverageytd : int
- Average attendance year to date
- attendancehigh : int
- Attendance high
- attendancehighdate : str
- Attendance high date
- attendancetotal : int
- Attendance total
- attendancetotalaway : int
- Attendace total away
- attendancetotalhome : int
- Attendance total home
+ openings_total_away : int
+ Total opening game attendance number for away games.
+ openings_total_home : int
+ Total opening home game attendance number.
+ openings_total_lost : int
+ Total number of opening games lost.
+ openings_total_ytd : int
+ Total number of opening games year to date.
+ attendance_average_away : int
+ Average away game attendance.
+ attendance_average_home : int
+ Average home game attendance.
+ attendance_average_ytd : int
+ Average attendance year to date.
+ attendance_high : int
+ Attendance high.
+ attendance_high_date : str
+ Attendance high date.
+ attendance_total : int
+ Attendance total.
+ attendance_total_away : int
+ Attendance total away.
+ attendance_total_home : int
+ Attendance total home.
"""
- openingstotalaway: int
- openingstotalhome: int
- openingstotallost: int
- openingstotalytd: int
- attendanceaverageytd: int
- attendancehigh: int
- attendancehighdate: str
- attendancetotal: int
- attendancetotalaway: int
- attendancetotalhome: int
- attendanceaverageaway: Optional[int] = None
- attendanceaveragehome: Optional[int] = None
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ openings_total_away: int = Field(alias="openingstotalaway")
+ openings_total_home: int = Field(alias="openingstotalhome")
+ openings_total_lost: int = Field(alias="openingstotallost")
+ openings_total_ytd: int = Field(alias="openingstotalytd")
+ attendance_average_ytd: int = Field(alias="attendanceaverageytd")
+ attendance_high: int = Field(alias="attendancehigh")
+ attendance_high_date: str = Field(alias="attendancehighdate")
+ attendance_total: int = Field(alias="attendancetotal")
+ attendance_total_away: int = Field(alias="attendancetotalaway")
+ attendance_total_home: int = Field(alias="attendancetotalhome")
+ attendance_average_away: Optional[int] = Field(default=None, alias="attendanceaverageaway")
+ attendance_average_home: Optional[int] = Field(default=None, alias="attendanceaveragehome")
diff --git a/mlbstatsapi/models/awards/__init__.py b/mlbstatsapi/models/awards/__init__.py
index 1a8c5305..822f5fd8 100644
--- a/mlbstatsapi/models/awards/__init__.py
+++ b/mlbstatsapi/models/awards/__init__.py
@@ -1,2 +1,2 @@
from .awards import Awards
-from .attributes import Award
\ No newline at end of file
+from .attributes import Award
diff --git a/mlbstatsapi/models/awards/attributes.py b/mlbstatsapi/models/awards/attributes.py
index 43096459..2e38fdad 100644
--- a/mlbstatsapi/models/awards/attributes.py
+++ b/mlbstatsapi/models/awards/attributes.py
@@ -1,47 +1,37 @@
-from typing import Union, Optional
-from dataclasses import dataclass
-
+from typing import Optional
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.teams import Team
from mlbstatsapi.models.people import Person
-@dataclass(kw_only=True, repr=False)
-class Award:
+
+class Award(MLBBaseModel):
"""
- This class represents an award object
+ A class representing an award.
Attributes
----------
id : str
- Award id
+ Award ID.
name : str
- Name of the award
+ Name of the award.
date : str
- Date of when award was given
+ Date of when award was given.
season : str
- Season award is for/from
+ Season award is for/from.
team : Team
- Team award was to/ Player is from
+ Team award was to / Player is from.
player : Person
- Person award is for
- votes : int None
- Any votes associated with award
- notes : str None
- Any notes associated with award
+ Person award is for.
+ votes : int
+ Any votes associated with award.
+ notes : str
+ Any notes associated with award.
"""
-
id: str
name: str
date: str
season: str
- team: Union[Team, dict]
- player: Union[Person, dict]
+ team: Team
+ player: Person
votes: Optional[int] = None
notes: Optional[str] = None
-
- def __post_init__(self):
- self.team = Team(**self.team)
- self.player = Person(**self.player)
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
diff --git a/mlbstatsapi/models/awards/awards.py b/mlbstatsapi/models/awards/awards.py
index fb4c4b06..d5730093 100644
--- a/mlbstatsapi/models/awards/awards.py
+++ b/mlbstatsapi/models/awards/awards.py
@@ -1,17 +1,15 @@
from typing import List
-from dataclasses import dataclass
-
+from mlbstatsapi.models.base import MLBBaseModel
from .attributes import Award
-@dataclass
-class Awards:
+
+class Awards(MLBBaseModel):
"""
- This class represents an awards object
+ A class representing an awards collection.
Attributes
----------
awards : List[Award]
- Awards
+ List of awards.
"""
-
- awards: List[Award]
+ awards: List[Award] = []
diff --git a/mlbstatsapi/models/base.py b/mlbstatsapi/models/base.py
new file mode 100644
index 00000000..171109dd
--- /dev/null
+++ b/mlbstatsapi/models/base.py
@@ -0,0 +1,15 @@
+from pydantic import BaseModel, ConfigDict
+
+
+class MLBBaseModel(BaseModel):
+ """Common base for all MLB Stats API models.
+
+ - Pydantic v2
+ - Ignores unknown fields to remain resilient to API changes
+ - populate_by_name allows alias-based population when needed
+ """
+
+ model_config = ConfigDict(
+ extra="ignore",
+ populate_by_name=True,
+ )
diff --git a/mlbstatsapi/models/data/data.py b/mlbstatsapi/models/data/data.py
index be5fed4b..6ca24987 100644
--- a/mlbstatsapi/models/data/data.py
+++ b/mlbstatsapi/models/data/data.py
@@ -1,96 +1,91 @@
-from dataclasses import dataclass, field, InitVar
-from typing import List, Union, Dict, Any, Optional
+from typing import Optional, Any
+from pydantic import Field, field_validator
+from mlbstatsapi.models.base import MLBBaseModel
-
-
-@dataclass(repr=False)
-class PitchBreak:
+class PitchBreak(MLBBaseModel):
"""
- A class to hold pitch pitch break data
-
+ A class to hold pitch break data.
+
Attributes
----------
- breakangle : float
- Degrees clockwise (batter's view) that the plane of
- the pitch deviates from the vertical
- breaklength : float
+ break_angle : float
+ Degrees clockwise (batter's view) that the plane of
+ the pitch deviates from the vertical.
+ break_vertical : float
+ Vertical break of the pitch.
+ break_vertical_induced : float
+ Induced vertical break.
+ break_horizontal : float
+ Horizontal break of the pitch.
+ break_length : float
Max distance that the pitch separates from the straight
- line between pitch start and pitch end
- breaky : int
- Distance from home plate where the break is greatest
- spinrate : int
- Pitch spinRate
- spindirection : int
- Pitch spinDirection
+ line between pitch start and pitch end.
+ break_y : int
+ Distance from home plate where the break is greatest.
+ spin_rate : float
+ Pitch spin rate.
+ spin_direction : float
+ Pitch spin direction.
"""
- breakangle: Optional[float]
- breakvertical: Optional[float]
- breakverticalinduced: Optional[float]
- breakhorizontal: Optional[float]
- spinrate: Optional[float] = None
- spindirection: Optional[float] = None
- breaklength: Optional[float] = None
- breaky: Optional[float] = None
+ break_angle: Optional[float] = Field(default=None, alias="breakangle")
+ break_vertical: Optional[float] = Field(default=None, alias="breakvertical")
+ break_vertical_induced: Optional[float] = Field(default=None, alias="breakverticalinduced")
+ break_horizontal: Optional[float] = Field(default=None, alias="breakhorizontal")
+ spin_rate: Optional[float] = Field(default=None, alias="spinrate")
+ spin_direction: Optional[float] = Field(default=None, alias="spindirection")
+ break_length: Optional[float] = Field(default=None, alias="breaklength")
+ break_y: Optional[float] = Field(default=None, alias="breaky")
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-@dataclass(repr=False)
-class PitchCoordinates:
+class PitchCoordinates(MLBBaseModel):
"""
- A class to hold pitch coordinates for playLog
+ A class to hold pitch coordinates for playLog.
Attributes
----------
- ay : float, default=None
- Ball acceleration on the y axis
- az : float, default=None
- Ball acceleration on the z axis
- pfxx : float, default=None
- horizontal movement of the ball in inches
- pfxz : float, default=None
- Vertical movement of the ball in inches
- px : float, default=None
- Horizontal position in feet of the ball as it
- crosses the front axis of home plate
- pz : float, default=None
- Vertical position in feet of the ball as it
- crosses the front axis of home plate
- vx0 : float, default=None
- Velocity of the ball from the x-axis
- vy0 : float, default=None
- Velocity of the ball from the y axis, this
- is negative becuase 0,0,0 is behind the batter
- and the ball travels from pitcher mound towards 0,0,0
- vz0 : float, default=None
- Velocity of the ball from the z axis
- x0 : float, default=None
- Coordinate location of the ball at the point it was
- reeased from pitchers hand on the x axis (time=0)
- y0 : float, default=None
- Coordinate location of the ball at the point it was
- reeased from pitchers hand on the y axis (time=0)
- z0 : float, default=None
- Coordinate location of the ball at the point it was
- reeased from pitchers hand on the z axis (time=0)
- ax : float, default=None
- Ball acceleration on the x axis
- x : float, default=None
- X coordinate where pitch crossed front of home plate
- y : float, default=None
- Y coordinate where pitch crossed front of home plate
+ ay : float
+ Ball acceleration on the y axis.
+ az : float
+ Ball acceleration on the z axis.
+ pfx_x : float
+ Horizontal movement of the ball in inches.
+ pfx_z : float
+ Vertical movement of the ball in inches.
+ p_x : float
+ Horizontal position in feet of the ball as it
+ crosses the front axis of home plate.
+ p_z : float
+ Vertical position in feet of the ball as it
+ crosses the front axis of home plate.
+ v_x0 : float
+ Velocity of the ball from the x-axis.
+ v_y0 : float
+ Velocity of the ball from the y axis.
+ v_z0 : float
+ Velocity of the ball from the z axis.
+ x0 : float
+ Coordinate location of the ball at release on x axis.
+ y0 : float
+ Coordinate location of the ball at release on y axis.
+ z0 : float
+ Coordinate location of the ball at release on z axis.
+ ax : float
+ Ball acceleration on the x axis.
+ x : float
+ X coordinate where pitch crossed front of home plate.
+ y : float
+ Y coordinate where pitch crossed front of home plate.
"""
ay: Optional[float] = None
az: Optional[float] = None
- pfxx: Optional[float] = None
- pfxz: Optional[float] = None
- px: Optional[float] = None
- pz: Optional[float] = None
- vx0: Optional[float] = None
- vy0: Optional[float] = None
- vz0: Optional[float] = None
+ pfx_x: Optional[float] = Field(default=None, alias="pfxx")
+ pfx_z: Optional[float] = Field(default=None, alias="pfxz")
+ p_x: Optional[float] = Field(default=None, alias="px")
+ p_z: Optional[float] = Field(default=None, alias="pz")
+ v_x0: Optional[float] = Field(default=None, alias="vx0")
+ v_y0: Optional[float] = Field(default=None, alias="vy0")
+ v_z0: Optional[float] = Field(default=None, alias="vz0")
x0: Optional[float] = None
y0: Optional[float] = None
z0: Optional[float] = None
@@ -98,24 +93,20 @@ class PitchCoordinates:
x: Optional[float] = None
y: Optional[float] = None
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-@dataclass(repr=False)
-class PitchData:
+class PitchData(MLBBaseModel):
"""
- A class to hold data on a pitch
-
+ A class to hold data on a pitch.
+
Attributes
----------
- startspeed : float
+ start_speed : float
The starting speed of the pitch.
- endspeed : float
+ end_speed : float
The ending speed of the pitch.
- strikezonetop : float
+ strike_zone_top : float
The top of the strike zone.
- strikezonebottom : float
+ strike_zone_bottom : float
The bottom of the strike zone.
coordinates : PitchCoordinates
The coordinates of the pitch.
@@ -123,240 +114,215 @@ class PitchData:
The break data of the pitch.
zone : float
The zone in which the pitch was thrown.
- typeconfidence : float
+ type_confidence : float
The confidence in the type of pitch thrown.
- platetime : float
+ plate_time : float
The amount of time the pitch was in the air.
extension : float
The extension of the pitch.
- strikezonewidth : float
- The width of the strikezone
- strikezonedepth : float
- The depth of the strikezone
+ strike_zone_width : float
+ The width of the strike zone.
+ strike_zone_depth : float
+ The depth of the strike zone.
"""
- strikezonetop: float
- strikezonebottom: float
- breaks: Union[PitchBreak, dict]
- coordinates: Optional[Union[PitchCoordinates, dict]] = field(default_factory=dict)
+ strike_zone_top: float = Field(alias="strikezonetop")
+ strike_zone_bottom: float = Field(alias="strikezonebottom")
+ breaks: PitchBreak
+ coordinates: Optional[PitchCoordinates] = None
extension: Optional[float] = None
- startspeed: Optional[float] = None
- endspeed: Optional[float] = None
+ start_speed: Optional[float] = Field(default=None, alias="startspeed")
+ end_speed: Optional[float] = Field(default=None, alias="endspeed")
zone: Optional[float] = None
- typeconfidence: Optional[float] = None
- platetime: Optional[float] = None
- strikezonewidth: Optional[float] = None
- strikezonedepth: Optional[float] = None
+ type_confidence: Optional[float] = Field(default=None, alias="typeconfidence")
+ plate_time: Optional[float] = Field(default=None, alias="platetime")
+ strike_zone_width: Optional[float] = Field(default=None, alias="strikezonewidth")
+ strike_zone_depth: Optional[float] = Field(default=None, alias="strikezonedepth")
- def __post_init__(self):
- self.coordinates = PitchCoordinates(**self.coordinates) if self.coordinates else self.coordinates
- self.breaks = PitchBreak(**self.breaks) if self.breaks else self.breaks
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-
-@dataclass
-class HitCoordinates:
+class HitCoordinates(MLBBaseModel):
"""
- A class to represent a play events hit location coordinates.
+ A class to represent a play event's hit location coordinates.
Attributes
----------
- coordx : int
- X coordinate for hit
- coordy : int
- Y coordinate for hit
+ coord_x : float
+ X coordinate for hit.
+ coord_y : float
+ Y coordinate for hit.
"""
- coordx: Optional[float] = None
- coordy: Optional[float] = None
+ coord_x: Optional[float] = Field(default=None, alias="coordx")
+ coord_y: Optional[float] = Field(default=None, alias="coordy")
@property
def x(self):
- return self.coordx
+ return self.coord_x
@property
def y(self):
- return self.coordy
+ return self.coord_y
-@dataclass(repr=False)
-class HitData:
+
+class HitData(MLBBaseModel):
"""
- A class to represent a play events hit data.
+ A class to represent a play event's hit data.
Attributes
----------
- launchspeed : float
- Hit launch speed
- launchangle : int
- Hit launch angle
- totaldistance : int
- Hits total distance
+ launch_speed : float
+ Hit launch speed.
+ launch_angle : float
+ Hit launch angle.
+ total_distance : float
+ Hit's total distance.
trajectory : str
- Hit trajectory
+ Hit trajectory.
hardness : str
- Hit hardness
- location : str
- Hit location
- coordinates : HitCoordinate
- Hit coordinates
+ Hit hardness.
+ location : int
+ Hit location.
+ coordinates : HitCoordinates
+ Hit coordinates.
"""
-
-
- coordinates: Union[HitCoordinates, dict]
+ coordinates: HitCoordinates
trajectory: Optional[str] = None
hardness: Optional[str] = None
location: Optional[int] = None
- launchspeed: Optional[float] = None
- launchangle: Optional[str] = None # this is a negative number and I'm brain farting on those
- totaldistance: Optional[float] = None
-
- def __post_init__(self):
- self.coordinates = HitCoordinates(**self.coordinates) if self.coordinates else self.coordinates
+ launch_speed: Optional[float] = Field(default=None, alias="launchspeed")
+ launch_angle: Optional[float] = Field(default=None, alias="launchangle")
+ total_distance: Optional[float] = Field(default=None, alias="totaldistance")
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-@dataclass
-class CodeDesc:
+class CodeDesc(MLBBaseModel):
"""
- a class to hold a code and a description
+ A class to hold a code and a description.
Attributes
----------
code : str
- the code to reference the attribute using this
+ The code to reference the attribute.
description : str
- the description of the attribute using this
+ The description of the attribute.
"""
code: str
description: Optional[str] = None
-@dataclass
-class Violation:
+
+class Violation(MLBBaseModel):
"""
-
+ A class to represent a violation during play.
+
Attributes
----------
type : str
- the type of violation during the play
+ The type of violation during the play.
description : str
- the description of the violation that occured
- player : player
- the player that caused the violation
+ The description of the violation that occurred.
+ player : dict
+ The player that caused the violation.
"""
type: Optional[str] = None
description: Optional[str] = None
player: Optional[dict] = None
-@dataclass(repr=False)
-class Count:
+
+class Count(MLBBaseModel):
"""
- a class to hold a pitch count and base runners
+ A class to hold a pitch count and base runners.
Attributes
----------
- code : str
- code
balls : int
- number of balls
- inning : int
- inning number
- istopinning : bool
- bool to hold status of top inning
+ Number of balls.
outs : int
- number of outs
- runneron1b : bool
- bool to hold 1b runner status
- runneron2b : bool
- bool to hold 2b runner status
- runneron3b : bool
- bool to hold 3b runner status
+ Number of outs.
strikes : int
- strike count
+ Strike count.
+ inning : int
+ Inning number.
+ is_top_inning : bool
+ Status of top inning.
+ runner_on_1b : bool
+ 1B runner status.
+ runner_on_2b : bool
+ 2B runner status.
+ runner_on_3b : bool
+ 3B runner status.
"""
balls: int
outs: int
strikes: int
inning: Optional[int] = None
- runneron1b: Optional[bool] = None
- runneron2b: Optional[bool] = None
- runneron3b: Optional[bool] = None
- istopinning: Optional[bool] = None
+ runner_on_1b: Optional[bool] = Field(default=None, alias="runneron1b")
+ runner_on_2b: Optional[bool] = Field(default=None, alias="runneron2b")
+ runner_on_3b: Optional[bool] = Field(default=None, alias="runneron3b")
+ is_top_inning: Optional[bool] = Field(default=None, alias="istopinning")
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-@dataclass(repr=False)
-class PlayDetails:
+class PlayDetails(MLBBaseModel):
"""
- A class to represent a gamelog stat for a hitter
+ A class to represent play details.
Attributes
----------
call : CodeDesc
- play call code and description
+ Play call code and description.
description : str
- description of the play
+ Description of the play.
event : str
- type of event
- eventtype : str
- type of event
- isinplay : bool
- is the ball in play true or false
- isstrike : bool
- is the ball a strike true or false
- isball : bool
- is it a ball true or false
- isbasehit : bool
- is the event a base hit true or false
- isatbat : bool
- is the event at bat true or false
- isplateappearance : bool
- is the event a at play appears true or false
+ Type of event.
+ event_type : str
+ Type of event.
+ is_in_play : bool
+ Is the ball in play.
+ is_strike : bool
+ Is the ball a strike.
+ is_ball : bool
+ Is it a ball.
+ is_base_hit : bool
+ Is the event a base hit.
+ is_at_bat : bool
+ Is the event at bat.
+ is_plate_appearance : bool
+ Is the event a plate appearance.
type : CodeDesc
- type of pitch code and description
- batside : CodeDesc
- bat side code and description
- pitchhand : CodeDesc
- pitch hand code and description
- fromcatcher : bool
+ Type of pitch code and description.
+ bat_side : CodeDesc
+ Bat side code and description.
+ pitch_hand : CodeDesc
+ Pitch hand code and description.
+ from_catcher : bool
+ From catcher flag.
"""
- call: Optional[Union[CodeDesc, dict]] = None
- isinplay: Optional[bool] = None
- isstrike: Optional[bool] = None
- isscoringplay: Optional[bool] = None
- isout: Optional[bool] = None
- runnergoing: Optional[bool] = None
- isball: Optional[bool] = None
- isbasehit: Optional[bool] = None
- isatbat: Optional[bool] = None
- isplateappearance: Optional[bool] = None
- batside: Optional[Union[CodeDesc, dict]] = field(default_factory=dict)
- pitchhand: Optional[Union[CodeDesc, dict]] = field(default_factory=dict)
- eventtype: Optional[str] = None
+ call: Optional[CodeDesc] = None
+ is_in_play: Optional[bool] = Field(default=None, alias="isinplay")
+ is_strike: Optional[bool] = Field(default=None, alias="isstrike")
+ is_scoring_play: Optional[bool] = Field(default=None, alias="isscoringplay")
+ is_out: Optional[bool] = Field(default=None, alias="isout")
+ runner_going: Optional[bool] = Field(default=None, alias="runnergoing")
+ is_ball: Optional[bool] = Field(default=None, alias="isball")
+ is_base_hit: Optional[bool] = Field(default=None, alias="isbasehit")
+ is_at_bat: Optional[bool] = Field(default=None, alias="isatbat")
+ is_plate_appearance: Optional[bool] = Field(default=None, alias="isplateappearance")
+ bat_side: Optional[CodeDesc] = Field(default=None, alias="batside")
+ pitch_hand: Optional[CodeDesc] = Field(default=None, alias="pitchhand")
+ event_type: Optional[str] = Field(default=None, alias="eventtype")
event: Optional[str] = None
description: Optional[str] = None
- type: Optional[Union[CodeDesc, dict]] = field(default_factory=dict)
- awayscore: Optional[int] = None
- homescore: Optional[int] = None
- hasreview: Optional[bool] = None
+ type: Optional[CodeDesc] = None
+ away_score: Optional[int] = Field(default=None, alias="awayscore")
+ home_score: Optional[int] = Field(default=None, alias="homescore")
+ has_review: Optional[bool] = Field(default=None, alias="hasreview")
code: Optional[str] = None
- ballcolor: Optional[str] = None
- trailcolor: Optional[str] = None
- fromcatcher: Optional[bool] = None
- disengagementnum: Optional[int] = None
- violation: Optional[Union[Violation, dict]] = field(default_factory=dict)
-
- def __post_init__(self):
- self.call = CodeDesc(**self.call) if self.call else self.call
- self.batside = CodeDesc(**self.batside) if self.batside else self.batside
- self.pitchhand = CodeDesc(**self.pitchhand) if self.pitchhand else self.pitchhand
- self.type = CodeDesc(**self.type) if self.type else self.type
- self.violation = Violation(**self.violation) if self.violation else self.violation
+ ball_color: Optional[str] = Field(default=None, alias="ballcolor")
+ trail_color: Optional[str] = Field(default=None, alias="trailcolor")
+ from_catcher: Optional[bool] = Field(default=None, alias="fromcatcher")
+ disengagement_num: Optional[int] = Field(default=None, alias="disengagementnum")
+ violation: Optional[Violation] = None
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ @field_validator('bat_side', 'pitch_hand', 'type', 'call', 'violation', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
diff --git a/mlbstatsapi/models/divisions/__init__.py b/mlbstatsapi/models/divisions/__init__.py
index 2e92696a..a8dc1256 100644
--- a/mlbstatsapi/models/divisions/__init__.py
+++ b/mlbstatsapi/models/divisions/__init__.py
@@ -1 +1,5 @@
-from .division import Division
\ No newline at end of file
+from .division import Division
+from mlbstatsapi.models.leagues import League
+
+# Rebuild to resolve forward reference to League
+Division.model_rebuild()
\ No newline at end of file
diff --git a/mlbstatsapi/models/divisions/division.py b/mlbstatsapi/models/divisions/division.py
index 3fb4b052..bedcd885 100644
--- a/mlbstatsapi/models/divisions/division.py
+++ b/mlbstatsapi/models/divisions/division.py
@@ -1,59 +1,55 @@
-from dataclasses import dataclass
-from typing import Optional, Union
-
-from mlbstatsapi.models.leagues import League
+from __future__ import annotations
+from typing import Optional, TYPE_CHECKING
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.sports import Sport
+if TYPE_CHECKING:
+ from mlbstatsapi.models.leagues import League
+
-@dataclass(repr=False)
-class Division:
+class Division(MLBBaseModel):
"""
A class to represent a division.
Attributes
----------
id : int
- id number of the divison
- name : str
- name of the division
+ ID number of the division.
link : str
- link of the division
+ API link for the division.
+ name : str
+ Name of the division.
season : str
- Current season for the division
- nameshort : str
- Short name for the division
+ Current season for the division.
+ name_short : str
+ Short name for the division.
abbreviation : str
- Abbreviation of the divison name
+ Abbreviation of the division name.
league : League
- League this division is in
+ League this division is in.
sport : Sport
- Sport this divison is in
- haswildcard : bool
- If this league has a wildcard
- sortorder : int
- Sort order
- numplayoffteams : int
- Number of playoff teams in division
+ Sport this division is in.
+ has_wildcard : bool
+ Whether this league has a wildcard.
+ sort_order : int
+ Sort order.
+ num_playoff_teams : int
+ Number of playoff teams in division.
active : bool
- Current status of this division
+ Current status of this division.
"""
id: int
link: str
name: Optional[str] = None
season: Optional[str] = None
- nameshort: Optional[str] = None
+ name_short: Optional[str] = Field(default=None, alias="nameshort")
abbreviation: Optional[str] = None
- league: Optional[Union[League, dict]] = None
- sport: Optional[Union[Sport, dict]] = None
- haswildcard: Optional[bool] = None
- sortorder: Optional[int] = None
- numplayoffteams: Optional[int] = None
+ league: Optional[League] = None
+ sport: Optional[Sport] = None
+ has_wildcard: Optional[bool] = Field(default=None, alias="haswildcard")
+ sort_order: Optional[int] = Field(default=None, alias="sortorder")
+ num_playoff_teams: Optional[int] = Field(default=None, alias="numplayoffteams")
active: Optional[bool] = None
- def __post_init__(self):
- self.league = League(**self.league) if self.league else self.league
- self.sport = Sport(**self.sport) if self.sport else self.sport
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ model_config = {"arbitrary_types_allowed": True}
diff --git a/mlbstatsapi/models/drafts/__init__.py b/mlbstatsapi/models/drafts/__init__.py
index c7f7e6af..ad4e43fe 100644
--- a/mlbstatsapi/models/drafts/__init__.py
+++ b/mlbstatsapi/models/drafts/__init__.py
@@ -1 +1,2 @@
-from .rounds import Round
\ No newline at end of file
+from .rounds import Round, DraftPick
+from .attributes import DraftHome, DraftSchool
diff --git a/mlbstatsapi/models/drafts/attributes.py b/mlbstatsapi/models/drafts/attributes.py
index 1e926a9e..460bff0f 100644
--- a/mlbstatsapi/models/drafts/attributes.py
+++ b/mlbstatsapi/models/drafts/attributes.py
@@ -1,10 +1,11 @@
-from dataclasses import dataclass, field
+from typing import Optional
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
-@dataclass
-class Home:
+class DraftHome(MLBBaseModel):
"""
- A home is a where a draft player is from
+ A class representing where a draft player is from.
Attributes
----------
@@ -16,19 +17,19 @@ class Home:
The country where the player is from.
"""
city: str
- state: str
country: str
+ state: Optional[str] = None
-@dataclass
-class School:
+
+class DraftSchool(MLBBaseModel):
"""
- Represents the school the draft player is from.
+ A class representing the school the draft player is from.
Attributes
----------
name : str
The name of the school.
- schoolclass : str
+ school_class : str
The class the student is in.
city : str
The city where the school is located.
@@ -38,7 +39,7 @@ class School:
The state where the school is located.
"""
name: str
- schoolclass: str
- city: str
country: str
- state: str
\ No newline at end of file
+ state: Optional[str] = None
+ school_class: Optional[str] = Field(default=None, alias="schoolclass")
+ city: Optional[str] = None
diff --git a/mlbstatsapi/models/drafts/rounds.py b/mlbstatsapi/models/drafts/rounds.py
index 9f549c3e..90b54ca6 100644
--- a/mlbstatsapi/models/drafts/rounds.py
+++ b/mlbstatsapi/models/drafts/rounds.py
@@ -1,97 +1,88 @@
-from dataclasses import dataclass, field
-from typing import List, Optional, Union
-
-from .attributes import School, Home
+from typing import List, Optional
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.teams import Team
from mlbstatsapi.models.people import Person
from mlbstatsapi.models.data import CodeDesc
+from .attributes import DraftSchool, DraftHome
+
-@dataclass(repr=False)
-class DraftPick:
+class DraftPick(MLBBaseModel):
"""
- Represents a pick made in the MLB draft.
+ A class representing a pick made in the MLB draft.
Attributes
----------
- bisplayerid : int
- The unique identifier of the player associated with this draft pick.
- pickround : str
+ team : Team
+ The team that made this draft pick.
+ draft_type : CodeDesc
+ Information about the type of draft in which this pick was made.
+ is_drafted : bool
+ Whether or not the player associated with this pick has been drafted.
+ is_pass : bool
+ Whether or not the team passed on making a pick in this round.
+ year : str
+ The year in which the draft took place.
+ school : DraftSchool
+ Information about the player's school or college.
+ home : DraftHome
+ Information about the player's home location.
+ pick_round : str
The round of the draft in which this pick was made.
- picknumber : int
+ pick_number : int
The number of the pick in the round.
- displaypicknumber : int
+ display_pick_number : int
The overall pick number displayed.
- roundpicknumber : int
+ round_pick_number : int
The number of the pick overall in the draft.
+ headshot_link : str
+ A link to a headshot image of the player.
+ person : Person
+ The person drafted.
+ bis_player_id : int
+ The unique identifier of the player associated with this draft pick.
rank : int
The rank of the player among all players eligible for the draft.
- pickvalue : str
+ pick_value : str
The value of the pick, if known.
- signingbonus : str
+ signing_bonus : str
The signing bonus associated with this pick, if known.
- home : Home
- Information about the player's home location.
- scoutingreport : str
- A scouting report on the player's abilities.
- school : School
- Information about the player's school or college.
+ scouting_report : str
+ A scouting report on the player's abilities.
blurb : str
- A brief summary of the player's background and accomplishments.
- headshotlink : str
- A link to a headshot image of the player.
- team : Team or dict
- The team that made this draft pick.
- drafttype : CodeDesc
- Information about the type of draft in which this pick was made.
- isdrafted : bool
- Whether or not the player associated with this pick has been drafted.
- ispass : bool
- Whether or not the team passed on making a pick in this round.
- year : str
- The year in which the draft took place.
+ A brief summary of the player's background and accomplishments.
"""
- team: Union[Team, dict]
- drafttype: Union[CodeDesc, dict]
- isdrafted: bool
- ispass: bool
+ team: Team
+ draft_type: CodeDesc = Field(alias="drafttype")
+ is_drafted: bool = Field(alias="isdrafted")
+ is_pass: bool = Field(alias="ispass")
year: str
- school: Union[School , dict]
- home: Union[Home, dict]
- pickround: str
- picknumber: int
- displaypicknumber: int
- roundpicknumber: int
- headshotlink: Optional[str] = None
- person: Optional[Union[Person, dict]] = None
- bisplayerid: Optional[int] = None
+ school: DraftSchool
+ home: DraftHome
+ pick_round: str = Field(alias="pickround")
+ pick_number: int = Field(alias="picknumber")
+ display_pick_number: int = Field(alias="displaypicknumber")
+ round_pick_number: int = Field(alias="roundpicknumber")
+ headshot_link: Optional[str] = Field(default=None, alias="headshotlink")
+ person: Optional[Person] = None
+ bis_player_id: Optional[int] = Field(default=None, alias="bisplayerid")
rank: Optional[int] = None
- pickvalue: Optional[str] = None
- signingbonus: Optional[str] = None
- scoutingreport: Optional[str] = None
+ pick_value: Optional[str] = Field(default=None, alias="pickvalue")
+ signing_bonus: Optional[str] = Field(default=None, alias="signingbonus")
+ scouting_report: Optional[str] = Field(default=None, alias="scoutingreport")
blurb: Optional[str] = None
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-@dataclass(repr=False)
-class Round:
+class Round(MLBBaseModel):
"""
- Represents a round of the MLB draft.
+ A class representing a round of the MLB draft.
Attributes
----------
round : str
The round number of the draft, represented as a string.
picks : List[DraftPick]
- A list of DraftPick objects representing the picks made in this round of the draft.
+ A list of DraftPick objects representing the picks made in this round.
"""
round: str
- picks: List[DraftPick]
-
- def __post_init__(self):
- self.picks = [DraftPick(**pick) for pick in self.picks]
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ picks: List[DraftPick] = []
diff --git a/mlbstatsapi/models/game/__init__.py b/mlbstatsapi/models/game/__init__.py
index 53426e37..97855410 100644
--- a/mlbstatsapi/models/game/__init__.py
+++ b/mlbstatsapi/models/game/__init__.py
@@ -1,5 +1,52 @@
from .game import Game
from .attributes import MetaData
-from .livedata.plays import Plays
-from .livedata.linescore import Linescore
-from .livedata.boxscore import BoxScore
+from .gamedata import (
+ GameData,
+ GameDataGame,
+ GameDatetime,
+ GameStatus,
+ GameTeams,
+ GameWeather,
+ GameInfo,
+ ReviewInfo,
+ GameReview,
+ GameFlags,
+ GameProbablePitchers,
+ MoundVisits,
+)
+from .livedata import (
+ LiveData,
+ GameDecisions,
+ GameLeaders,
+ Plays,
+ Play,
+ PlayAbout,
+ PlayResult,
+ PlayReviewDetails,
+ PlayMatchup,
+ PlayMatchupSplits,
+ PlayEvent,
+ PlayRunner,
+ RunnerMovement,
+ RunnerDetails,
+ RunnerCredits,
+ PlayByInning,
+ PlayByInningHits,
+ HitsByTeam,
+ HitCoordinates,
+ BoxScore,
+ TopPerformer,
+ BoxScoreVL,
+ BoxScoreTeamInfo,
+ BoxScoreGameStatus,
+ PlayersDictPerson,
+ BoxScoreTeam,
+ BoxScoreTeams,
+ BoxScoreOfficial,
+ Linescore,
+ LinescoreTeamScoring,
+ LinescoreInning,
+ LinescoreTeams,
+ LinescoreOffense,
+ LinescoreDefense,
+)
diff --git a/mlbstatsapi/models/game/attributes.py b/mlbstatsapi/models/game/attributes.py
index 9977e63e..26e45fcb 100644
--- a/mlbstatsapi/models/game/attributes.py
+++ b/mlbstatsapi/models/game/attributes.py
@@ -1,23 +1,24 @@
from typing import List
-from dataclasses import dataclass
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
-@dataclass
-class MetaData:
+
+class MetaData(MLBBaseModel):
"""
- A class to represent a Game's metaData.
+ A class to represent a Game's metadata.
Attributes
----------
wait : int
- No idea what this wait signifies
+ Wait value.
timestamp : str
- The timeStamp
- gameevents : List[str]
- Current game events for this game
- logicalevents : List[str]
- Current logical events for this game
+ The timestamp.
+ game_events : List[str]
+ Current game events for this game.
+ logical_events : List[str]
+ Current logical events for this game.
"""
wait: int
timestamp: str
- gameevents: List[str]
- logicalevents: List[str]
\ No newline at end of file
+ game_events: List[str] = Field(alias="gameevents")
+ logical_events: List[str] = Field(alias="logicalevents")
diff --git a/mlbstatsapi/models/game/game.py b/mlbstatsapi/models/game/game.py
index f44f6089..73ba6cf1 100644
--- a/mlbstatsapi/models/game/game.py
+++ b/mlbstatsapi/models/game/game.py
@@ -1,48 +1,35 @@
-from typing import Union, Optional
-from dataclasses import dataclass
-
+from typing import Optional
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.game.gamedata import GameData
from mlbstatsapi.models.game.livedata import LiveData
-
from .attributes import MetaData
-@dataclass
-class Game:
+class Game(MLBBaseModel):
"""
A class to represent a Game.
Attributes
----------
- gamepk : int
- id number of this game
+ game_pk : int
+ ID number of this game.
link : str
- link to the api address for this game
- copyright : str
- MLB AM copyright information
+ Link to the API address for this game.
metadata : MetaData
- metaData of this game
- gamedata : GameData
- gameData of this game
- livedata : LiveData
- liveData of this game
-
- Methods
- -------
- id():
- returns this games id
+ Metadata of this game.
+ game_data : GameData
+ Game data of this game.
+ live_data : LiveData
+ Live data of this game.
"""
- gamepk: int
+ game_pk: int = Field(alias="gamepk")
link: str
- metadata: Union[MetaData, dict]
- gamedata: Union[GameData, dict]
- livedata: Union[LiveData, dict]
-
- def __post_init__(self):
- self.metadata = MetaData(**self.metadata)
- self.gamedata = GameData(**self.gamedata)
- self.livedata = LiveData(**self.livedata)
+ metadata: Optional[MetaData] = None
+ game_data: Optional[GameData] = Field(default=None, alias="gamedata")
+ live_data: Optional[LiveData] = Field(default=None, alias="livedata")
@property
- def id(self):
- return self.gamepk
+ def id(self) -> int:
+ """Returns this game's ID."""
+ return self.game_pk
diff --git a/mlbstatsapi/models/game/gamedata/__init__.py b/mlbstatsapi/models/game/gamedata/__init__.py
index 34c840a4..db2e2b76 100644
--- a/mlbstatsapi/models/game/gamedata/__init__.py
+++ b/mlbstatsapi/models/game/gamedata/__init__.py
@@ -1,2 +1,14 @@
from .gamedata import GameData
-from .attributes import GameStatus, MoundVisits
\ No newline at end of file
+from .attributes import (
+ GameDataGame,
+ GameDatetime,
+ GameStatus,
+ GameTeams,
+ GameWeather,
+ GameInfo,
+ ReviewInfo,
+ GameReview,
+ GameFlags,
+ GameProbablePitchers,
+ MoundVisits,
+)
diff --git a/mlbstatsapi/models/game/gamedata/attributes.py b/mlbstatsapi/models/game/gamedata/attributes.py
index 9d4b32ba..f3f81e13 100644
--- a/mlbstatsapi/models/game/gamedata/attributes.py
+++ b/mlbstatsapi/models/game/gamedata/attributes.py
@@ -1,273 +1,265 @@
-from typing import Optional, Union
-from dataclasses import dataclass, field
+from typing import Optional, Any
+from pydantic import Field, field_validator
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.people import Person
from mlbstatsapi.models.teams import Team
-@dataclass
-class GameDataGame:
+class GameDataGame(MLBBaseModel):
"""
- A class to represent the this game's game info.
+ A class to represent the game's game info.
Attributes
----------
pk : int
- This game's game id
+ This game's game ID.
type : str
- This game's game type code
- doubleheader : str
- Represents if this game is a double header or not
+ This game's game type code.
+ double_header : str
+ Represents if this game is a double header or not.
id : str
- An unknown Id
- gamedaytype : str
- This game's gameday type code
+ An unknown ID.
+ gameday_type : str
+ This game's gameday type code.
tiebreaker : str
- Is this game a tie breaker
- gamenumber : int
+ Is this game a tie breaker.
+ game_number : int
The game number for this game. If double header will be 2.
- calendareventid : str
- The id for this calendar event
+ calendar_event_id : str
+ The ID for this calendar event.
season : str
- This game's season year
- seasondisplay : str
- This game's displayed season
+ This game's season year.
+ season_display : str
+ This game's displayed season.
"""
pk: int
type: str
- doubleheader: str
+ double_header: str = Field(alias="doubleheader")
id: str
- gamedaytype: str
+ gameday_type: str = Field(alias="gamedaytype")
tiebreaker: str
- gamenumber: int
- calendareventid: str
+ game_number: int = Field(alias="gamenumber")
+ calendar_event_id: str = Field(alias="calendareventid")
season: str
- seasondisplay: str
+ season_display: str = Field(alias="seasondisplay")
-@dataclass(repr=False)
-class GameDatetime:
+class GameDatetime(MLBBaseModel):
"""
A class to represent the date time for this game.
Attributes
----------
datetime : str
- Date time for this game
- originaldate : str
- The original scheduled date for this game
- officialdate : str
- The current scheduled date for this game
- daynight : str
- The current lighting condition game type
+ Date time for this game.
+ original_date : str
+ The original scheduled date for this game.
+ official_date : str
+ The current scheduled date for this game.
+ day_night : str
+ The current lighting condition game type.
time : str
- The time
+ The time.
ampm : str
- The games am or pm code
+ The game's am or pm code.
+ resume_date : str
+ Resume date if applicable.
+ resume_datetime : str
+ Resume datetime if applicable.
+ resumed_from_date : str
+ Resumed from date if applicable.
+ resumed_from_datetime : str
+ Resumed from datetime if applicable.
"""
datetime: str
- originaldate: str
- officialdate: str
- daynight: str
+ original_date: str = Field(alias="originaldate")
+ official_date: str = Field(alias="officialdate")
+ day_night: str = Field(alias="daynight")
time: str
ampm: str
- resumedate: Optional[str] = None
- resumedatetime: Optional[str] = None
- resumedfromdate: Optional[str] = None
- resumedfromdatetime: Optional[str] = None
+ resume_date: Optional[str] = Field(default=None, alias="resumedate")
+ resume_datetime: Optional[str] = Field(default=None, alias="resumedatetime")
+ resumed_from_date: Optional[str] = Field(default=None, alias="resumedfromdate")
+ resumed_from_datetime: Optional[str] = Field(default=None, alias="resumedfromdatetime")
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-@dataclass
-class GameStatus:
+class GameStatus(MLBBaseModel):
"""
A class to represent this game's game status.
Attributes
----------
- abstractgamestate : str
- The abstract game state
- codedgamestate : str
- The coded game state
- detailedstate : str
- The detailed game state
- statuscode : str
- Status code for this game
- starttimetbd : bool
- If the start time is TBD
- abstractgamecode : str
- The abstract game code
+ abstract_game_state : str
+ The abstract game state.
+ coded_game_state : str
+ The coded game state.
+ detailed_state : str
+ The detailed game state.
+ status_code : str
+ Status code for this game.
+ start_time_tbd : bool
+ If the start time is TBD.
+ abstract_game_code : str
+ The abstract game code.
reason : str
- reason for a state. Usually used for delays or cancellations
+ Reason for a state. Usually used for delays or cancellations.
"""
- abstractgamestate: str
- codedgamestate: str
- detailedstate: str
- statuscode: str
- starttimetbd: bool
- abstractgamecode: str
+ abstract_game_state: str = Field(alias="abstractgamestate")
+ coded_game_state: str = Field(alias="codedgamestate")
+ detailed_state: str = Field(alias="detailedstate")
+ status_code: str = Field(alias="statuscode")
+ start_time_tbd: bool = Field(alias="starttimetbd")
+ abstract_game_code: str = Field(alias="abstractgamecode")
reason: Optional[str] = None
-@dataclass
-class GameTeams:
+class GameTeams(MLBBaseModel):
"""
A class to represent the home and away teams.
Attributes
----------
away : Team
- Away team
+ Away team.
home : Team
- Home team
+ Home team.
"""
- away: Union[Team, dict]
- home: Union[Team, dict]
+ away: Team
+ home: Team
- def __post_init__(self):
- self.away = Team(**self.away)
- self.home = Team(**self.home)
-
-@dataclass
-class GameWeather:
+class GameWeather(MLBBaseModel):
"""
A class to represent the weather for this game.
Attributes
----------
condition : str
- The weather condition
+ The weather condition.
temp : str
- The temperature in F
+ The temperature in F.
wind : str
- The wind in MPH and the direction
+ The wind in MPH and the direction.
"""
condition: str
temp: str
wind: Optional[str] = None
-@dataclass
-class GameInfo:
+class GameInfo(MLBBaseModel):
"""
A class to represent the game info for this game.
Attributes
----------
+ first_pitch : str
+ The time of the first pitch.
attendance : int
- The attendance for this game
- firstpitch : str
- The time of the first pitch
- gamedurationminutes : int
- The duration of the game in minutes
- delaydurationminutes : int
- The length of delay for the game in minutes
+ The attendance for this game.
+ game_duration_minutes : int
+ The duration of the game in minutes.
+ delay_duration_minutes : int
+ The length of delay for the game in minutes.
"""
- firstpitch: str
+ first_pitch: str = Field(alias="firstpitch")
attendance: Optional[int] = None
- gamedurationminutes: Optional[int] = None
- delaydurationminutes: Optional[int] = None
+ game_duration_minutes: Optional[int] = Field(default=None, alias="gamedurationminutes")
+ delay_duration_minutes: Optional[int] = Field(default=None, alias="delaydurationminutes")
-@dataclass
-class ReviewInfo:
+class ReviewInfo(MLBBaseModel):
"""
- A class to represent reviewInfo for each team in this game.
+ A class to represent review info for each team in this game.
Attributes
----------
used : int
- How many challenges used
+ How many challenges used.
remaining : int
- How many challenges are remaining
+ How many challenges are remaining.
"""
used: int
remaining: int
-@dataclass
-class GameReview:
+class GameReview(MLBBaseModel):
"""
A class to represent the Game Reviews for this game.
Attributes
----------
- haschallenges : bool
- If their are challenges
+ has_challenges : bool
+ If there are challenges.
away : ReviewInfo
- Away team review info
+ Away team review info.
home : ReviewInfo
- Home team review info
+ Home team review info.
"""
- haschallenges: bool
- away: Union[ReviewInfo, dict]
- home: Union[ReviewInfo, dict]
-
- def __post_init__(self):
- self.away = ReviewInfo(**self.away)
- self.home = ReviewInfo(**self.home)
+ has_challenges: bool = Field(alias="haschallenges")
+ away: ReviewInfo
+ home: ReviewInfo
-@dataclass
-class GameFlags:
+class GameFlags(MLBBaseModel):
"""
A class to represent the flags for this game.
Attributes
----------
- nohitter : bool
- If there is a no hitter in this game
- perfectgame : bool
- If there this game is a perfect game
- awayteamnohitter : bool
- If the away team has a no hitter
- awayteamperfectgame : bool
- If the away team has a perfect game
- hometeamnohitter : bool
- If the home team has a no hitter
- hometeamperfectgame : bool
- If the home team has a perfect game
+ no_hitter : bool
+ If there is a no hitter in this game.
+ perfect_game : bool
+ If this game is a perfect game.
+ away_team_no_hitter : bool
+ If the away team has a no hitter.
+ away_team_perfect_game : bool
+ If the away team has a perfect game.
+ home_team_no_hitter : bool
+ If the home team has a no hitter.
+ home_team_perfect_game : bool
+ If the home team has a perfect game.
"""
- nohitter: bool
- perfectgame: bool
- awayteamnohitter: bool
- awayteamperfectgame: bool
- hometeamnohitter: bool
- hometeamperfectgame: bool
+ no_hitter: bool = Field(alias="nohitter")
+ perfect_game: bool = Field(alias="perfectgame")
+ away_team_no_hitter: bool = Field(alias="awayteamnohitter")
+ away_team_perfect_game: bool = Field(alias="awayteamperfectgame")
+ home_team_no_hitter: bool = Field(alias="hometeamnohitter")
+ home_team_perfect_game: bool = Field(alias="hometeamperfectgame")
-@dataclass
-class GameProbablePitchers:
+class GameProbablePitchers(MLBBaseModel):
"""
A class to represent the home and away probable pitchers for this game.
Attributes
----------
home : Person
- Home team probable pitcher
+ Home team probable pitcher.
away : Person
- Away team probable pitcher
+ Away team probable pitcher.
"""
- away: Union[Person, dict] = field(default_factory=dict)
- home: Union[Person, dict] = field(default_factory=dict)
+ away: Optional[Person] = None
+ home: Optional[Person] = None
- def __post_init__(self):
- self.away = Person(**self.away) if self.away else self.away
- self.home = Person(**self.home) if self.home else self.home
+ @field_validator('away', 'home', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
-@dataclass
-class MoundVisits:
+
+class MoundVisits(MLBBaseModel):
"""
- A class to represent the mound visits for a game
+ A class to represent the mound visits for a game.
+
Attributes
----------
- home : Person
- Home team probable pitcher
- away : Person
- Away team probable pitcher
+ home : dict
+ Home team mound visits.
+ away : dict
+ Away team mound visits.
"""
- away: dict = field(default_factory=dict)
- home: dict = field(default_factory=dict)
-
+ away: dict = {}
+ home: dict = {}
diff --git a/mlbstatsapi/models/game/gamedata/gamedata.py b/mlbstatsapi/models/game/gamedata/gamedata.py
index e76e09ec..71e3b148 100644
--- a/mlbstatsapi/models/game/gamedata/gamedata.py
+++ b/mlbstatsapi/models/game/gamedata/gamedata.py
@@ -1,96 +1,98 @@
-from typing import Optional, Union, List
-from dataclasses import dataclass, field
+from typing import Optional, List, Dict, Any
+from pydantic import Field, field_validator, model_validator
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.venues import Venue
from mlbstatsapi.models.people import Person
+from .attributes import (
+ GameDataGame,
+ GameDatetime,
+ GameStatus,
+ GameTeams,
+ GameWeather,
+ GameInfo,
+ GameReview,
+ GameFlags,
+ GameProbablePitchers,
+ MoundVisits,
+)
-from .attributes import GameDataGame
-from .attributes import GameDatetime
-from .attributes import GameStatus
-from .attributes import GameTeams
-from .attributes import GameWeather
-from .attributes import GameInfo
-from .attributes import GameReview
-from .attributes import GameFlags
-from .attributes import GameProbablePitchers
-from .attributes import MoundVisits
-@dataclass(repr=False)
-class GameData:
+class GameData(MLBBaseModel):
"""
- A class to represent a games game data.
+ A class to represent a game's game data.
Attributes
----------
game : GameDataGame
- game information about this game
+ Game information about this game.
datetime : GameDatetime
- Time and dates for this game
+ Time and dates for this game.
status : GameStatus
- information on this game's status
+ Information on this game's status.
teams : GameTeams
- Our two teams for this game, home and away
+ Our two teams for this game, home and away.
players : List[Person]
- A list of all the players for this game
+ A list of all the players for this game.
venue : Venue
- Venue information for this game
- officialvenue : Venue
- The official venue for this game
+ Venue information for this game.
+ official_venue : Venue
+ The official venue for this game.
weather : GameWeather
The weather for this game.
- gameinfo : GameInfo
- information on this game
+ game_info : GameInfo
+ Information on this game.
review : GameReview
- Game review info and team challenges
+ Game review info and team challenges.
flags : GameFlags
- Flag bools for this game
- alerts : List[]
- Alerts
- probablepitchers : GameProbablePitchers
- Home and away probable pitchers for this game
- officialscorer : Person
- The official scorer for this game
- primarydatacaster : Person
- The official dataCaster for this game
+ Flag bools for this game.
+ alerts : List
+ Alerts.
+ probable_pitchers : GameProbablePitchers
+ Home and away probable pitchers for this game.
+ official_scorer : Person
+ The official scorer for this game.
+ primary_data_caster : Person
+ The official data caster for this game.
+ secondary_data_caster : Person
+ Secondary data caster for this game.
+ mound_visits : MoundVisits
+ Mound visits for this game.
+ abs_challenges : List[dict]
+ ABS challenges for this game.
"""
+ game: GameDataGame
+ datetime: GameDatetime
+ status: GameStatus
+ teams: GameTeams
+ players: List[Person] = []
+ venue: Venue
+ official_venue: Venue = Field(alias="officialvenue")
+ review: GameReview
+ flags: GameFlags
+ alerts: List = []
+ probable_pitchers: GameProbablePitchers = Field(alias="probablepitchers")
+ mound_visits: Optional[MoundVisits] = Field(default=None, alias="moundvisits")
+ game_info: Optional[GameInfo] = Field(default=None, alias="gameinfo")
+ weather: Optional[GameWeather] = None
+ official_scorer: Optional[Person] = Field(default=None, alias="officialscorer")
+ primary_data_caster: Optional[Person] = Field(default=None, alias="primarydatacaster")
+ secondary_data_caster: Optional[Person] = Field(default=None, alias="secondarydatacaster")
+ abs_challenges: Optional[List[dict]] = Field(default=None, alias="abschallenges")
- game: Union[GameDataGame, dict]
- datetime: Union[GameDatetime, dict]
- status: Union[GameStatus, dict]
- teams: Union[GameTeams, dict]
- players: Union[List[Person], dict]
- venue: Union[Venue, dict]
- officialvenue: Union[Venue, dict]
- review: Union[GameReview, dict]
- flags: Union[GameFlags, dict]
- alerts: List
- probablepitchers: Union[GameProbablePitchers, dict]
- moundvisits: Optional[Union[MoundVisits, dict]] = None
- gameinfo: Union[GameInfo, dict] = field(default_factory=dict)
- weather: Union[GameWeather, dict] = field(default_factory=dict)
- officialscorer: Optional[Union[Person, dict]] = field(default_factory=dict)
- primarydatacaster: Optional[Union[Person, dict]] = field(default_factory=dict)
- secondarydatacaster: Optional[Union[Person, dict]] = field(default_factory=dict)
- abschallenges: Optional[Union[List[dict], dict]] = field(default_factory=dict)
-
- def __post_init__(self):
- self.game = GameDataGame(**self.game)
- self.datetime = GameDatetime(**self.datetime)
- self.status = GameStatus(**self.status)
- self.teams = GameTeams(**self.teams)
- self.players = [Person(**(self.players[key])) for key in self.players]
- self.venue = Venue(**self.venue)
- self.officialvenue = Venue(**self.officialvenue)
- self.weather = GameWeather(**self.weather) if self.weather else self.weather
- self.gameinfo = GameInfo(**self.gameinfo) if self.gameinfo else self.gameinfo
- self.review = GameReview(**self.review)
- self.flags = GameFlags(**self.flags)
- self.probablepitchers = GameProbablePitchers(**self.probablepitchers)
- self.officialscorer = Person(**self.officialscorer) if self.officialscorer else self.officialscorer
- self.primarydatacaster = Person(**self.primarydatacaster) if self.primarydatacaster else self.primarydatacaster
- self.secondarydatacaster = Person(**self.secondarydatacaster) if self.secondarydatacaster else self.secondarydatacaster
- self.moundvisits = MoundVisits(**self.moundvisits) if self.moundvisits else self.moundvisits
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
+ @model_validator(mode='before')
+ @classmethod
+ def handle_players_dict(cls, data: Dict[str, Any]) -> Dict[str, Any]:
+ """Convert players dict to list of Person objects."""
+ if isinstance(data, dict) and 'players' in data:
+ players_data = data['players']
+ if isinstance(players_data, dict):
+ data['players'] = list(players_data.values())
+ return data
+ @field_validator('weather', 'game_info', 'official_scorer', 'primary_data_caster', 'secondary_data_caster', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
diff --git a/mlbstatsapi/models/game/livedata/__init__.py b/mlbstatsapi/models/game/livedata/__init__.py
index b67d7512..6c206e67 100644
--- a/mlbstatsapi/models/game/livedata/__init__.py
+++ b/mlbstatsapi/models/game/livedata/__init__.py
@@ -1 +1,39 @@
from .livedata import LiveData
+from .attributes import GameDecisions, GameLeaders
+from .plays import (
+ Plays,
+ Play,
+ PlayAbout,
+ PlayResult,
+ PlayReviewDetails,
+ PlayMatchup,
+ PlayMatchupSplits,
+ PlayEvent,
+ PlayRunner,
+ RunnerMovement,
+ RunnerDetails,
+ RunnerCredits,
+ PlayByInning,
+ PlayByInningHits,
+ HitsByTeam,
+ HitCoordinates,
+)
+from .boxscore import (
+ BoxScore,
+ TopPerformer,
+ BoxScoreVL,
+ BoxScoreTeamInfo,
+ BoxScoreGameStatus,
+ PlayersDictPerson,
+ BoxScoreTeam,
+ BoxScoreTeams,
+ BoxScoreOfficial,
+)
+from .linescore import (
+ Linescore,
+ LinescoreTeamScoring,
+ LinescoreInning,
+ LinescoreTeams,
+ LinescoreOffense,
+ LinescoreDefense,
+)
diff --git a/mlbstatsapi/models/game/livedata/attributes.py b/mlbstatsapi/models/game/livedata/attributes.py
index 3bb038ba..88c22d30 100644
--- a/mlbstatsapi/models/game/livedata/attributes.py
+++ b/mlbstatsapi/models/game/livedata/attributes.py
@@ -1,51 +1,41 @@
-from typing import Union, Optional
-from dataclasses import dataclass
+from typing import Optional
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.people import Person
-@dataclass(repr=False)
-class GameDecisions:
+class GameDecisions(MLBBaseModel):
"""
- A class to represent the winning and loosing pitcher for this game.
+ A class to represent the winning and losing pitcher for this game.
Only used when a game is over.
Attributes
----------
winner : Person
- The winning person
+ The winning pitcher.
loser : Person
- The loosing person
+ The losing pitcher.
+ save : Person
+ The save pitcher (if applicable).
"""
- winner: Union[Person, dict]
- loser: Union[Person, dict]
- save: Optional[Union[Person, dict]] = None
+ winner: Person
+ loser: Person
+ save: Optional[Person] = None
- def __post_init__(self):
- self.winner = Person(**self.winner)
- self.loser = Person(**self.loser)
- self.save = Person(**self.save) if self.save else self.save
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-
-@dataclass
-class GameLeaders:
+class GameLeaders(MLBBaseModel):
"""
- A class to represent this games live data leaders.
- Not sure what this data looks like since every game ive seen
- has an empty dict for each of these.
+ A class to represent this game's live data leaders.
Attributes
----------
- hitdistance : dict
- hit distance
- hitspeed : dict
- hit speed
- pitchspeed : dict
- pitch speed
+ hit_distance : dict
+ Hit distance leaders.
+ hit_speed : dict
+ Hit speed leaders.
+ pitch_speed : dict
+ Pitch speed leaders.
"""
- # Dont know what this populated looks like. Every game ive seen its three empty dicts?
- hitdistance: dict
- hitspeed: dict
- pitchspeed: dict
\ No newline at end of file
+ hit_distance: dict = Field(alias="hitdistance")
+ hit_speed: dict = Field(alias="hitspeed")
+ pitch_speed: dict = Field(alias="pitchspeed")
diff --git a/mlbstatsapi/models/game/livedata/boxscore/__init__.py b/mlbstatsapi/models/game/livedata/boxscore/__init__.py
index cc041c3f..9513019e 100644
--- a/mlbstatsapi/models/game/livedata/boxscore/__init__.py
+++ b/mlbstatsapi/models/game/livedata/boxscore/__init__.py
@@ -1 +1,10 @@
-from .boxscore import BoxScore
+from .boxscore import BoxScore, TopPerformer
+from .attributes import (
+ BoxScoreVL,
+ BoxScoreTeamInfo,
+ BoxScoreGameStatus,
+ PlayersDictPerson,
+ BoxScoreTeam,
+ BoxScoreTeams,
+ BoxScoreOfficial,
+)
diff --git a/mlbstatsapi/models/game/livedata/boxscore/attributes.py b/mlbstatsapi/models/game/livedata/boxscore/attributes.py
index 3ef15008..0806d7f7 100644
--- a/mlbstatsapi/models/game/livedata/boxscore/attributes.py
+++ b/mlbstatsapi/models/game/livedata/boxscore/attributes.py
@@ -1,68 +1,63 @@
-from typing import Union, List, Optional
-from dataclasses import dataclass, field
+from typing import List, Optional, Dict, Any
+from pydantic import Field, field_validator
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.people import Person, Position
from mlbstatsapi.models.teams import Team
from mlbstatsapi.models.data import CodeDesc
-@dataclass
-class BoxScoreVL:
+class BoxScoreVL(MLBBaseModel):
"""
- A class to represent a boxscore team's infos label and value
+ A class to represent a boxscore team's info label and value.
Attributes
----------
label : str
- The label for this peice of info
+ The label for this piece of info.
value : str
- The info associated with this label
+ The info associated with this label.
"""
label: str
- value: str = None
+ value: Optional[str] = None
-@dataclass
-class BoxScoreTeamInfo:
+class BoxScoreTeamInfo(MLBBaseModel):
"""
- A class to represent a boxscore team's info
+ A class to represent a boxscore team's info.
Attributes
----------
title : str
- Type of information
- fieldlist : List[BoxScoreVL]
- List holding the info for this info type
+ Type of information.
+ field_list : List[BoxScoreVL]
+ List holding the info for this info type.
"""
title: str
- fieldlist: Union[List[BoxScoreVL], List[dict]]
+ field_list: List[BoxScoreVL] = Field(alias="fieldlist")
- def __post_init__(self):
- self.fieldlist = [BoxScoreVL(**fieldlists) for fieldlists in self.fieldlist]
-
-@dataclass
-class GameStatus:
+class BoxScoreGameStatus(MLBBaseModel):
"""
A class representing the game status of a player.
Attributes
----------
- iscurrentbatter : bool
+ is_current_batter : bool
Whether the player is the current batter.
- iscurrentpitcher : bool
+ is_current_pitcher : bool
Whether the player is the current pitcher.
- isonbench : bool
+ is_on_bench : bool
Whether the player is on the bench.
- issubstitute : bool
+ is_substitute : bool
Whether the player is a substitute.
"""
- iscurrentbatter: bool
- iscurrentpitcher: bool
- isonbench: bool
- issubstitute: bool
+ is_current_batter: bool = Field(alias="iscurrentbatter")
+ is_current_pitcher: bool = Field(alias="iscurrentpitcher")
+ is_on_bench: bool = Field(alias="isonbench")
+ is_substitute: bool = Field(alias="issubstitute")
+
-@dataclass
-class PlayersDictPerson:
+class PlayersDictPerson(MLBBaseModel):
"""
A class representing a person in a dictionary of players.
@@ -70,122 +65,101 @@ class PlayersDictPerson:
----------
person : Person
The person object.
- jerseynumber : str
+ jersey_number : str
The person's jersey number.
position : Position
The person's position.
status : CodeDesc
The person's status.
- parentteamid : int
+ parent_team_id : int
The ID of the person's parent team.
stats : dict
A dictionary of the person's stats.
- seasonstats : dict
+ season_stats : dict
A dictionary of the person's season stats.
- gameStatus : GameStatus
+ game_status : BoxScoreGameStatus
The person's game status.
- battingorder : int
- The persons place in the batting order if avaliable.
- allpositions : Position
- All of the person's positions if avaliable.
+ batting_order : int
+ The person's place in the batting order if available.
+ all_positions : List[Position]
+ All of the person's positions if available.
"""
- person: Union[Person, dict]
- status: Union[CodeDesc, dict]
+ person: Person
+ status: CodeDesc
stats: dict
- seasonstats: dict
- gamestatus: Union[GameStatus, dict]
- position: Optional[Union[Position, dict]] = None
- battingorder: Optional[int] = None
- jerseynumber: Optional[str] = None
- parentteamid: Optional[int] = None
- allpositions: Optional[Union[List[Position], List[dict]]] = None
-
- def __post_init__(self):
- self.person = Person(**self.person)
- self.position = Position(**self.position) if self.position else self.position
- self.status = CodeDesc(**self.status)
- self.gamestatus = GameStatus(**self.gamestatus)
- self.allpositions = [Position(**allposition) for allposition in self.allpositions] if self.allpositions else self.allpositions
-
-@dataclass
-class BoxScoreTeam:
+ season_stats: dict = Field(alias="seasonstats")
+ game_status: BoxScoreGameStatus = Field(alias="gamestatus")
+ position: Optional[Position] = None
+ batting_order: Optional[int] = Field(default=None, alias="battingorder")
+ jersey_number: Optional[str] = Field(default=None, alias="jerseynumber")
+ parent_team_id: Optional[int] = Field(default=None, alias="parentteamid")
+ all_positions: Optional[List[Position]] = Field(default=None, alias="allpositions")
+
+
+class BoxScoreTeam(MLBBaseModel):
"""
- A class to represent the boxscore team
+ A class to represent the boxscore team.
Attributes
----------
team : Team
- This team
- teamstats : Dict
- Team stats
- players : Dict
- Players on team
+ This team.
+ team_stats : dict
+ Team stats.
+ players : dict
+ Players on team.
batters : List[int]
- List of batters playerid for this team
+ List of batter player IDs for this team.
pitchers : List[int]
- List of pitcher playerid for this team
+ List of pitcher player IDs for this team.
bench : List[int]
- List of bench playerid for this team
+ List of bench player IDs for this team.
bullpen : List[int]
- Bullpen list of playerid
- battingorder : List[int]
- Batting order for this team as a list of playerid
+ Bullpen list of player IDs.
+ batting_order : List[int]
+ Batting order for this team as a list of player IDs.
info : List[BoxScoreTeamInfo]
- Batting and fielding info for team
- note : List[str]
- Team notes
+ Batting and fielding info for team.
+ note : List[BoxScoreVL]
+ Team notes.
"""
- team: Union[Team, dict]
- teamstats: dict
- players: dict
+ team: Team
+ team_stats: dict = Field(alias="teamstats")
+ players: Dict[str, PlayersDictPerson]
batters: List[int]
pitchers: List[int]
bench: List[int]
bullpen: List[int]
- battingorder: List[int]
- info: Union[List[BoxScoreTeamInfo], List[dict]]
- note: List[str]
-
- def __post_init__(self):
- self.team = Team(**self.team)
- self.info = [BoxScoreTeamInfo(**infos) for infos in self.info]
+ batting_order: List[int] = Field(alias="battingorder")
+ info: List[BoxScoreTeamInfo]
+ note: List[BoxScoreVL] = []
- for player in self.players:
- self.players[player] = PlayersDictPerson(**self.players[player])
-@dataclass
-class BoxScoreTeams:
+class BoxScoreTeams(MLBBaseModel):
"""
- A class to represent the boxscore home and away teams
+ A class to represent the boxscore home and away teams.
Attributes
----------
home : BoxScoreTeam
- Home team boxscore information
+ Home team boxscore information.
away : BoxScoreTeam
- Away team boxscore information
+ Away team boxscore information.
"""
- home: Union[BoxScoreTeam, dict]
- away: Union[BoxScoreTeam, dict]
+ home: BoxScoreTeam
+ away: BoxScoreTeam
- def __post_init__(self):
- self.home = BoxScoreTeam(**self.home)
- self.away = BoxScoreTeam(**self.away)
-@dataclass
-class BoxScoreOffical:
+class BoxScoreOfficial(MLBBaseModel):
"""
- A class to represent an official for this game
+ A class to represent an official for this game.
Attributes
----------
official : Person
- The official person
- officialtype : str
- What type of official this person is
+ The official person.
+ official_type : str
+ What type of official this person is.
"""
- official: Union[Person, dict]
- officialtype: str
-
- def __post_init__(self):
- self.official = Person(**self.official)
+ official: Person
+ official_type: str = Field(alias="officialtype")
diff --git a/mlbstatsapi/models/game/livedata/boxscore/boxscore.py b/mlbstatsapi/models/game/livedata/boxscore/boxscore.py
index 3838c5c0..c906852e 100644
--- a/mlbstatsapi/models/game/livedata/boxscore/boxscore.py
+++ b/mlbstatsapi/models/game/livedata/boxscore/boxscore.py
@@ -1,62 +1,52 @@
-from typing import Union, List, Any, Optional
-from dataclasses import dataclass, field
+from typing import List, Optional
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
+from .attributes import BoxScoreTeams, BoxScoreOfficial, BoxScoreVL, PlayersDictPerson
-from .attributes import BoxScoreTeams, BoxScoreOffical, BoxScoreVL, PlayersDictPerson
-
-
-@dataclass
-class TopPerformer:
+class TopPerformer(MLBBaseModel):
"""
- A class to represent this games topperformer
+ A class to represent this game's top performer.
Attributes
----------
- player : Player
- Player
+ player : PlayersDictPerson
+ Player.
type : str
- The officials for this game
- gamescore : int
- gamescore
- hittinggamescore : int
- hitting game score
+ The type of top performer.
+ game_score : int
+ Game score.
+ hitting_game_score : int
+ Hitting game score.
+ pitching_game_score : int
+ Pitching game score.
"""
- player: Union[PlayersDictPerson, dict]
+ player: PlayersDictPerson
type: str
- gamescore: int
- hittinggamescore: Optional[int] = None
- pitchinggamescore: Optional[int] = None
-
- def __post_init__(self):
- self.player = PlayersDictPerson(**self.player)
+ game_score: int = Field(alias="gamescore")
+ hitting_game_score: Optional[int] = Field(default=None, alias="hittinggamescore")
+ pitching_game_score: Optional[int] = Field(default=None, alias="pitchinggamescore")
-@dataclass
-class BoxScore:
+
+class BoxScore(MLBBaseModel):
"""
- A class to represent this games boxscore
+ A class to represent this game's boxscore.
Attributes
----------
teams : BoxScoreTeams
- Box score data for each team
- officials : List[BoxScoreOffical]
- The officials for this game
+ Box score data for each team.
+ officials : List[BoxScoreOfficial]
+ The officials for this game.
info : List[BoxScoreVL]
- Box score information
- pitchingnotes : List[str]
- Pitching notes for this game
+ Box score information.
+ pitching_notes : List[str]
+ Pitching notes for this game.
+ top_performers : List[TopPerformer]
+ Top performers for this game.
"""
-
- teams: Union[BoxScoreTeams, dict]
- officials: Union[List[BoxScoreOffical], List[dict]]
- info: Union[List[BoxScoreVL], List[dict]]
- pitchingnotes: List[str]
- topperformers: Optional[List[Union[TopPerformer, dict]]] = field(default_factory=list)
-
- def __post_init__(self):
- self.teams = BoxScoreTeams(**self.teams)
- self.officials = [BoxScoreOffical(**official) for official in self.officials]
- self.info = [BoxScoreVL(**infos) for infos in self.info]
- self.topperformers = [TopPerformer(**topperformer) for topperformer in self.topperformers]
-
-
+ teams: BoxScoreTeams
+ officials: List[BoxScoreOfficial] = []
+ info: List[BoxScoreVL] = []
+ pitching_notes: List[str] = Field(default=[], alias="pitchingnotes")
+ top_performers: List[TopPerformer] = Field(default=[], alias="topperformers")
diff --git a/mlbstatsapi/models/game/livedata/linescore/__init__.py b/mlbstatsapi/models/game/livedata/linescore/__init__.py
index 09b4b432..b13122cf 100644
--- a/mlbstatsapi/models/game/livedata/linescore/__init__.py
+++ b/mlbstatsapi/models/game/livedata/linescore/__init__.py
@@ -1 +1,8 @@
from .linescore import Linescore
+from .attributes import (
+ LinescoreTeamScoring,
+ LinescoreInning,
+ LinescoreTeams,
+ LinescoreOffense,
+ LinescoreDefense,
+)
diff --git a/mlbstatsapi/models/game/livedata/linescore/attributes.py b/mlbstatsapi/models/game/livedata/linescore/attributes.py
index 71bf2f29..429a3b99 100644
--- a/mlbstatsapi/models/game/livedata/linescore/attributes.py
+++ b/mlbstatsapi/models/game/livedata/linescore/attributes.py
@@ -1,184 +1,188 @@
-from typing import Union, Optional
-from dataclasses import dataclass, field
+from typing import Optional, Any
+from pydantic import Field, field_validator
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.people import Person
from mlbstatsapi.models.teams import Team
-@dataclass
-class LinescoreTeamScoreing:
+
+class LinescoreTeamScoring(MLBBaseModel):
"""
- A class to represent a games Linescore
+ A class to represent a games linescore team scoring.
Attributes
----------
hits : int
- Team hits for this inning
+ Team hits for this inning.
errors : int
- Team errors for this inning
- leftonbase : int
- Player left on base for this inning
+ Team errors for this inning.
+ left_on_base : int
+ Players left on base for this inning.
runs : int
- Team runs for this inning
- iswinner : bool
- If team is winner
+ Team runs for this inning.
+ is_winner : bool
+ If team is winner.
"""
hits: int
errors: int
- leftonbase: int
+ left_on_base: int = Field(alias="leftonbase")
runs: Optional[int] = None
- iswinner: Optional[bool] = None
+ is_winner: Optional[bool] = Field(default=None, alias="iswinner")
+
-@dataclass
-class LinescoreInning:
+class LinescoreInning(MLBBaseModel):
"""
- A class to represent a inning for a games Linescore
+ A class to represent an inning for a game's linescore.
Attributes
----------
num : int
- Inning number
- ordinalnum : str
- Inning ordinal
- home : LinescoreTeamScoreing
- Home team inning info
- away : LinescoreTeamScoreing
- Away team inning info
+ Inning number.
+ ordinal_num : str
+ Inning ordinal.
+ home : LinescoreTeamScoring
+ Home team inning info.
+ away : LinescoreTeamScoring
+ Away team inning info.
"""
num: int
- ordinalnum: str
- home: Union[LinescoreTeamScoreing, dict]
- away: Union[LinescoreTeamScoreing, dict]
+ ordinal_num: str = Field(alias="ordinalnum")
+ home: Optional[LinescoreTeamScoring] = None
+ away: Optional[LinescoreTeamScoring] = None
- def __post_init__(self):
- self.home = LinescoreTeamScoreing(**self.home) if self.home else self.home
- self.away = LinescoreTeamScoreing(**self.away) if self.away else self.away
+ @field_validator('home', 'away', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
-@dataclass
-class LinescoreTeams:
+
+class LinescoreTeams(MLBBaseModel):
"""
- A class to represent home and away teams in the linescore
+ A class to represent home and away teams in the linescore.
Attributes
----------
- home : LinescoreTeamScoreing
- Home team current inning info
- away : LinescoreTeamScoreing
- Away team current inning info
+ home : LinescoreTeamScoring
+ Home team current inning info.
+ away : LinescoreTeamScoring
+ Away team current inning info.
"""
- home: Union[LinescoreTeamScoreing, dict] = field(default_factory=dict)
- away: Union[LinescoreTeamScoreing, dict] = field(default_factory=dict)
+ home: Optional[LinescoreTeamScoring] = None
+ away: Optional[LinescoreTeamScoring] = None
+
+ @field_validator('home', 'away', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
- def __post_init__(self):
- self.home = LinescoreTeamScoreing(**self.home) if self.home else self.home
- self.away = LinescoreTeamScoreing(**self.away) if self.away else self.away
-@dataclass(repr=False)
-class LinescoreOffense:
+class LinescoreOffense(MLBBaseModel):
"""
- A class to represent a games current offense
+ A class to represent a game's current offense.
Attributes
----------
batter : Person
- Current batter
- ondeck : Person
- Current on deck batter
- inhole : Person
- Current in the hole batter
+ Current batter.
+ on_deck : Person
+ Current on deck batter.
+ in_hole : Person
+ Current in the hole batter.
pitcher : Person
- Who is this teams pitcher
- battingorder : int
- Number in the batting order
+ Who is this team's pitcher.
+ batting_order : int
+ Number in the batting order.
team : Team
- The team currently on offense
+ The team currently on offense.
+ first : str
+ Runner on first (if any).
+ second : str
+ Runner on second (if any).
+ third : str
+ Runner on third (if any).
"""
- team: Union[Team, dict]
- batter: Optional[Union[Person, dict]] = field(default_factory=dict)
- ondeck: Optional[Union[Person, dict]] = field(default_factory=dict)
- inhole: Optional[Union[Person, dict]] = field(default_factory=dict)
- pitcher: Optional[Union[Person, dict]] = field(default_factory=dict)
- battingorder: Optional[int] = None
+ team: Team
+ batter: Optional[Person] = None
+ on_deck: Optional[Person] = Field(default=None, alias="ondeck")
+ in_hole: Optional[Person] = Field(default=None, alias="inhole")
+ pitcher: Optional[Person] = None
+ batting_order: Optional[int] = Field(default=None, alias="battingorder")
first: Optional[str] = None
second: Optional[str] = None
third: Optional[str] = None
- def __post_init__(self):
- self.batter = Person(**self.batter) if self.batter else self.batter
- self.ondeck = Person(**self.ondeck) if self.ondeck else self.ondeck
- self.inhole = Person(**self.inhole) if self.inhole else self.inhole
- self.pitcher = Person(**self.pitcher) if self.pitcher else self.pitcher
- self.team = Team(**self.team)
+ @field_validator('batter', 'on_deck', 'in_hole', 'pitcher', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-@dataclass(repr=False)
-class LinescoreDefense:
+class LinescoreDefense(MLBBaseModel):
"""
- A class to represent a games current defense
+ A class to represent a game's current defense.
Attributes
----------
pitcher : Person
- Current pitcher
+ Current pitcher.
catcher : Person
- Current catcher
+ Current catcher.
first : Person
- Current first
+ Current first baseman.
second : Person
- Current second
+ Current second baseman.
third : Person
- Current third
+ Current third baseman.
shortstop : Person
- Current shortstop
+ Current shortstop.
left : Person
- Current left
+ Current left fielder.
center : Person
- Current center
+ Current center fielder.
right : Person
- Current right
+ Current right fielder.
batter : Person
- The next batter when this team switches to offense
- ondeck : Person
- The next ondeck batter when this team switches to offense
- inhole : Person
- The next inHole batter when this team switches to offense
- battingorder : int
- Number this team is in the batting order
+ The next batter when this team switches to offense.
+ on_deck : Person
+ The next on deck batter when this team switches to offense.
+ in_hole : Person
+ The next in hole batter when this team switches to offense.
+ batting_order : int
+ Number this team is in the batting order.
team : Team
- The team that is playing defense currently
+ The team that is playing defense currently.
"""
- team: Union[Team, dict]
- pitcher: Optional[Union[Person, dict]] = field(default_factory=dict)
- catcher: Optional[Union[Person, dict]] = field(default_factory=dict)
- first: Optional[Union[Person, dict]] = field(default_factory=dict)
- second: Optional[Union[Person, dict]] = field(default_factory=dict)
- third: Optional[Union[Person, dict]] = field(default_factory=dict)
- shortstop: Optional[Union[Person, dict]] = field(default_factory=dict)
- left: Optional[Union[Person, dict]] = field(default_factory=dict)
- center: Optional[Union[Person, dict]] = field(default_factory=dict)
- right: Optional[Union[Person, dict]] = field(default_factory=dict)
- batter: Optional[Union[Person, dict]] = field(default_factory=dict)
- ondeck: Optional[Union[Person, dict]] = field(default_factory=dict)
- inhole: Optional[Union[Person, dict]] = field(default_factory=dict)
- battingorder: int = None
-
-
- def __post_init__(self):
- self.pitcher = Person(**self.pitcher) if self.pitcher else self.pitcher
- self.catcher = Person(**self.catcher) if self.catcher else self.catcher
- self.first = Person(**self.first) if self.first else self.first
- self.second = Person(**self.second) if self.second else self.second
- self.third = Person(**self.third) if self.third else self.third
- self.shortstop = Person(**self.shortstop) if self.shortstop else self.shortstop
- self.left = Person(**self.left) if self.left else self.left
- self.center = Person(**self.center) if self.center else self.center
- self.right = Person(**self.right) if self.right else self.right
- self.batter = Person(**self.batter) if self.batter else self.batter
- self.ondeck = Person(**self.ondeck) if self.ondeck else self.ondeck
- self.inhole = Person(**self.inhole) if self.inhole else self.inhole
- self.team = Team(**self.team)
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ team: Team
+ pitcher: Optional[Person] = None
+ catcher: Optional[Person] = None
+ first: Optional[Person] = None
+ second: Optional[Person] = None
+ third: Optional[Person] = None
+ shortstop: Optional[Person] = None
+ left: Optional[Person] = None
+ center: Optional[Person] = None
+ right: Optional[Person] = None
+ batter: Optional[Person] = None
+ on_deck: Optional[Person] = Field(default=None, alias="ondeck")
+ in_hole: Optional[Person] = Field(default=None, alias="inhole")
+ batting_order: Optional[int] = Field(default=None, alias="battingorder")
+
+ @field_validator(
+ 'pitcher', 'catcher', 'first', 'second', 'third', 'shortstop',
+ 'left', 'center', 'right', 'batter', 'on_deck', 'in_hole',
+ mode='before'
+ )
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
diff --git a/mlbstatsapi/models/game/livedata/linescore/linescore.py b/mlbstatsapi/models/game/livedata/linescore/linescore.py
index c89338d4..fba9dc38 100644
--- a/mlbstatsapi/models/game/livedata/linescore/linescore.py
+++ b/mlbstatsapi/models/game/livedata/linescore/linescore.py
@@ -1,67 +1,60 @@
-from typing import Union, List, Optional
-from dataclasses import dataclass
+from typing import List, Optional
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
+from .attributes import (
+ LinescoreInning,
+ LinescoreTeams,
+ LinescoreDefense,
+ LinescoreOffense,
+)
-from .attributes import LinescoreInning
-from .attributes import LinescoreTeams
-from .attributes import LinescoreDefense
-from .attributes import LinescoreOffense
-@dataclass(repr=False)
-class Linescore:
+class Linescore(MLBBaseModel):
"""
- A class to represent a games Linescore
+ A class to represent a game's linescore.
Attributes
----------
- currentinning : int
- The games current inning
- currentinningordinal : str
- This innings ordinal
- inningstate : str
- What state this inning is in
- inninghalf : str
- WHich half of the inning are we in
- istopinning : bool
- Is this the top of the inning
- scheduledinnings : int
- How many innings are scheduled for this game
+ current_inning : int
+ The game's current inning.
+ current_inning_ordinal : str
+ This inning's ordinal.
+ inning_state : str
+ What state this inning is in.
+ inning_half : str
+ Which half of the inning we are in.
+ is_top_inning : bool
+ Is this the top of the inning.
+ scheduled_innings : int
+ How many innings are scheduled for this game.
innings : List[LinescoreInning]
- Data on each inning
+ Data on each inning.
teams : LinescoreTeams
- Line score data on our teams
+ Line score data on our teams.
defense : LinescoreDefense
- Current defense
+ Current defense.
offense : LinescoreOffense
- Current offense
+ Current offense.
balls : int
- current count balls
+ Current count balls.
strikes : int
- current count strikes
+ Current count strikes.
outs : int
- current count outs
+ Current count outs.
+ note : str
+ Any note for the linescore.
"""
-
- scheduledinnings: int
- innings: Union[List[LinescoreInning], List[dict]]
- teams: Union[LinescoreTeams, dict]
- defense: Union[LinescoreDefense, dict]
- offense: Union[LinescoreOffense, dict]
+ scheduled_innings: int = Field(alias="scheduledinnings")
+ innings: List[LinescoreInning] = []
+ teams: LinescoreTeams
+ defense: LinescoreDefense
+ offense: LinescoreOffense
balls: Optional[int] = None
strikes: Optional[int] = None
outs: Optional[int] = None
note: Optional[str] = None
- currentinning: Optional[int] = None
- currentinningordinal: Optional[str] = None
- inningstate: Optional[str] = None
- inninghalf: Optional[str] = None
- istopinning: Optional[bool] = None
-
- def __post_init__(self):
- self.innings = [LinescoreInning(**inning) for inning in self.innings]
- self.teams = LinescoreTeams(**self.teams)
- self.defense = LinescoreDefense(**self.defense)
- self.offense = LinescoreOffense(**self.offense)
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ current_inning: Optional[int] = Field(default=None, alias="currentinning")
+ current_inning_ordinal: Optional[str] = Field(default=None, alias="currentinningordinal")
+ inning_state: Optional[str] = Field(default=None, alias="inningstate")
+ inning_half: Optional[str] = Field(default=None, alias="inninghalf")
+ is_top_inning: Optional[bool] = Field(default=None, alias="istopinning")
diff --git a/mlbstatsapi/models/game/livedata/livedata.py b/mlbstatsapi/models/game/livedata/livedata.py
index 8f883686..94f2ecec 100644
--- a/mlbstatsapi/models/game/livedata/livedata.py
+++ b/mlbstatsapi/models/game/livedata/livedata.py
@@ -1,45 +1,39 @@
-from typing import Union, Optional
-from dataclasses import dataclass, field
-
+from typing import Optional, Any
+from pydantic import Field, field_validator
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.game.livedata.plays import Plays
from mlbstatsapi.models.game.livedata.linescore import Linescore
from mlbstatsapi.models.game.livedata.boxscore import BoxScore
-
from .attributes import GameLeaders, GameDecisions
-@dataclass(repr=False)
-class LiveData:
+class LiveData(MLBBaseModel):
"""
- A class to represent this games live data.
+ A class to represent this game's live data.
Attributes
----------
plays : Plays
- Has the plays for this game
+ Has the plays for this game.
linescore : Linescore
- This games linescore
+ This game's linescore.
boxscore : BoxScore
- This games boxscore
+ This game's boxscore.
leaders : GameLeaders
- The data leaders for this game
- decisions : GameDecisions = None
- Decisions for this game, Ie a winner or a loser
+ The data leaders for this game.
+ decisions : GameDecisions
+ Decisions for this game (i.e., winner or loser).
"""
- plays: Union[Plays, dict]
- boxscore: Union[BoxScore, dict]
- leaders: Union[GameLeaders, dict]
- decisions: Optional[Union[GameDecisions, dict]] = field(default_factory=dict)
- linescore: Union[Linescore, dict] = field(default_factory=dict)
-
-
- def __post_init__(self):
- self.plays = Plays(**self.plays)
- self.linescore = Linescore(**self.linescore) if self.linescore else self.linescore
- self.boxscore = BoxScore(**self.boxscore)
- self.decisions = GameDecisions(**self.decisions) if self.decisions else self.decisions
- self.leaders = GameLeaders(**self.leaders)
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ plays: Plays
+ boxscore: BoxScore
+ leaders: GameLeaders
+ decisions: Optional[GameDecisions] = None
+ linescore: Optional[Linescore] = None
+
+ @field_validator('decisions', 'linescore', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
diff --git a/mlbstatsapi/models/game/livedata/plays/__init__.py b/mlbstatsapi/models/game/livedata/plays/__init__.py
index fd58b650..9758654a 100644
--- a/mlbstatsapi/models/game/livedata/plays/__init__.py
+++ b/mlbstatsapi/models/game/livedata/plays/__init__.py
@@ -1 +1,15 @@
from .plays import Plays
+from .play import (
+ Play,
+ PlayAbout,
+ PlayResult,
+ PlayReviewDetails,
+ PlayMatchup,
+ PlayMatchupSplits,
+ PlayEvent,
+ PlayRunner,
+ RunnerMovement,
+ RunnerDetails,
+ RunnerCredits,
+)
+from .playbyinning import PlayByInning, PlayByInningHits, HitsByTeam, HitCoordinates
diff --git a/mlbstatsapi/models/game/livedata/plays/play/__init__.py b/mlbstatsapi/models/game/livedata/plays/play/__init__.py
index be2d3b78..ce09c199 100644
--- a/mlbstatsapi/models/game/livedata/plays/play/__init__.py
+++ b/mlbstatsapi/models/game/livedata/plays/play/__init__.py
@@ -1 +1,5 @@
from .play import Play
+from .attributes import PlayAbout, PlayResult, PlayReviewDetails
+from .matchup import PlayMatchup, PlayMatchupSplits
+from .playevent import PlayEvent
+from .playrunner import PlayRunner, RunnerMovement, RunnerDetails, RunnerCredits
diff --git a/mlbstatsapi/models/game/livedata/plays/play/attributes.py b/mlbstatsapi/models/game/livedata/plays/play/attributes.py
index a066f43d..16cc5acc 100644
--- a/mlbstatsapi/models/game/livedata/plays/play/attributes.py
+++ b/mlbstatsapi/models/game/livedata/plays/play/attributes.py
@@ -1,111 +1,102 @@
from typing import Optional
-from dataclasses import dataclass
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
-@dataclass(repr=False)
-class PlayAbout:
+
+class PlayAbout(MLBBaseModel):
"""
- A class to represent a information about a play.
+ A class to represent information about a play.
Attributes
----------
- atbatindex : int
- Current at bat index
- halfinning : str
- What side of the inning
- istopinning : bool
- Is this inning the top of the inning
+ at_bat_index : int
+ Current at bat index.
+ half_inning : str
+ What side of the inning.
+ is_top_inning : bool
+ Is this inning the top of the inning.
inning : int
- What number of inning we are in
- starttime : str
- The start time for this play
- endtime : str
- The end time for this play
- iscomplete : bool
- Is this play complete
- isscoringplay : bool
- is this play a scoring play
- hasreview : bool
- Dose this play have a review
- hasout : bool
- Does this play have a out
- captivatingindex : int
- What is the captivating index for this play
+ What number of inning we are in.
+ start_time : str
+ The start time for this play.
+ end_time : str
+ The end time for this play.
+ is_complete : bool
+ Is this play complete.
+ is_scoring_play : bool
+ Is this play a scoring play.
+ has_review : bool
+ Does this play have a review.
+ has_out : bool
+ Does this play have an out.
+ captivating_index : int
+ What is the captivating index for this play.
"""
- atbatindex: int
- halfinning: str
- istopinning: bool
+ at_bat_index: int = Field(alias="atbatindex")
+ half_inning: str = Field(alias="halfinning")
+ is_top_inning: bool = Field(alias="istopinning")
inning: int
- iscomplete: bool
- isscoringplay: bool
- hasout: bool
- captivatingindex: int
- endtime: Optional[str] = None
- starttime: Optional[str] = None
- hasreview: Optional[bool] = None
+ is_complete: bool = Field(alias="iscomplete")
+ is_scoring_play: bool = Field(alias="isscoringplay")
+ has_out: bool = Field(alias="hasout")
+ captivating_index: int = Field(alias="captivatingindex")
+ end_time: Optional[str] = Field(default=None, alias="endtime")
+ start_time: Optional[str] = Field(default=None, alias="starttime")
+ has_review: Optional[bool] = Field(default=None, alias="hasreview")
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-@dataclass(repr=False)
-class PlayResult:
+class PlayResult(MLBBaseModel):
"""
A class to represent a play result.
Attributes
----------
type : str
- Play result type
+ Play result type.
event : str
- Play event
- eventtype : str
- Event type
+ Play event.
+ event_type : str
+ Event type.
description : str
- Event description
+ Event description.
rbi : int
- Number of RBI's
- awayscore : int
- Score for away team
- homescore : int
- Score for home team
- isout : bool
- If the play was an out
+ Number of RBIs.
+ away_score : int
+ Score for away team.
+ home_score : int
+ Score for home team.
+ is_out : bool
+ If the play was an out.
"""
type: str
- awayscore: int
- homescore: int
+ away_score: int = Field(alias="awayscore")
+ home_score: int = Field(alias="homescore")
rbi: Optional[int] = None
event: Optional[str] = None
- eventtype: Optional[str] = None
+ event_type: Optional[str] = Field(default=None, alias="eventtype")
description: Optional[str] = None
- isout: Optional[bool] = None
+ is_out: Optional[bool] = Field(default=None, alias="isout")
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-@dataclass(repr=False)
-class PlayReviewDetails:
+class PlayReviewDetails(MLBBaseModel):
"""
A class to represent play review details.
Attributes
----------
- isoverturned : bool
- Was it overturned
- inprogress : bool
- Is it in progress
- reviewtype : str
- What type of review
- challengeteamid : int
- The team issuing the challenge review
+ is_overturned : bool
+ Was it overturned.
+ in_progress : bool
+ Is it in progress.
+ review_type : str
+ What type of review.
+ challenge_team_id : int
+ The team issuing the challenge review.
+ additional_reviews : str
+ Additional reviews.
"""
- isoverturned: bool
- inprogress: bool
- reviewtype: str
- challengeteamid: Optional[int] = None
- additionalreviews: Optional[str] = None
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
+ is_overturned: bool = Field(alias="isoverturned")
+ in_progress: bool = Field(alias="inprogress")
+ review_type: str = Field(alias="reviewtype")
+ challenge_team_id: Optional[int] = Field(default=None, alias="challengeteamid")
+ additional_reviews: Optional[str] = Field(default=None, alias="additionalreviews")
diff --git a/mlbstatsapi/models/game/livedata/plays/play/matchup/__init__.py b/mlbstatsapi/models/game/livedata/plays/play/matchup/__init__.py
index 5527ce5a..2b41dbce 100644
--- a/mlbstatsapi/models/game/livedata/plays/play/matchup/__init__.py
+++ b/mlbstatsapi/models/game/livedata/plays/play/matchup/__init__.py
@@ -1 +1,2 @@
-from .matchup import PlayMatchupSplits, PlayMatchup
\ No newline at end of file
+from .matchup import PlayMatchup
+from .attributes import PlayMatchupSplits
diff --git a/mlbstatsapi/models/game/livedata/plays/play/matchup/attributes.py b/mlbstatsapi/models/game/livedata/plays/play/matchup/attributes.py
index 12b3c190..e9f27b76 100644
--- a/mlbstatsapi/models/game/livedata/plays/play/matchup/attributes.py
+++ b/mlbstatsapi/models/game/livedata/plays/play/matchup/attributes.py
@@ -1,19 +1,20 @@
-from dataclasses import dataclass
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
-@dataclass
-class PlayMatchupSplits:
+
+class PlayMatchupSplits(MLBBaseModel):
"""
- A class to represent a playMatchup Split.
+ A class to represent a play matchup split.
Attributes
----------
batter : str
- Batter matchup split
+ Batter matchup split.
pitcher : str
- Pitcher matchup split
- menonbase : str
- Menonbase matchup split
+ Pitcher matchup split.
+ men_on_base : str
+ Men on base matchup split.
"""
batter: str
pitcher: str
- menonbase: str
\ No newline at end of file
+ men_on_base: str = Field(alias="menonbase")
diff --git a/mlbstatsapi/models/game/livedata/plays/play/matchup/matchup.py b/mlbstatsapi/models/game/livedata/plays/play/matchup/matchup.py
index 1cfc8d94..0ca20a2f 100644
--- a/mlbstatsapi/models/game/livedata/plays/play/matchup/matchup.py
+++ b/mlbstatsapi/models/game/livedata/plays/play/matchup/matchup.py
@@ -1,64 +1,55 @@
-from typing import Union, Optional, List
-from dataclasses import dataclass
-
+from typing import Optional, List, Any
+from pydantic import Field, field_validator
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.people import Person
from mlbstatsapi.models.data import CodeDesc
-
from .attributes import PlayMatchupSplits
-@dataclass(repr=False)
-class PlayMatchup:
+
+class PlayMatchup(MLBBaseModel):
"""
- A class to represent a play Matchup.
+ A class to represent a play matchup.
Attributes
----------
batter : Person
- Matchup batter
- batside : PlayMatchupSide
- batters batside
+ Matchup batter.
+ bat_side : CodeDesc
+ Batter's bat side.
pitcher : Person
- Matchup pitcher
- pitchhand : PlayMatchupSide
- Pitchers side
- pitcherhotcoldzones : List
- Pitcher hot cold zone stats
+ Matchup pitcher.
+ pitch_hand : CodeDesc
+ Pitcher's side.
+ pitcher_hot_cold_zones : List
+ Pitcher hot cold zone stats.
splits : PlayMatchupSplits
- PlayMatchupSplits
- batterhotcoldzonestats : List
- Batter hot cold zone stats
- postonfirst : Person
- Runner on first
- postonsecond : Person
- Runner on second
- postonthird : Person
- Runner on third
+ Play matchup splits.
+ batter_hot_cold_zone_stats : List
+ Batter hot cold zone stats.
+ post_on_first : Person
+ Runner on first.
+ post_on_second : Person
+ Runner on second.
+ post_on_third : Person
+ Runner on third.
"""
- batter: Union[Person, dict]
- batside: Union[CodeDesc, dict]
- pitcher: Union[Person, dict]
- pitchhand: Union[CodeDesc, dict]
- batterhotcoldzones: List
- pitcherhotcoldzones: List
- splits: Union[PlayMatchupSplits, dict]
- batterhotcoldzonestats: Optional[List] = None
- pitcherhotcoldzonestats: Optional[List] = None
- postonfirst: Optional[Union[Person, dict]] = None
- postonsecond: Optional[Union[Person, dict]] = None
- postonthird: Optional[Union[Person, dict]] = None
+ batter: Person
+ bat_side: CodeDesc = Field(alias="batside")
+ pitcher: Person
+ pitch_hand: CodeDesc = Field(alias="pitchhand")
+ batter_hot_cold_zones: List = Field(alias="batterhotcoldzones")
+ pitcher_hot_cold_zones: List = Field(alias="pitcherhotcoldzones")
+ splits: PlayMatchupSplits
+ batter_hot_cold_zone_stats: Optional[List] = Field(default=None, alias="batterhotcoldzonestats")
+ pitcher_hot_cold_zone_stats: Optional[List] = Field(default=None, alias="pitcherhotcoldzonestats")
+ post_on_first: Optional[Person] = Field(default=None, alias="postonfirst")
+ post_on_second: Optional[Person] = Field(default=None, alias="postonsecond")
+ post_on_third: Optional[Person] = Field(default=None, alias="postonthird")
- def __post_init__(self):
- self.batter = Person(**self.batter)
- self.batside = CodeDesc(**self.batside)
- self.pitcher = Person(**self.pitcher)
- self.pitchhand = CodeDesc(**self.pitchhand)
- self.splits = PlayMatchupSplits(**self.splits)
- self.batterhotcoldzonestats = self.batterhotcoldzonestats['stats'] if self.batterhotcoldzonestats else self.batterhotcoldzonestats
- self.pitcherhotcoldzonestats = self.pitcherhotcoldzonestats['stats'] if self.pitcherhotcoldzonestats else self.pitcherhotcoldzonestats
- self.postonfirst = Person(**self.postonfirst) if self.postonfirst else self.postonfirst
- self.postonsecond = Person(**self.postonsecond) if self.postonsecond else self.postonsecond
- self.postonthird = Person(**self.postonthird) if self.postonthird else self.postonthird
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ @field_validator('batter_hot_cold_zone_stats', 'pitcher_hot_cold_zone_stats', mode='before')
+ @classmethod
+ def extract_stats(cls, v: Any) -> Any:
+ """Extract stats from nested dict if present."""
+ if isinstance(v, dict) and 'stats' in v:
+ return v['stats']
+ return v
diff --git a/mlbstatsapi/models/game/livedata/plays/play/play.py b/mlbstatsapi/models/game/livedata/plays/play/play.py
index 7bde0527..999feedb 100644
--- a/mlbstatsapi/models/game/livedata/plays/play/play.py
+++ b/mlbstatsapi/models/game/livedata/plays/play/play.py
@@ -1,6 +1,6 @@
-from typing import Union, Optional, List
-from dataclasses import dataclass
-
+from typing import Optional, List
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.game.livedata.plays.play.matchup import PlayMatchup
from mlbstatsapi.models.game.livedata.plays.play.playrunner import PlayRunner
from mlbstatsapi.models.game.livedata.plays.play.playevent import PlayEvent
@@ -8,60 +8,46 @@
from .attributes import PlayAbout, PlayResult, PlayReviewDetails
-@dataclass(repr=False)
-class Play:
+class Play(MLBBaseModel):
"""
A class to represent a single play in this game.
Attributes
----------
result : PlayResult
- Play result
+ Play result.
about : PlayAbout
- Information about this play
- count : PlayCount
- This plays count
+ Information about this play.
+ count : Count
+ This play's count.
matchup : PlayMatchup
- This plays matchup
- pitchindex : List[int]
- Pitch index for this play, indexing playEvents
- actionindex : List[int]
- Action index for this play, indexing playEvents
- runnerindex : List[int]
- Runner index for this play, indexing runners
+ This play's matchup.
+ pitch_index : List[int]
+ Pitch index for this play, indexing play events.
+ action_index : List[int]
+ Action index for this play, indexing play events.
+ runner_index : List[int]
+ Runner index for this play, indexing runners.
runners : List[PlayRunner]
- Runners
- playevents : List[PlayEvent]
- Play events
- playendtime : str
- Time this play ends
- atbatindex : int
- The play index number
- reviewdetails : PlayReviewDetails
- Information on reviews if present
+ Runners.
+ play_events : List[PlayEvent]
+ Play events.
+ play_end_time : str
+ Time this play ends.
+ at_bat_index : int
+ The play index number.
+ review_details : PlayReviewDetails
+ Information on reviews if present.
"""
- result: Union[PlayResult, dict]
- about: Union[PlayAbout, dict]
- count: Union[Count, dict]
- matchup: Union[PlayMatchup, dict]
- pitchindex: List[int]
- actionindex: List[int]
- runnerindex: List[int]
- runners: Union[List[PlayRunner], List[dict]]
- playevents: Union[List[PlayEvent], List[dict]]
- atbatindex: int
- playendtime: Optional[str] = None
- reviewdetails: Optional[Union[PlayReviewDetails, dict]] = None
-
- def __post_init__(self):
- self.result = PlayResult(**self.result)
- self.about = PlayAbout(**self.about)
- self.count = Count(**self.count)
- self.matchup = PlayMatchup(**self.matchup)
- self.runners = [PlayRunner(**runner) for runner in self.runners]
- self.playevents = [PlayEvent(**playevent) for playevent in self.playevents]
- self.reviewdetails = PlayReviewDetails(**self.reviewdetails) if self.reviewdetails else self.reviewdetails
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ result: PlayResult
+ about: PlayAbout
+ count: Count
+ matchup: PlayMatchup
+ pitch_index: List[int] = Field(alias="pitchindex")
+ action_index: List[int] = Field(alias="actionindex")
+ runner_index: List[int] = Field(alias="runnerindex")
+ runners: List[PlayRunner] = []
+ play_events: List[PlayEvent] = Field(default=[], alias="playevents")
+ at_bat_index: int = Field(alias="atbatindex")
+ play_end_time: Optional[str] = Field(default=None, alias="playendtime")
+ review_details: Optional[PlayReviewDetails] = Field(default=None, alias="reviewdetails")
diff --git a/mlbstatsapi/models/game/livedata/plays/play/playevent/__init__.py b/mlbstatsapi/models/game/livedata/plays/play/playevent/__init__.py
index fa265370..43fc4f5b 100644
--- a/mlbstatsapi/models/game/livedata/plays/play/playevent/__init__.py
+++ b/mlbstatsapi/models/game/livedata/plays/play/playevent/__init__.py
@@ -1 +1 @@
-from .playevent import PlayEvent
\ No newline at end of file
+from .playevent import PlayEvent
diff --git a/mlbstatsapi/models/game/livedata/plays/play/playevent/playevent.py b/mlbstatsapi/models/game/livedata/plays/play/playevent/playevent.py
index 236fbf71..2caf1812 100644
--- a/mlbstatsapi/models/game/livedata/plays/play/playevent/playevent.py
+++ b/mlbstatsapi/models/game/livedata/plays/play/playevent/playevent.py
@@ -1,85 +1,73 @@
-from typing import Union, Optional
-from dataclasses import dataclass
+from typing import Optional
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.people import Person, Position
from mlbstatsapi.models.data import Count, HitData, PitchData, PlayDetails
-@dataclass(repr=False)
-class PlayEvent:
+
+class PlayEvent(MLBBaseModel):
"""
- A class to represent a information about a play.
+ A class to represent a play event.
Attributes
----------
details : PlayDetails
- Event details
+ Event details.
index : int
- Event index
- starttime : str
- Event start time
- endtime : str
- Event end time
- ispitch : bool
- Is this event a pitch
+ Event index.
+ start_time : str
+ Event start time.
+ end_time : str
+ Event end time.
+ is_pitch : bool
+ Is this event a pitch.
type : str
- Type
- playid : str
- Unique play id ?
- pitchnumber : int
- Pitch number
- actionplayid : str
- Unique action play id ?
- isbaserunningplay : bool
- Is there base running this play
- issubstitution : bool
- Is this a substitution
- battingorder : str
- A weird batting order string that only has appeared once
- count : PlayCount
- Count
- pitchdata : PitchData
- Pitch data
- hitdata : HitData
- Hit data
+ Type.
+ play_id : str
+ Unique play ID.
+ pitch_number : int
+ Pitch number.
+ action_play_id : str
+ Unique action play ID.
+ is_base_running_play : bool
+ Is there base running this play.
+ is_substitution : bool
+ Is this a substitution.
+ batting_order : str
+ Batting order string.
+ count : Count
+ Count.
+ pitch_data : PitchData
+ Pitch data.
+ hit_data : HitData
+ Hit data.
player : Person
- Player
+ Player.
position : Position
- Position
- replacedplayer : Person
- Replaced player
+ Position.
+ replaced_player : Person
+ Replaced player.
"""
- details: Union[PlayDetails, dict]
+ details: PlayDetails
index: int
- ispitch: bool
+ is_pitch: bool = Field(alias="ispitch")
type: str
- pfxid: Optional[str] = None
- starttime: Optional[str] = None
- endtime: Optional[str] = None
+ pfx_id: Optional[str] = Field(default=None, alias="pfxid")
+ start_time: Optional[str] = Field(default=None, alias="starttime")
+ end_time: Optional[str] = Field(default=None, alias="endtime")
umpire: Optional[str] = None
base: Optional[str] = None
- playid: Optional[str] = None
- pitchnumber: Optional[int] = None
- actionplayid: Optional[str] = None
- isbaserunningplay: Optional[bool] = None
- issubstitution: Optional[bool] = None
- battingorder: Optional[str] = None
- count: Optional[Union[Count, dict]] = None
- pitchdata: Optional[Union[PitchData, dict]] = None
- hitdata: Optional[Union[HitData, dict]] = None
- player: Optional[Union[Person, dict]] = None
- position: Optional[Union[Position, dict]] = None
- replacedplayer: Optional[Union[Person, dict]] = None
- reviewdetails: Optional[dict] = None
- injurytype: Optional[str] = None
-
- def __post_init__(self):
- self.details = PlayDetails(**self.details)
- self.count = Count(**self.count) if self.count else self.count
- self.pitchdata = PitchData(**self.pitchdata) if self.pitchdata else self.pitchdata
- self.hitdata = HitData(**self.hitdata) if self.hitdata else self.hitdata
- self.player = Person(**self.player) if self.player else self.player
- self.position = Position(**self.position) if self.position else self.position
- self.replacedplayer = Person(**self.replacedplayer) if self.replacedplayer else self.replacedplayer
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ play_id: Optional[str] = Field(default=None, alias="playid")
+ pitch_number: Optional[int] = Field(default=None, alias="pitchnumber")
+ action_play_id: Optional[str] = Field(default=None, alias="actionplayid")
+ is_base_running_play: Optional[bool] = Field(default=None, alias="isbaserunningplay")
+ is_substitution: Optional[bool] = Field(default=None, alias="issubstitution")
+ batting_order: Optional[str] = Field(default=None, alias="battingorder")
+ count: Optional[Count] = None
+ pitch_data: Optional[PitchData] = Field(default=None, alias="pitchdata")
+ hit_data: Optional[HitData] = Field(default=None, alias="hitdata")
+ player: Optional[Person] = None
+ position: Optional[Position] = None
+ replaced_player: Optional[Person] = Field(default=None, alias="replacedplayer")
+ review_details: Optional[dict] = Field(default=None, alias="reviewdetails")
+ injury_type: Optional[str] = Field(default=None, alias="injurytype")
diff --git a/mlbstatsapi/models/game/livedata/plays/play/playrunner/__init__.py b/mlbstatsapi/models/game/livedata/plays/play/playrunner/__init__.py
index bfb8f16f..10591084 100644
--- a/mlbstatsapi/models/game/livedata/plays/play/playrunner/__init__.py
+++ b/mlbstatsapi/models/game/livedata/plays/play/playrunner/__init__.py
@@ -1 +1,2 @@
from .playrunner import PlayRunner
+from .attributes import RunnerMovement, RunnerDetails, RunnerCredits
diff --git a/mlbstatsapi/models/game/livedata/plays/play/playrunner/attributes.py b/mlbstatsapi/models/game/livedata/plays/play/playrunner/attributes.py
index 86d649b0..18f21b3b 100644
--- a/mlbstatsapi/models/game/livedata/plays/play/playrunner/attributes.py
+++ b/mlbstatsapi/models/game/livedata/plays/play/playrunner/attributes.py
@@ -1,106 +1,88 @@
-from typing import Union, Optional
-from dataclasses import dataclass
-
+from typing import Optional
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.people import Person, Position
-@dataclass
-class RunnerCredits:
+class RunnerCredits(MLBBaseModel):
"""
- A class to represent a runners credit.
+ A class to represent a runner's credit.
Attributes
----------
- player: Person
- The player
- position: RunnerCreditsPosition
- The position
- credit: str
- The credit
+ player : Person
+ The player.
+ position : Position
+ The position.
+ credit : str
+ The credit.
"""
- player: Union[Person, dict]
- position: Union[Position, dict]
+ player: Person
+ position: Position
credit: str
- def __post_init__(self):
- self.player = Person(**self.player)
- self.position = Position(**self.position)
-
-@dataclass(repr=False)
-class RunnerMovement:
+class RunnerMovement(MLBBaseModel):
"""
- A class to represent a play runner.
+ A class to represent a play runner movement.
Attributes
----------
- isout: bool
- Was the running movement an out
- outnumber: int
- What is the outnumber
- originbase: str
- Original base
- start: str
- What base the runner started from
- end: str
- What base the runner ended at
- outbase: str
- Base runner was made out
+ is_out : bool
+ Was the running movement an out.
+ out_number : int
+ What is the out number (None if not an out).
+ origin_base : str
+ Original base.
+ start : str
+ What base the runner started from.
+ end : str
+ What base the runner ended at.
+ out_base : str
+ Base runner was made out.
"""
- isout: bool
- outnumber: int
- originbase: Optional[str] = None
+ is_out: bool = Field(alias="isout")
+ out_number: Optional[int] = Field(default=None, alias="outnumber")
+ origin_base: Optional[str] = Field(default=None, alias="originbase")
start: Optional[str] = None
end: Optional[str] = None
- outbase: Optional[str] = None
+ out_base: Optional[str] = Field(default=None, alias="outbase")
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-@dataclass(repr=False)
-class RunnerDetails:
+class RunnerDetails(MLBBaseModel):
"""
- A class to represent a play runner.
+ A class to represent a play runner details.
Attributes
----------
- event: str
- Runner event
- eventtype: str
- Runner event type
- runner: Person
- Who the runner is
- isscoringevent: bool
- Was this a scoring events
- rbi: bool
- Was this a rbi
- earned: bool
- Was it earned
- teamunearned: bool
- Was it unearned
- playindex: int
- Play index
- movementreason: str
- Reason for the movement
- responsiblepitcher: Person
- WHo was the responsible pitcher
+ event : str
+ Runner event.
+ event_type : str
+ Runner event type.
+ runner : Person
+ Who the runner is.
+ is_scoring_event : bool
+ Was this a scoring event.
+ rbi : bool
+ Was this an RBI.
+ earned : bool
+ Was it earned.
+ team_unearned : bool
+ Was it unearned.
+ play_index : int
+ Play index.
+ movement_reason : str
+ Reason for the movement.
+ responsible_pitcher : Person
+ Who was the responsible pitcher.
"""
event: str
- eventtype: str
- runner: Union[Person, dict]
- isscoringevent: bool
+ event_type: str = Field(alias="eventtype")
+ runner: Person
+ is_scoring_event: bool = Field(alias="isscoringevent")
rbi: bool
earned: bool
- teamunearned: bool
- playindex: int
- movementreason: Optional[str] = None
- responsiblepitcher: Optional[Union[Person, dict]] = None
-
- def __post_init__(self):
- self.runner = Person(**self.runner)
- self.responsiblepitcher = Person(**self.responsiblepitcher) if self.responsiblepitcher else self.responsiblepitcher
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ team_unearned: bool = Field(alias="teamunearned")
+ play_index: int = Field(alias="playindex")
+ movement_reason: Optional[str] = Field(default=None, alias="movementreason")
+ responsible_pitcher: Optional[Person] = Field(default=None, alias="responsiblepitcher")
diff --git a/mlbstatsapi/models/game/livedata/plays/play/playrunner/playrunner.py b/mlbstatsapi/models/game/livedata/plays/play/playrunner/playrunner.py
index d6f09f8d..b1ec2f45 100644
--- a/mlbstatsapi/models/game/livedata/plays/play/playrunner/playrunner.py
+++ b/mlbstatsapi/models/game/livedata/plays/play/playrunner/playrunner.py
@@ -1,28 +1,21 @@
-from typing import Union, List, Optional
-from dataclasses import dataclass, field
-
+from typing import Optional, List
+from mlbstatsapi.models.base import MLBBaseModel
from .attributes import RunnerMovement, RunnerDetails, RunnerCredits
-@dataclass
-class PlayRunner:
+class PlayRunner(MLBBaseModel):
"""
A class to represent a play runner.
Attributes
----------
+ movement : RunnerMovement
+ Runner movements.
+ details : RunnerDetails
+ Runner details.
+ credits : List[RunnerCredits]
+ Runner credits.
+ """
movement: RunnerMovement
- Runner movements
details: RunnerDetails
- Runner details
- credits: List[RunnerCredits]
- Runner credits
- """
- movement: Union[RunnerMovement, dict]
- details: Union[RunnerDetails, dict]
- credits: Optional[Union[List[RunnerCredits], List[dict]]] = field(default_factory=list)
-
- def __post_init__(self):
- self.movement = RunnerMovement(**self.movement)
- self.details = RunnerDetails(**self.details)
- self.credits = [RunnerCredits(**credit) for credit in self.credits]
+ credits: List[RunnerCredits] = []
diff --git a/mlbstatsapi/models/game/livedata/plays/playbyinning/__init__.py b/mlbstatsapi/models/game/livedata/plays/playbyinning/__init__.py
index 3d02fc80..f62f9116 100644
--- a/mlbstatsapi/models/game/livedata/plays/playbyinning/__init__.py
+++ b/mlbstatsapi/models/game/livedata/plays/playbyinning/__init__.py
@@ -1 +1,2 @@
from .playbyinning import PlayByInning
+from .attributes import PlayByInningHits, HitsByTeam, HitCoordinates
diff --git a/mlbstatsapi/models/game/livedata/plays/playbyinning/attributes.py b/mlbstatsapi/models/game/livedata/plays/playbyinning/attributes.py
index ccbf46fa..56136f27 100644
--- a/mlbstatsapi/models/game/livedata/plays/playbyinning/attributes.py
+++ b/mlbstatsapi/models/game/livedata/plays/playbyinning/attributes.py
@@ -1,75 +1,65 @@
-from typing import Union, List
-from dataclasses import dataclass
-
+from typing import List
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.teams import Team
from mlbstatsapi.models.people import Person
-@dataclass
-class HitCoordinates:
+
+class HitCoordinates(MLBBaseModel):
"""
- A class to represent a Hits coordinates.
+ A class to represent a hit's coordinates.
Attributes
----------
x : float
- X coordinate for hit
+ X coordinate for hit.
y : float
- Y coordinate for hit
+ Y coordinate for hit.
"""
x: float
y: float
-@dataclass
-class HitsByTeam:
+
+class HitsByTeam(MLBBaseModel):
"""
- A class to represent a Hit during an inning.
+ A class to represent a hit during an inning.
Attributes
----------
team : Team
- This team
+ This team.
inning : int
- This inning number
+ This inning number.
pitcher : Person
- The pitcher
+ The pitcher.
batter : Person
- The batter
+ The batter.
coordinates : HitCoordinates
- Hit coordinates
+ Hit coordinates.
type : str
- Type
+ Type.
description : str
- description
+ Description.
"""
- team: Union[Team, dict]
+ team: Team
inning: int
- pitcher: Union[Person, dict]
- batter: Union[Person, dict]
- coordinates: Union[HitCoordinates, dict]
+ pitcher: Person
+ batter: Person
+ coordinates: HitCoordinates
type: str
description: str
- def __post_init__(self):
- self.team = Team(**self.team)
- self.pitcher = Person(**self.pitcher)
- self.batter = Person(**self.batter)
- self.coordinates = HitCoordinates(**self.coordinates)
-@dataclass
-class PlayByInningHits:
+class PlayByInningHits(MLBBaseModel):
"""
- A class to represent a play by inning in this game.
+ A class to represent a play by inning hits.
Attributes
----------
home : List[HitsByTeam]
- Home team hits
+ Home team hits.
away : List[HitsByTeam]
- Away team hits
+ Away team hits.
"""
- home: Union[List[HitsByTeam], List[dict]]
- away: Union[List[HitsByTeam], List[dict]]
-
- def __post_init__(self):
- self.home = [HitsByTeam(**home_hit) for home_hit in self.home]
- self.away = [HitsByTeam(**away_hit) for away_hit in self.away]
+ home: List[HitsByTeam] = []
+ away: List[HitsByTeam] = []
diff --git a/mlbstatsapi/models/game/livedata/plays/playbyinning/playbyinning.py b/mlbstatsapi/models/game/livedata/plays/playbyinning/playbyinning.py
index d5b84950..883f9b41 100644
--- a/mlbstatsapi/models/game/livedata/plays/playbyinning/playbyinning.py
+++ b/mlbstatsapi/models/game/livedata/plays/playbyinning/playbyinning.py
@@ -1,31 +1,28 @@
-from typing import Union, List
-from dataclasses import dataclass
-
+from typing import List
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from .attributes import PlayByInningHits
-@dataclass
-class PlayByInning:
+
+class PlayByInning(MLBBaseModel):
"""
A class to represent a play by inning in this game.
Attributes
----------
- startindex : int
- Starting play index number, indexed with Plays.allPlays
- endindex : int
- End play index number, indexed with Plays.allPlays
+ start_index : int
+ Starting play index number, indexed with Plays.all_plays.
+ end_index : int
+ End play index number, indexed with Plays.all_plays.
top : List[int]
- Play indexes for top of the inning
+ Play indexes for top of the inning.
bottom : List[int]
- play indexes for bottom of the inning
+ Play indexes for bottom of the inning.
hits : PlayByInningHits
- Hits for the inning by home and away
+ Hits for the inning by home and away.
"""
- startindex: int
- endindex: int
+ start_index: int = Field(alias="startindex")
+ end_index: int = Field(alias="endindex")
top: List[int]
bottom: List[int]
- hits: Union[PlayByInningHits, dict]
-
- def __post_init__(self):
- self.hits = PlayByInningHits(**self.hits)
+ hits: PlayByInningHits
diff --git a/mlbstatsapi/models/game/livedata/plays/plays.py b/mlbstatsapi/models/game/livedata/plays/plays.py
index c21c3ead..36e4064b 100644
--- a/mlbstatsapi/models/game/livedata/plays/plays.py
+++ b/mlbstatsapi/models/game/livedata/plays/plays.py
@@ -1,37 +1,34 @@
-from typing import Union, List
-from dataclasses import dataclass, field
-
+from typing import List, Optional, Any
+from pydantic import Field, field_validator
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.game.livedata.plays.play import Play
from mlbstatsapi.models.game.livedata.plays.playbyinning import PlayByInning
-@dataclass(repr=False)
-class Plays:
+class Plays(MLBBaseModel):
"""
A class to represent the plays in this game.
Attributes
----------
- allplays : List[Play]
- All the plays in this game
- currentplay : Play
- The current play in this game
- scoringplays : List[int]
- Which plays are scoring plays, indexed with allPlays
- playsbyinning : List[PlayByInning]
- Plays by inning
+ all_plays : List[Play]
+ All the plays in this game.
+ current_play : Play
+ The current play in this game.
+ scoring_plays : List[int]
+ Which plays are scoring plays, indexed with all_plays.
+ plays_by_inning : List[PlayByInning]
+ Plays by inning.
"""
- allplays: Union[List[Play], List[dict]]
- scoringplays: List[int]
- playsbyinning: Union[List[PlayByInning], List[dict]]
- currentplay: Union[Play, dict] = field(default_factory=dict)
-
-
- def __post_init__(self):
- self.allplays = [Play(**play) for play in self.allplays if play]
- self.currentplay = Play(**self.currentplay) if self.currentplay else self.currentplay
- self.playsbyinning = [PlayByInning(**inning) for inning in self.playsbyinning if inning]
+ all_plays: List[Play] = Field(default=[], alias="allplays")
+ scoring_plays: List[int] = Field(alias="scoringplays")
+ plays_by_inning: List[PlayByInning] = Field(default=[], alias="playsbyinning")
+ current_play: Optional[Play] = Field(default=None, alias="currentplay")
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ @field_validator('current_play', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
diff --git a/mlbstatsapi/models/gamepace/__init__.py b/mlbstatsapi/models/gamepace/__init__.py
index 4d13e2a0..8f57ad25 100644
--- a/mlbstatsapi/models/gamepace/__init__.py
+++ b/mlbstatsapi/models/gamepace/__init__.py
@@ -1,2 +1,2 @@
-from .gamepace import Gamepace
-from .attributes import Gamepacedata
\ No newline at end of file
+from .gamepace import GamePace
+from .attributes import GamePaceData, PrPortalCalculatedFields
diff --git a/mlbstatsapi/models/gamepace/attributes.py b/mlbstatsapi/models/gamepace/attributes.py
index 9866b1c5..ca2097b2 100644
--- a/mlbstatsapi/models/gamepace/attributes.py
+++ b/mlbstatsapi/models/gamepace/attributes.py
@@ -1,186 +1,174 @@
-from typing import Union, Optional
-from dataclasses import dataclass
-
+from typing import Optional
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.teams import Team
from mlbstatsapi.models.leagues import League
from mlbstatsapi.models.sports import Sport
-@dataclass(kw_only=True)
-class Prportalcalculatedfields:
+class PrPortalCalculatedFields(MLBBaseModel):
"""
- This dataclass represents the calculated fields for a baseball game.
+ A class representing the calculated fields for a baseball game.
- Attributes:
+ Attributes
----------
- total7inngames : int
+ total_7_inn_games : int
The total number of 7-inning games played.
- total9inngames : int
+ total_9_inn_games : int
The total number of 9-inning games played.
- totalextrainngames : int
+ total_extra_inn_games : int
The total number of extra-inning games played.
- timeper7inngame : str
+ time_per_7_inn_game : str
The average time per 7-inning game.
- timeper9inngame : str
+ time_per_9_inn_game : str
The average time per 9-inning game.
- timeperextrainngame : str
+ time_per_extra_inn_game : str
The average time per extra-inning game.
"""
- total7inngames: int
- total9inngames: int
- totalextrainngames: int
- timeper7inngame: str
- timeper9inngame: str
- timeperextrainngame: str
+ total_7_inn_games: Optional[int] = Field(default=None, alias="total7inngames")
+ total_9_inn_games: Optional[int] = Field(default=None, alias="total9inngames")
+ total_extra_inn_games: Optional[int] = Field(default=None, alias="totalextrainngames")
+ time_per_7_inn_game: Optional[str] = Field(default=None, alias="timeper7inngame")
+ time_per_9_inn_game: Optional[str] = Field(default=None, alias="timeper9inngame")
+ time_per_extra_inn_game: Optional[str] = Field(default=None, alias="timeperextrainngame")
-@dataclass(kw_only=True, repr=False)
-class Gamepacedata:
+class GamePaceData(MLBBaseModel):
"""
- This dataclass represents a league in a sport, with various statistics and metrics related to its games and performances.
+ A class representing game pace data for a league, team, or sport.
- Attributes:
+ Attributes
----------
- hitsper9inn : float
+ hits_per_9_inn : float
The number of hits per 9 innings played.
- runsper9inn : float
+ runs_per_9_inn : float
The number of runs scored per 9 innings played.
- pitchesper9inn : float
+ pitches_per_9_inn : float
The number of pitches thrown per 9 innings played.
- plateappearancesper9inn : float
+ plate_appearances_per_9_inn : float
The number of plate appearances per 9 innings played.
- hitspergame : float
+ hits_per_game : float
The number of hits per game played.
- runspergame : float
+ runs_per_game : float
The number of runs scored per game played.
- inningsplayedpergame : float
+ innings_played_per_game : float
The number of innings played per game.
- pitchespergame : float
+ pitches_per_game : float
The number of pitches thrown per game played.
- pitcherspergame : float
+ pitchers_per_game : float
The number of pitchers used per game played.
- plateappearancespergame : float
+ plate_appearances_per_game : float
The number of plate appearances per game played.
- totalgametime : str
- The total time spent playing games in the league.
- totalinningsplayed : float
- The total number of innings played in the league.
- totalhits : int
- The total number of hits in the league.
- totalruns : int
- The total number of runs scored in the league.
- totalplateappearances : int
- The total number of plate appearances in the league.
- totalpitchers : int
- The total number of pitchers used in the league.
- totalpitches : int
- The total number of pitches thrown in the league.
- totalgames : int
- The total number of games played in the league.
- total7inngames : int
- The total number of 7-inning games played in the league.
- total9inngames : int
- The total number of 9-inning games played in the league.
- totalextrainngames : int
- The total number of extra inning games played in the league.
- timepergame : str
- The amount of time spent per game in the league.
- timeperpitch : str
- The amount of time spent per pitch in the league.
- timeperhit : str
- The amount of time spent per hit in the league.
- timeperrun : str
- The amount of time spent per run scored in the league.
- timeperplateappearance : str
- The amount of time spent per plate appearance in the league.
- timeper9inn : str
- The amount of time spent per 9 innings played in the league.
- timeper77plateappearances : str
- The amount of time spent per 7-7 plate appearances in the league.
- totalextrainntime : str
- The total amount of time spent on extra inning games in the league.
- timeper7inngame : str
- The amount of time spent per 7-inning game in the league.
- total7inngamescompletedearly: int
- The total number of 7-inning games completed early in the league.
- timeper7inngamewithoutextrainn: str
- The amount of time spent per 7-inning game without extra innings in the league.
- total7inngamesscheduled : int
- The total number of 7-inning games scheduled in the league.
- total7inngameswithoutextrainn : int
- The total number of 7-inning games played without extra innings in the league.
- total9inngamescompletedearly : int
- The total number of 9-inning games completed early in the league.
- total9inngameswithoutextrainn : int
- The total number of 9-inning games
- total9inngamesscheduled : int
- The total number of 9 inning games scheduled
- hitsperrun : float
- The number of hits per run
- pitchesperpitcher : float
- Number of pitches thrown per pitcher
+ total_game_time : str
+ The total time spent playing games.
+ total_innings_played : float
+ The total number of innings played.
+ total_hits : int
+ The total number of hits.
+ total_runs : int
+ The total number of runs scored.
+ total_plate_appearances : int
+ The total number of plate appearances.
+ total_pitchers : int
+ The total number of pitchers used.
+ total_pitches : int
+ The total number of pitches thrown.
+ total_games : int
+ The total number of games played.
+ total_7_inn_games : int
+ The total number of 7-inning games played.
+ total_9_inn_games : int
+ The total number of 9-inning games played.
+ total_extra_inn_games : int
+ The total number of extra inning games played.
+ time_per_game : str
+ The amount of time spent per game.
+ time_per_pitch : str
+ The amount of time spent per pitch.
+ time_per_hit : str
+ The amount of time spent per hit.
+ time_per_run : str
+ The amount of time spent per run scored.
+ time_per_plate_appearance : str
+ The amount of time spent per plate appearance.
+ time_per_9_inn : str
+ The amount of time spent per 9 innings played.
+ time_per_77_plate_appearances : str
+ The amount of time spent per 77 plate appearances.
+ total_extra_inn_time : str
+ The total amount of time spent on extra inning games.
+ time_per_7_inn_game : str
+ The amount of time spent per 7-inning game.
+ total_7_inn_games_completed_early : int
+ The total number of 7-inning games completed early.
+ time_per_7_inn_game_without_extra_inn : str
+ The amount of time spent per 7-inning game without extra innings.
+ total_7_inn_games_scheduled : int
+ The total number of 7-inning games scheduled.
+ total_7_inn_games_without_extra_inn : int
+ The total number of 7-inning games played without extra innings.
+ total_9_inn_games_completed_early : int
+ The total number of 9-inning games completed early.
+ total_9_inn_games_without_extra_inn : int
+ The total number of 9-inning games without extra innings.
+ total_9_inn_games_scheduled : int
+ The total number of 9 inning games scheduled.
+ hits_per_run : float
+ The number of hits per run.
+ pitches_per_pitcher : float
+ Number of pitches thrown per pitcher.
season : str
- Season number
- team: Team
- Team
+ Season number.
+ team : Team
+ Team.
league : League
- League
+ League.
sport : Sport
- Sport`
- prportalcalculatedfields : Prportalcalculatedfields
- calculated fields for a league
+ Sport.
+ pr_portal_calculated_fields : PrPortalCalculatedFields
+ Calculated fields.
"""
- hitsper9inn: Optional[float] = None
- runsper9inn: Optional[float] = None
- pitchesper9inn: Optional[float] = None
- plateappearancesper9inn: Optional[float] = None
- hitspergame: Optional[float] = None
- runspergame: Optional[float] = None
- inningsplayedpergame: Optional[float] = None
- pitchespergame: Optional[float] = None
- pitcherspergame: Optional[float] = None
- plateappearancespergame: Optional[float] = None
- totalgametime: Optional[str] = None
- totalinningsplayed: Optional[float] = None
- totalhits: Optional[int] = None
- totalruns: Optional[int] = None
- totalplateappearances: Optional[int] = None
- totalpitchers: Optional[int] = None
- totalpitches: Optional[int] = None
- totalgames: Optional[int] = None
- total7inngames: Optional[int] = None
- total9inngames: Optional[int] = None
- totalextrainngames: Optional[int] = None
- timepergame: Optional[str] = None
- timeperpitch: Optional[str] = None
- timeperhit: Optional[str] = None
- timeperrun: Optional[str] = None
- timeperplateappearance: Optional[str] = None
- timeper9inn: Optional[str] = None
- timeper77plateappearances: Optional[str] = None
- totalextrainntime: Optional[str] = None
- timeper7inngame: Optional[str] = None
- total7inngamescompletedearly: Optional[int] = None
- timeper7inngamewithoutextrainn: Optional[str] = None
- total7inngamesscheduled: Optional[int] = None
- total7inngameswithoutextrainn: Optional[int] = None
- total9inngamescompletedearly: Optional[int] = None
- total9inngameswithoutextrainn: Optional[int] = None
- total9inngamesscheduled: Optional[int] = None
- hitsperrun: Optional[float] = None
- pitchesperpitcher: Optional[float] = None
+ hits_per_9_inn: Optional[float] = Field(default=None, alias="hitsper9inn")
+ runs_per_9_inn: Optional[float] = Field(default=None, alias="runsper9inn")
+ pitches_per_9_inn: Optional[float] = Field(default=None, alias="pitchesper9inn")
+ plate_appearances_per_9_inn: Optional[float] = Field(default=None, alias="plateappearancesper9inn")
+ hits_per_game: Optional[float] = Field(default=None, alias="hitspergame")
+ runs_per_game: Optional[float] = Field(default=None, alias="runspergame")
+ innings_played_per_game: Optional[float] = Field(default=None, alias="inningsplayedpergame")
+ pitches_per_game: Optional[float] = Field(default=None, alias="pitchespergame")
+ pitchers_per_game: Optional[float] = Field(default=None, alias="pitcherspergame")
+ plate_appearances_per_game: Optional[float] = Field(default=None, alias="plateappearancespergame")
+ total_game_time: Optional[str] = Field(default=None, alias="totalgametime")
+ total_innings_played: Optional[float] = Field(default=None, alias="totalinningsplayed")
+ total_hits: Optional[int] = Field(default=None, alias="totalhits")
+ total_runs: Optional[int] = Field(default=None, alias="totalruns")
+ total_plate_appearances: Optional[int] = Field(default=None, alias="totalplateappearances")
+ total_pitchers: Optional[int] = Field(default=None, alias="totalpitchers")
+ total_pitches: Optional[int] = Field(default=None, alias="totalpitches")
+ total_games: Optional[int] = Field(default=None, alias="totalgames")
+ total_7_inn_games: Optional[int] = Field(default=None, alias="total7inngames")
+ total_9_inn_games: Optional[int] = Field(default=None, alias="total9inngames")
+ total_extra_inn_games: Optional[int] = Field(default=None, alias="totalextrainngames")
+ time_per_game: Optional[str] = Field(default=None, alias="timepergame")
+ time_per_pitch: Optional[str] = Field(default=None, alias="timeperpitch")
+ time_per_hit: Optional[str] = Field(default=None, alias="timeperhit")
+ time_per_run: Optional[str] = Field(default=None, alias="timeperrun")
+ time_per_plate_appearance: Optional[str] = Field(default=None, alias="timeperplateappearance")
+ time_per_9_inn: Optional[str] = Field(default=None, alias="timeper9inn")
+ time_per_77_plate_appearances: Optional[str] = Field(default=None, alias="timeper77plateappearances")
+ total_extra_inn_time: Optional[str] = Field(default=None, alias="totalextrainntime")
+ time_per_7_inn_game: Optional[str] = Field(default=None, alias="timeper7inngame")
+ total_7_inn_games_completed_early: Optional[int] = Field(default=None, alias="total7inngamescompletedearly")
+ time_per_7_inn_game_without_extra_inn: Optional[str] = Field(default=None, alias="timeper7inngamewithoutextrainn")
+ total_7_inn_games_scheduled: Optional[int] = Field(default=None, alias="total7inngamesscheduled")
+ total_7_inn_games_without_extra_inn: Optional[int] = Field(default=None, alias="total7inngameswithoutextrainn")
+ total_9_inn_games_completed_early: Optional[int] = Field(default=None, alias="total9inngamescompletedearly")
+ total_9_inn_games_without_extra_inn: Optional[int] = Field(default=None, alias="total9inngameswithoutextrainn")
+ total_9_inn_games_scheduled: Optional[int] = Field(default=None, alias="total9inngamesscheduled")
+ hits_per_run: Optional[float] = Field(default=None, alias="hitsperrun")
+ pitches_per_pitcher: Optional[float] = Field(default=None, alias="pitchesperpitcher")
season: Optional[str] = None
- team: Optional[Union[Team, dict]] = None
- league: Optional[Union[League, dict]] = None
- sport: Optional[Union[Sport, dict]] = None
- prportalcalculatedfields: Optional[Union[Prportalcalculatedfields, dict]] = None
-
- def __post_init__(self):
- self.team = Team(**self.team) if self.team else None
- self.league = League(**self.league) if self.league else None
- self.sport = Sport(**self.sport) if self.sport else None
- self.prportalcalculatedfields = Prportalcalculatedfields(**self.prportalcalculatedfields) if self.prportalcalculatedfields else None
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ team: Optional[Team] = None
+ league: Optional[League] = None
+ sport: Optional[Sport] = None
+ pr_portal_calculated_fields: Optional[PrPortalCalculatedFields] = Field(default=None, alias="prportalcalculatedfields")
diff --git a/mlbstatsapi/models/gamepace/gamepace.py b/mlbstatsapi/models/gamepace/gamepace.py
index 764117ea..5b341d78 100644
--- a/mlbstatsapi/models/gamepace/gamepace.py
+++ b/mlbstatsapi/models/gamepace/gamepace.py
@@ -1,28 +1,21 @@
-from dataclasses import dataclass
-from typing import Optional, List
+from typing import List
+from mlbstatsapi.models.base import MLBBaseModel
+from .attributes import GamePaceData
-from .attributes import Gamepacedata
-@dataclass
-class Gamepace:
+class GamePace(MLBBaseModel):
"""
- A dataclass representing a gamepace.
+ A class representing game pace data.
- Attributes:
+ Attributes
----------
- teams : List[Gamepacedata]
- A list of teams in the gamepace.
- leagues : List[Gamepacedata]
- A list of leagues in the gamepace.
- sports : List[Gamepacedata]
- A list of sports in the gamepace.
+ teams : List[GamePaceData]
+ A list of game pace data by team.
+ leagues : List[GamePaceData]
+ A list of game pace data by league.
+ sports : List[GamePaceData]
+ A list of game pace data by sport.
"""
- teams: Optional[List[Gamepacedata]] = None
- leagues: Optional[List[Gamepacedata]] = None
- sports: Optional[List[Gamepacedata]] = None
-
-
- def __post_init__(self):
- self.teams = [Gamepacedata(**teams) for teams in self.teams]
- self.leagues = [Gamepacedata(**leagues) for leagues in self.leagues]
- self.sports = [Gamepacedata(**sports) for sports in self.sports]
\ No newline at end of file
+ teams: List[GamePaceData] = []
+ leagues: List[GamePaceData] = []
+ sports: List[GamePaceData] = []
diff --git a/mlbstatsapi/models/homerunderby/__init__.py b/mlbstatsapi/models/homerunderby/__init__.py
index 8b290c1c..25d28621 100644
--- a/mlbstatsapi/models/homerunderby/__init__.py
+++ b/mlbstatsapi/models/homerunderby/__init__.py
@@ -1,2 +1,13 @@
-from .homerunderby import Homerunderby
-from .attributes import Round
\ No newline at end of file
+from .homerunderby import HomeRunDerby
+from .attributes import (
+ Round,
+ Matchup,
+ Seed,
+ Hits,
+ HitData,
+ TrajectoryData,
+ Coordinates,
+ Status,
+ Info,
+ EventType,
+)
diff --git a/mlbstatsapi/models/homerunderby/attributes.py b/mlbstatsapi/models/homerunderby/attributes.py
index 9db29dd0..1a1c2d4b 100644
--- a/mlbstatsapi/models/homerunderby/attributes.py
+++ b/mlbstatsapi/models/homerunderby/attributes.py
@@ -1,17 +1,17 @@
-from typing import Union, Optional, List
-from dataclasses import dataclass
-
+from typing import Optional, List, Any
+from pydantic import Field, field_validator
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.venues import Venue
from mlbstatsapi.models.teams import Team
from mlbstatsapi.models.people import Person
-@dataclass
-class Eventtype:
+
+class EventType(MLBBaseModel):
"""
- The Eventtype class holds information about the type of an event.
+ A class representing the type of an event.
- Attributes:
- ___________
+ Attributes
+ ----------
code : str
The unique code of the event type.
name : str
@@ -20,313 +20,263 @@ class Eventtype:
code: str
name: str
-@dataclass
-class Info:
+
+class Info(MLBBaseModel):
"""
- The Info class holds information about an event.
+ A class representing information about an event.
Attributes
----------
id : int
The unique identifier of the event.
- nongameguid : str
- Guid of the event.
+ non_game_guid : str
+ GUID of the event.
name : str
The name of the event.
- eventtype : Eventtype
- The type of event. Can be an instance of the Eventtype class or a
- dictionary containing the attributes for the Eventtype class.
- eventdate : str
+ event_type : EventType
+ The type of event.
+ event_date : str
The date of the event.
venue : Venue
- The venue of the event. Can be an instance of the Venue class or
- a dictionary containing the attributes for the Venue class.
- ismultiday : bool
+ The venue of the event.
+ is_multi_day : bool
Whether the event spans multiple days.
- isprimarycalendar : bool
+ is_primary_calendar : bool
Whether the event is on the primary calendar.
- filecode : str
+ file_code : str
The code of the file associated with the event.
- eventnumber : int
+ event_number : int
The number of the event.
- publicfacing : bool
+ public_facing : bool
Whether the event is public-facing.
teams : List[Team]
- The teams participating in the event. Can be a list of instances of
- the Team class or a list of dictionaries containing the attributes
- for the Team class.
+ The teams participating in the event.
"""
id: int
- nongameguid: str
+ non_game_guid: str = Field(alias="nongameguid")
name: str
- eventtype: Union[Eventtype, dict]
- eventdate: str
- venue: Union[Venue, dict]
- ismultiday: bool
- isprimarycalendar: bool
- filecode: str
- eventnumber: int
- publicfacing: bool
- teams: List[Union[Team, dict]]
+ event_type: EventType = Field(alias="eventtype")
+ event_date: str = Field(alias="eventdate")
+ venue: Venue
+ is_multi_day: bool = Field(alias="ismultiday")
+ is_primary_calendar: bool = Field(alias="isprimarycalendar")
+ file_code: str = Field(alias="filecode")
+ event_number: int = Field(alias="eventnumber")
+ public_facing: bool = Field(alias="publicfacing")
+ teams: List[Team] = []
- def __post_init__(self):
- self.eventtype = Eventtype(**self.eventtype)
- self.venue = Venue(**self.venue)
- self.teams = [Team(**team) for team in self.teams]
-@dataclass
-class Status:
+class Status(MLBBaseModel):
"""
A class representing the status of a round.
Attributes
----------
state : str
- The current state of the game or round (e.g. "in progress", "paused",
- "ended")
- currentround : int
- The number of the current round in the game
- currentroundtimeleft : str
- The amount of time left in the current round, in a human-readable
- format (e.g. "4:00")
- intiebreaker : bool
- Whether the game or round is currently in a tiebreaker
- tiebreakernum : int
- The number of the current tiebreaker, if applicable
- clockstopped : bool
- Whether the round clock is currently stopped
- bonustime : bool
- Whether the round is currently in bonus time
+ The current state of the game or round.
+ current_round : int
+ The number of the current round in the game.
+ current_round_time_left : str
+ The amount of time left in the current round.
+ in_tiebreaker : bool
+ Whether the game or round is currently in a tiebreaker.
+ tiebreaker_num : int
+ The number of the current tiebreaker, if applicable.
+ clock_stopped : bool
+ Whether the round clock is currently stopped.
+ bonus_time : bool
+ Whether the round is currently in bonus time.
"""
state: str
- currentround: int
- currentroundtimeleft: str
- intiebreaker: bool
- tiebreakernum: int
- clockstopped: bool
- bonustime: bool
+ current_round: int = Field(alias="currentround")
+ current_round_time_left: str = Field(alias="currentroundtimeleft")
+ in_tiebreaker: bool = Field(alias="intiebreaker")
+ tiebreaker_num: int = Field(alias="tiebreakernum")
+ clock_stopped: bool = Field(alias="clockstopped")
+ bonus_time: bool = Field(alias="bonustime")
-@dataclass
-class Coordinates:
- """"
- A class representing the coordinates of a hit
+
+class Coordinates(MLBBaseModel):
+ """
+ A class representing the coordinates of a hit.
Attributes
----------
- coordx : float
- The x-coordinate of the hit
- coordy : float
- The y-coordinate of the hit
- landingposx : float
- The x-coordinate of the hits's landing position,
- if applicable
- landingposy : float
- The y-coordinate of the hits's landing position,
- if applicable
+ coord_x : float
+ The x-coordinate of the hit.
+ coord_y : float
+ The y-coordinate of the hit.
+ landing_pos_x : float
+ The x-coordinate of the hit's landing position.
+ landing_pos_y : float
+ The y-coordinate of the hit's landing position.
"""
- coordx: float
- coordy: float
- landingposx: float
- landingposy: float
+ coord_x: Optional[float] = Field(default=None, alias="coordx")
+ coord_y: Optional[float] = Field(default=None, alias="coordy")
+ landing_pos_x: Optional[float] = Field(default=None, alias="landingposx")
+ landing_pos_y: Optional[float] = Field(default=None, alias="landingposy")
-@dataclass
-class Trajectorydata:
- """"
+
+class TrajectoryData(MLBBaseModel):
+ """
A class representing data on a hit's trajectory in three-dimensional space.
Attributes
----------
- trajectorypolynomialx : List[int]
- A list of coefficients for the polynomial representing the
- x-coordinate of the hits's trajectory
- trajectorypolynomialy : List[int]
- A list of coefficients for the polynomial representing the
- y-coordinate of the hits's trajectory
- trajectorypolynomialz : List[int]
- A list of coefficients for the polynomial representing the
- z-coordinate of the hits's trajectory
- validtimeinterval : List[int]
- A list of two elements representing the start and end times for which
- the polynomial coefficients are valid
- measuredtimeinterval : List[int]
- A list of two elements representing the start and end times of the
- interval during which the hits's trajectory was measured
+ trajectory_polynomial_x : List[float]
+ Coefficients for the polynomial representing the x-coordinate trajectory.
+ trajectory_polynomial_y : List[float]
+ Coefficients for the polynomial representing the y-coordinate trajectory.
+ trajectory_polynomial_z : List[float]
+ Coefficients for the polynomial representing the z-coordinate trajectory.
+ valid_time_interval : List[float]
+ Start and end times for which the polynomial coefficients are valid.
+ measured_time_interval : List[float]
+ Start and end times of the interval during which trajectory was measured.
"""
- trajectorypolynomialx: List[int]
- trajectorypolynomialy: List[int]
- trajectorypolynomialz: List[int]
- validtimeinterval: List[int]
- measuredtimeinterval: List[int]
+ trajectory_polynomial_x: List[float] = Field(alias="trajectorypolynomialx")
+ trajectory_polynomial_y: List[float] = Field(alias="trajectorypolynomialy")
+ trajectory_polynomial_z: List[float] = Field(alias="trajectorypolynomialz")
+ valid_time_interval: List[float] = Field(alias="validtimeinterval")
+ measured_time_interval: List[float] = Field(alias="measuredtimeinterval")
+
+
+class HitData(MLBBaseModel):
+ """
+ A class representing data on a hit.
-@dataclass
-class Hitdata:
- """"
- A class representing data on a hit
-
Attributes
----------
- launchspeed : float
- The speed at which the hit was launched
- totaldistance : int
- The total distance the hit traveled
- launchangle : float: None
- The angle at which the hit was launched, if applicable
- coordinates : Coordinates: None
- Coordinates for the hit
- trajectorydata : Trajectorydata: None
- Trajectory data for the hit
+ total_distance : int
+ The total distance the hit traveled.
+ launch_speed : float
+ The speed at which the hit was launched.
+ launch_angle : float
+ The angle at which the hit was launched.
+ coordinates : Coordinates
+ Coordinates for the hit.
+ trajectory_data : TrajectoryData
+ Trajectory data for the hit.
"""
- totaldistance: int
- launchspeed: Optional[float] = None
- launchangle: Optional[float] = None
- coordinates: Optional[Union[Coordinates, dict]] = None
- trajectorydata: Optional[Union[Trajectorydata, dict]] = None
+ total_distance: int = Field(alias="totaldistance")
+ launch_speed: Optional[float] = Field(default=None, alias="launchspeed")
+ launch_angle: Optional[float] = Field(default=None, alias="launchangle")
+ coordinates: Optional[Coordinates] = None
+ trajectory_data: Optional[TrajectoryData] = Field(default=None, alias="trajectorydata")
- def __post_init__(self):
- self.coordinates = Coordinates(**self.coordinates) if self.coordinates else None
- self.trajectorydata = Trajectorydata(**self.trajectorydata) if self.trajectorydata else None
-@dataclass
-class Hits:
- """"
- A class representing a hit in the homerun derby
+class Hits(MLBBaseModel):
+ """
+ A class representing a hit in the homerun derby.
Attributes
----------
- bonustime : bool
- A boolean indicating whether the hit occurred during bonus time.
+ bonus_time : bool
+ Whether the hit occurred during bonus time.
homerun : bool
- A boolean indicating whether the hit was a homerun.
+ Whether the hit was a homerun.
tiebreaker : bool
- A boolean indicating whether the hit occurred during a tiebreaker.
- hitdata : Hitdata
- An object containing the data for the hit. This can either be a
- Hitdata object or a dictionary.
- ishomerun : bool
- A boolean indicating whether the hit was a homerun. This attribute
- is a duplicate of the `homerun` attribute.
- playid : str
- A string containing the ID of the play in which the hit occurred.
- timeremaining : str
- A string indicating the amount of time remaining in the game when the
- hit occurred.
- isbonustime : bool
- A boolean indicating whether the hit occurred during bonus time. This
- attribute is a duplicate of the `bonustime` attribute.
- timeremainingseconds : int
- A integer indicated the amount of time remaining in seconds
- istiebreaker : bool
- A boolean indicating whether the hit occurred during a tiebreaker.
- This attribute is a duplicate of the `tiebreaker` attribute.
+ Whether the hit occurred during a tiebreaker.
+ hit_data : HitData
+ The data for the hit.
+ is_homerun : bool
+ Whether the hit was a homerun.
+ time_remaining : str
+ Amount of time remaining when the hit occurred.
+ is_bonus_time : bool
+ Whether the hit occurred during bonus time.
+ time_remaining_seconds : int
+ Amount of time remaining in seconds.
+ is_tiebreaker : bool
+ Whether the hit occurred during a tiebreaker.
+ play_id : str
+ The ID of the play in which the hit occurred.
"""
- bonustime: bool
+ bonus_time: bool = Field(alias="bonustime")
homerun: bool
tiebreaker: bool
- hitdata: Union[Hitdata, dict]
- ishomerun: bool
- timeremaining: str
- isbonustime: bool
- istiebreaker: bool
- timeremainingseconds: Optional[int] = None
- playid: Optional[str] = None
+ hit_data: HitData = Field(alias="hitdata")
+ is_homerun: bool = Field(alias="ishomerun")
+ time_remaining: str = Field(alias="timeremaining")
+ is_bonus_time: bool = Field(alias="isbonustime")
+ is_tiebreaker: bool = Field(alias="istiebreaker")
+ time_remaining_seconds: Optional[int] = Field(default=None, alias="timeremainingseconds")
+ play_id: Optional[str] = Field(default=None, alias="playid")
- def __post_init__(self):
- self.hitdata = Hitdata(**self.hitdata)
-@dataclass
-class Seed:
- """"
- A class representing either a high or a low seed in the matchup for
- the homerun derby.
+class Seed(MLBBaseModel):
+ """
+ A class representing a seed in a homerun derby matchup.
Attributes
----------
complete : bool
- A boolean indicating whether the seed has been completed.
+ Whether the seed has been completed.
started : bool
- A boolean indicating whether the seed has been started.
+ Whether the seed has been started.
winner : bool
- A boolean indicating whether the player for this seed is the winner
- of the game.
+ Whether the player for this seed is the winner.
player : Person
- An object containing the data for the player associated with this
- seed. This can either be a Person object or a dictionary.
- topderbyhitdata : Hitdata
- An object containing the data for the top hit in the seed. This can
- either be a Hitdata object or a dictionary.
- hits : Hits
- An object containing the data for the hits in the seed. This can
- either be a Hits object or a dictionary.
+ The player associated with this seed.
+ top_derby_hit_data : HitData
+ The data for the top hit in the seed.
+ hits : List[Hits]
+ The hits in the seed.
seed : int
- An integer representing the seed number.
+ The seed number.
order : int
- An integer representing the order in which the seed was played.
- iswinner : bool
- A boolean indicating whether the player for this seed is the winner
- of the game. This attribute is a duplicate of the `winner` attribute.
- iscomplete : bool
- A boolean indicating whether the seed has been completed. This
- attribute is a duplicate of the `complete` attribute.
- isstarted : bool
- A boolean indicating whether the seed has been started. This
- attribute is a duplicate of the `started` attribute.
- numhomeruns : int
- An integer representing the number of homeruns hit in the seed.
+ The order in which the seed was played.
+ is_winner : bool
+ Whether the player for this seed is the winner.
+ is_complete : bool
+ Whether the seed has been completed.
+ is_started : bool
+ Whether the seed has been started.
+ num_homeruns : int
+ The number of homeruns hit in the seed.
"""
complete: bool
started: bool
winner: bool
- player: Union[Person, dict]
- topderbyhitdata: Union[Hitdata, dict]
- hits: Union[Hits, dict]
+ player: Person
+ top_derby_hit_data: HitData = Field(alias="topderbyhitdata")
+ hits: List[Hits] = []
seed: int
order: int
- iswinner: bool
- iscomplete: bool
- isstarted: bool
- numhomeruns: int
+ is_winner: bool = Field(alias="iswinner")
+ is_complete: bool = Field(alias="iscomplete")
+ is_started: bool = Field(alias="isstarted")
+ num_homeruns: int = Field(alias="numhomeruns")
- def __post_init__(self):
- self.player = Person(**self.player)
- self.topderbyhitdata = Hitdata(**self.topderbyhitdata)
- self.hits = [Hits(**hit) for hit in self.hits]
-@dataclass
-class Matchup:
- """"
- A class representing a matchup in the homerun derby
-
+class Matchup(MLBBaseModel):
+ """
+ A class representing a matchup in the homerun derby.
+
Attributes
----------
- topseed : Seed
- Containing the top seed in the matchup.
- bottomseed : Seed
- Containing the bottom seed in the matchup.
+ top_seed : Seed
+ The top seed in the matchup.
+ bottom_seed : Seed
+ The bottom seed in the matchup.
"""
- topseed: Union[Seed, dict]
- bottomseed: Union[Seed, dict]
+ top_seed: Seed = Field(alias="topseed")
+ bottom_seed: Seed = Field(alias="bottomseed")
- def __post_init__(self):
- self.topseed = Seed(**self.topseed)
- self.bottomseed = Seed(**self.bottomseed)
-@dataclass
-class Round:
- """"
- A class representing a round in the homerun derby
+class Round(MLBBaseModel):
+ """
+ A class representing a round in the homerun derby.
Attributes
----------
round : int
- An integer representing the round number.
- numbatters : int
- An integer representing the number of batters in the round.
+ The round number.
+ num_batters : int
+ The number of batters in the round.
matchups : List[Matchup]
- A list of objects containing the data for the matchups in the round.
+ The matchups in the round.
"""
round: int
- matchups: List[Union[Matchup, dict]]
- numbatters: Optional[int] = None
-
- def __post_init__(self):
- self.matchups = [Matchup(**matchup) for matchup in self.matchups]
\ No newline at end of file
+ matchups: List[Matchup] = []
+ num_batters: Optional[int] = Field(default=None, alias="numbatters")
diff --git a/mlbstatsapi/models/homerunderby/homerunderby.py b/mlbstatsapi/models/homerunderby/homerunderby.py
index 360b95ec..66705315 100644
--- a/mlbstatsapi/models/homerunderby/homerunderby.py
+++ b/mlbstatsapi/models/homerunderby/homerunderby.py
@@ -1,42 +1,39 @@
-from typing import Union, List
-from dataclasses import dataclass
-
+from typing import List, Any
+from pydantic import field_validator
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.people import Person
-
from .attributes import Info, Status, Round
-@dataclass
-class Homerunderby:
+class HomeRunDerby(MLBBaseModel):
"""
- A class representing a homerun derby
+ A class representing a homerun derby.
Attributes
----------
info : Info
- An object containing information about the game.
+ Information about the event.
status : Status
- An object containing the status of the game.
- rounds : Round
- A list of Round objects representing the rounds in the game.
+ The status of the game.
+ rounds : List[Round]
+ The rounds in the game.
players : List[Person]
- A list of objects containing the data for the players in the game.
+ The players in the game.
"""
- info: Union[Info, dict]
- status: Union[Status, dict]
- rounds: List[Round]
- players: List[Union[Person, dict]]
-
- def __post_init__(self):
- self.info = Info(**self.info)
- self.status = Status(**self.status)
- self.rounds = [Round(**round) for round in self.rounds]
-
- player_list = []
-
- for player in self.players:
- if 'stats' in player:
- player.pop('stats')
- player_list.append(Person(**player))
-
- self.players = player_list
\ No newline at end of file
+ info: Info
+ status: Status
+ rounds: List[Round] = []
+ players: List[Person] = []
+
+ @field_validator('players', mode='before')
+ @classmethod
+ def clean_players(cls, v: Any) -> Any:
+ """Remove 'stats' key from player dicts before validation."""
+ if isinstance(v, list):
+ cleaned = []
+ for player in v:
+ if isinstance(player, dict) and 'stats' in player:
+ player = {k: val for k, val in player.items() if k != 'stats'}
+ cleaned.append(player)
+ return cleaned
+ return v
diff --git a/mlbstatsapi/models/leagues/league.py b/mlbstatsapi/models/leagues/league.py
index 152986a6..508883fe 100644
--- a/mlbstatsapi/models/leagues/league.py
+++ b/mlbstatsapi/models/leagues/league.py
@@ -1,25 +1,24 @@
-from dataclasses import dataclass
-from typing import Optional, Union
-
+from typing import Optional
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.sports import Sport
from mlbstatsapi.models.seasons import Season
-@dataclass
-class LeagueRecord:
+class LeagueRecord(MLBBaseModel):
"""
- A class to represent a leaguerecord.
+ A class to represent a league record.
Attributes
----------
wins : int
- number of wins in leaguerecord
+ Number of wins in league record.
losses : int
- number of losses in leaguerecord
- ties : int
- number of ties in leaguerecord
+ Number of losses in league record.
pct : str
- winning pct of leaguerecord
+ Winning percentage of league record.
+ ties : int
+ Number of ties in league record.
"""
wins: int
losses: int
@@ -27,79 +26,70 @@ class LeagueRecord:
ties: Optional[int] = None
-@dataclass(repr=False)
-class League:
+class League(MLBBaseModel):
"""
A class to represent a league.
Attributes
----------
id : int
- id number of the league
- name : str
- name of the league
+ ID number of the league.
link : str
- link of the league
+ API link for the league.
+ name : str
+ Name of the league.
abbreviation : str
- abbreviation the league
- nameshort : str
- Short name for the league
- seasonstate : str
- State of the leagues season
- haswildcard : bool
- Status of the leagues wildcard
- hassplitseason : bool
- Status of the leagues split season
- numgames : int
- Total number of league games
- hasplayoffpoints : bool
- Status of the leagues playoff points
- numteams : int
- Total number of team in league
- numwildcardteams : int
- Total number of wildcard teams in league
- seasondateinfo : Season
- Season obj
+ Abbreviation of the league.
+ name_short : str
+ Short name for the league.
+ season_state : str
+ State of the league's season.
+ has_wildcard : bool
+ Status of the league's wildcard.
+ has_split_season : bool
+ Status of the league's split season.
+ num_games : int
+ Total number of league games.
+ has_playoff_points : bool
+ Status of the league's playoff points.
+ num_teams : int
+ Total number of teams in league.
+ num_wildcard_teams : int
+ Total number of wildcard teams in league.
+ season_date_info : Season
+ Season object.
season : str
- League season
- orgcode : str
- Leagues orginization code
- conferencesinuse : bool
- Status of the in use conferences of the league
- divisionsinuse : bool
- Status of leagues divisions in use
+ League season.
+ org_code : str
+ League's organization code.
+ conferences_in_use : bool
+ Status of in-use conferences of the league.
+ divisions_in_use : bool
+ Status of league's divisions in use.
sport : Sport
- What 'sport' this league is a part of
- sortorder : int
- League sort order
+ What sport this league is a part of.
+ sort_order : int
+ League sort order.
active : bool
- Status on the activity of the league
+ Status on the activity of the league.
"""
id: int
link: str
name: Optional[str] = None
abbreviation: Optional[str] = None
- nameshort: Optional[str] = None
- seasonstate: Optional[str] = None
- haswildcard: Optional[bool] = None
- hassplitseason: Optional[bool] = None
- numgames: Optional[int] = None
- hasplayoffpoints: Optional[bool] = None
- numteams: Optional[int] = None
- numwildcardteams: Optional[int] = None
- seasondateinfo: Optional[Union[Season, dict]] = None
+ name_short: Optional[str] = Field(default=None, alias="nameshort")
+ season_state: Optional[str] = Field(default=None, alias="seasonstate")
+ has_wildcard: Optional[bool] = Field(default=None, alias="haswildcard")
+ has_split_season: Optional[bool] = Field(default=None, alias="hassplitseason")
+ num_games: Optional[int] = Field(default=None, alias="numgames")
+ has_playoff_points: Optional[bool] = Field(default=None, alias="hasplayoffpoints")
+ num_teams: Optional[int] = Field(default=None, alias="numteams")
+ num_wildcard_teams: Optional[int] = Field(default=None, alias="numwildcardteams")
+ season_date_info: Optional[Season] = Field(default=None, alias="seasondateinfo")
season: Optional[str] = None
- orgcode: Optional[str] = None
- conferencesinuse: Optional[bool] = None
- divisionsinuse: Optional[bool] = None
- sport: Optional[Union[Sport, dict]] = None
- sortorder: Optional[int] = None
+ org_code: Optional[str] = Field(default=None, alias="orgcode")
+ conferences_in_use: Optional[bool] = Field(default=None, alias="conferencesinuse")
+ divisions_in_use: Optional[bool] = Field(default=None, alias="divisionsinuse")
+ sport: Optional[Sport] = None
+ sort_order: Optional[int] = Field(default=None, alias="sortorder")
active: Optional[bool] = None
-
- def __post_init__(self):
- self.seasondateinfo = Season(**self.seasondateinfo) if self.seasondateinfo else self.seasondateinfo
- self.sport = Sport(**self.sport) if self.sport else self.sport
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
diff --git a/mlbstatsapi/models/people/__init__.py b/mlbstatsapi/models/people/__init__.py
index 14b3469b..c3eeac0d 100644
--- a/mlbstatsapi/models/people/__init__.py
+++ b/mlbstatsapi/models/people/__init__.py
@@ -1,2 +1,2 @@
-from .attributes import BatSide, Position, PitchHand, Status
+from .attributes import BatSide, Position, PitchHand, Status, Home, School
from .people import Player, Coach, Person, Batter, Pitcher, DraftPick
diff --git a/mlbstatsapi/models/people/attributes.py b/mlbstatsapi/models/people/attributes.py
index 778753e2..dcc7f2e3 100644
--- a/mlbstatsapi/models/people/attributes.py
+++ b/mlbstatsapi/models/people/attributes.py
@@ -1,53 +1,52 @@
-from dataclasses import dataclass
+from typing import Optional
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
-@dataclass
-class BatSide:
+class BatSide(MLBBaseModel):
"""
- A class to represent a BatSide.
+ A class to represent a bat side.
Attributes
----------
code : str
- code number of the BatSide
- descritpion: str
- description of the BatSide
+ Code of the bat side.
+ description : str
+ Description of the bat side.
"""
code: str
description: str
-@dataclass
-class PitchHand:
+class PitchHand(MLBBaseModel):
"""
- A class to represent a PitchHand.
+ A class to represent a pitch hand.
Attributes
----------
code : str
- code number of the PitchHand
- descritpion: str
- description of the PitchHand
+ Code of the pitch hand.
+ description : str
+ Description of the pitch hand.
"""
code: str
description: str
-@dataclass
-class Position:
+class Position(MLBBaseModel):
"""
- A class to represent a batside.
+ A class to represent a position.
Attributes
----------
- code: str
- code number of the Position
- name: str
- the name of the Position
- type: str
- the type of the Position
- abbreviation: str
- the abbreviation of the Position
+ code : str
+ Code of the position.
+ name : str
+ Name of the position.
+ type : str
+ Type of the position.
+ abbreviation : str
+ Abbreviation of the position.
"""
code: str
name: str
@@ -55,25 +54,24 @@ class Position:
abbreviation: str
-@dataclass
-class Status:
+class Status(MLBBaseModel):
"""
- A dataclass to hold player status
+ A class to represent player status.
Attributes
----------
- code: str
- code of the player
- description: str
- description of the status
+ code : str
+ Code of the player status.
+ description : str
+ Description of the status.
"""
code: str
description: str
-@dataclass
-class Home:
+
+class Home(MLBBaseModel):
"""
- A home is a where a draft player is from
+ A class to represent where a draft player is from.
Attributes
----------
@@ -88,16 +86,16 @@ class Home:
state: str
country: str
-@dataclass
-class School:
+
+class School(MLBBaseModel):
"""
- Represents the school the draft player is from.
+ A class to represent the school a draft player is from.
Attributes
----------
name : str
The name of the school.
- schoolclass : str
+ school_class : str
The class the student is in.
city : str
The city where the school is located.
@@ -107,7 +105,7 @@ class School:
The state where the school is located.
"""
name: str
- schoolclass: str
+ school_class: str = Field(alias="schoolclass")
city: str
country: str
- state: str
\ No newline at end of file
+ state: str
diff --git a/mlbstatsapi/models/people/people.py b/mlbstatsapi/models/people/people.py
index 209d7412..15c6ef06 100644
--- a/mlbstatsapi/models/people/people.py
+++ b/mlbstatsapi/models/people/people.py
@@ -1,222 +1,214 @@
-from dataclasses import dataclass, field, InitVar
-from typing import Union, Dict, Any, Optional
-
+from __future__ import annotations
+from typing import Optional, Any, TYPE_CHECKING
+from pydantic import Field, field_validator, model_validator
+from mlbstatsapi.models.base import MLBBaseModel
from .attributes import BatSide, Position, PitchHand, Status, Home, School
from mlbstatsapi.models.teams import Team
from mlbstatsapi.models.data import CodeDesc
-# from mlbstatsapi.models.drafts import Home, College
-@dataclass(repr=False)
-class Person:
+class Person(MLBBaseModel):
"""
A class to represent a Person.
Attributes
----------
id : int
- id number of the person
- full_name : str
- full_name of the person
+ ID number of the person.
link : str
- Api link to person
- primaryposition : Position
- PrimaryPosition of the Person
- pitchhand : str
- PitchHand of the Person
- batside : str
- BatSide of the Person
- fullname : str
- full name of the Person
- firstname : str
- First name of the Person
- lastname : str
- Last name of the Person
- primarynumber : str
- Primary number of the Person
- birthdate : str
- Birth date of the Person
- currentteam : str
- The current Team of the Person
- currentage : str
- The current age of the Person
- birthcity : str
- The birthcity of the Person
- birthstateprovince : str
- The province of the birth state
+ API link to person.
+ primary_position : Position
+ Primary position of the person.
+ pitch_hand : PitchHand
+ Pitch hand of the person.
+ bat_side : BatSide
+ Bat side of the person.
+ full_name : str
+ Full name of the person.
+ first_name : str
+ First name of the person.
+ last_name : str
+ Last name of the person.
+ primary_number : str
+ Primary number of the person.
+ birth_date : str
+ Birth date of the person.
+ current_team : Team
+ The current team of the person.
+ current_age : int
+ The current age of the person.
+ birth_city : str
+ The birth city of the person.
+ birth_state_province : str
+ The province of the birth state.
height : str
- The height of the Person
- weight : str
- The weight of the Person
- active : str
- The active status of the Person
- usename : str
- The use name of the Person
- middlename : str
- The middle name of the Person
- boxscorename : str
- The box score name of the Person
+ The height of the person.
+ weight : int
+ The weight of the person.
+ active : bool
+ The active status of the person.
+ use_name : str
+ The use name of the person.
+ middle_name : str
+ The middle name of the person.
+ boxscore_name : str
+ The box score name of the person.
nickname : str
- The nickname of the Person
- draftyear : int
- The draft year of the Person
- mlbdebutdate : str
- The MLB debut date of the Person
- namefirstlast : str
- The first and last name of the Person
- nameslug : str
- The name slug of the Person
- firstlastname : str
- The first and last name of the Person
- lastfirstname : str
- The last and first name of the Person
- lastinitname : str
- The last init name of the Person
- initlastname : str
- The init last name of the Person
- fullfmlname : str
- The full fml name of the Person
- fulllfmname : str
- The full lfm name of the Person
- uselastname : str
- The last name of the
- birthcountry : str
- The birth country of the Person
+ The nickname of the person.
+ draft_year : int
+ The draft year of the person.
+ mlb_debut_date : str
+ The MLB debut date of the person.
+ name_first_last : str
+ The first and last name of the person.
+ name_slug : str
+ The name slug of the person.
+ first_last_name : str
+ The first and last name of the person.
+ last_first_name : str
+ The last and first name of the person.
+ last_init_name : str
+ The last init name of the person.
+ init_last_name : str
+ The init last name of the person.
+ full_fml_name : str
+ The full FML name of the person.
+ full_lfm_name : str
+ The full LFM name of the person.
+ use_last_name : str
+ The use last name of the person.
+ birth_country : str
+ The birth country of the person.
pronunciation : str
- The pronuciation of the Person's name
- strikezonetop : float
- The strike zone top of the Person
- strikezonebottom : float
- The strike zone bottom of the Person
- nametitle : str
- The name title of the Person
+ The pronunciation of the person's name.
+ strike_zone_top : float
+ The strike zone top of the person.
+ strike_zone_bottom : float
+ The strike zone bottom of the person.
+ name_title : str
+ The name title of the person.
gender : str
- The gender of the Person
- isplayer : bool
- The player status of the Person
- isverified : bool
- The verification of the Person
- namematrilineal : str
- The name matrilineal of the Person
- deathdate : str
- The death date of the Person
- deathcity : str
- The death city of the Person
- deathcountry : str
- The death country of the Person
- lastplayeddate : str
- The last played date of the Person
- namesuffix : str
- The namesuffix of the Person
+ The gender of the person.
+ is_player : bool
+ The player status of the person.
+ is_verified : bool
+ The verification of the person.
+ name_matrilineal : str
+ The name matrilineal of the person.
+ death_date : str
+ The death date of the person.
+ death_city : str
+ The death city of the person.
+ death_country : str
+ The death country of the person.
+ death_state_province : str
+ The death state province of the person.
+ last_played_date : str
+ The last played date of the person.
+ name_suffix : str
+ The name suffix of the person.
"""
-
id: int
link: str
- primaryposition: Union[Position, Dict[str, Any]] = field(default_factory=dict)
- pitchhand: Union[PitchHand, Dict[str, Any]] = field(default_factory=dict)
- batside: Union[BatSide, Dict[str, Any]] = field(default_factory=dict)
- fullname: Optional[str] = None
- firstname: Optional[str] = None
- lastname: Optional[str] = None
- primarynumber: Optional[str] = None
- birthdate: Optional[str] = None
- currentteam: Optional[str] = None
- currentage: Optional[str] = None
- birthcity: Optional[str] = None
- birthstateprovince: Optional[str] = None
+ primary_position: Optional[Position] = Field(default=None, alias="primaryposition")
+ pitch_hand: Optional[PitchHand] = Field(default=None, alias="pitchhand")
+ bat_side: Optional[BatSide] = Field(default=None, alias="batside")
+ full_name: Optional[str] = Field(default=None, alias="fullname")
+ first_name: Optional[str] = Field(default=None, alias="firstname")
+ last_name: Optional[str] = Field(default=None, alias="lastname")
+ primary_number: Optional[str] = Field(default=None, alias="primarynumber")
+ birth_date: Optional[str] = Field(default=None, alias="birthdate")
+ current_team: Optional[Team] = Field(default=None, alias="currentteam")
+ current_age: Optional[int] = Field(default=None, alias="currentage")
+ birth_city: Optional[str] = Field(default=None, alias="birthcity")
+ birth_state_province: Optional[str] = Field(default=None, alias="birthstateprovince")
height: Optional[str] = None
weight: Optional[int] = None
active: Optional[bool] = None
- usename: Optional[str] = None
- middlename: Optional[str] = None
- boxscorename: Optional[str] = None
+ use_name: Optional[str] = Field(default=None, alias="usename")
+ middle_name: Optional[str] = Field(default=None, alias="middlename")
+ boxscore_name: Optional[str] = Field(default=None, alias="boxscorename")
nickname: Optional[str] = None
- draftyear: Optional[int] = None
- mlbdebutdate: Optional[str] = None
- namefirstlast: Optional[str] = None
- nameslug: Optional[str] = None
- firstlastname: Optional[str] = None
- lastfirstname: Optional[str] = None
- lastinitname: Optional[str] = None
- initlastname: Optional[str] = None
- fullfmlname: Optional[str] = None
- fulllfmname: Optional[str] = None
- birthcountry: Optional[str] = None
+ draft_year: Optional[int] = Field(default=None, alias="draftyear")
+ mlb_debut_date: Optional[str] = Field(default=None, alias="mlbdebutdate")
+ name_first_last: Optional[str] = Field(default=None, alias="namefirstlast")
+ name_slug: Optional[str] = Field(default=None, alias="nameslug")
+ first_last_name: Optional[str] = Field(default=None, alias="firstlastname")
+ last_first_name: Optional[str] = Field(default=None, alias="lastfirstname")
+ last_init_name: Optional[str] = Field(default=None, alias="lastinitname")
+ init_last_name: Optional[str] = Field(default=None, alias="initlastname")
+ full_fml_name: Optional[str] = Field(default=None, alias="fullfmlname")
+ full_lfm_name: Optional[str] = Field(default=None, alias="fulllfmname")
+ birth_country: Optional[str] = Field(default=None, alias="birthcountry")
pronunciation: Optional[str] = None
- strikezonetop: Optional[float] = None
- strikezonebottom: Optional[float] = None
- nametitle: Optional[str] = None
+ strike_zone_top: Optional[float] = Field(default=None, alias="strikezonetop")
+ strike_zone_bottom: Optional[float] = Field(default=None, alias="strikezonebottom")
+ name_title: Optional[str] = Field(default=None, alias="nametitle")
gender: Optional[str] = None
- isplayer: Optional[bool] = None
- isverified: Optional[bool] = None
- namematrilineal: Optional[str] = None
- deathdate: Optional[str] = None
- deathcity: Optional[str] = None
- deathcountry: Optional[str] = None
- deathstateprovince: Optional[str] = None
- lastplayeddate: Optional[str] = None
- uselastname: Optional[str] = None
- namesuffix: Optional[str] = None
-
- def __post_init__(self):
- self.primaryposition = Position(**self.primaryposition) if self.primaryposition else self.primaryposition
- self.pitchhand = PitchHand(**self.pitchhand) if self.pitchhand else self.pitchhand
- self.batside = BatSide(**self.batside) if self.batside else self.batside
+ is_player: Optional[bool] = Field(default=None, alias="isplayer")
+ is_verified: Optional[bool] = Field(default=None, alias="isverified")
+ name_matrilineal: Optional[str] = Field(default=None, alias="namematrilineal")
+ death_date: Optional[str] = Field(default=None, alias="deathdate")
+ death_city: Optional[str] = Field(default=None, alias="deathcity")
+ death_country: Optional[str] = Field(default=None, alias="deathcountry")
+ death_state_province: Optional[str] = Field(default=None, alias="deathstateprovince")
+ last_played_date: Optional[str] = Field(default=None, alias="lastplayeddate")
+ use_last_name: Optional[str] = Field(default=None, alias="uselastname")
+ name_suffix: Optional[str] = Field(default=None, alias="namesuffix")
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-@dataclass(kw_only=True, repr=False)
class Player(Person):
"""
A class to represent a Player.
Attributes
----------
- jerseynumber : str
- id number of the person
- status :
- Status of the player
- parentteamid : int
- parent team id
+ jersey_number : str
+ Jersey number of the player.
+ status : Status
+ Status of the player.
+ parent_team_id : int
+ Parent team ID.
note : str
- Optional str that allows a note to be added to a player. Such cases seen
- include injury notes.
+ Optional note about the player (e.g., injury notes).
+ position : Position
+ Position of the player (alias for primary_position).
"""
- parentteamid: Optional[int] = None
- jerseynumber: str
- position: InitVar[dict]
- status: Union[Status, dict]
+ jersey_number: str = Field(alias="jerseynumber")
+ status: Status
+ parent_team_id: Optional[int] = Field(default=None, alias="parentteamid")
note: Optional[str] = None
- def __post_init__(self, position: dict):
- self.primaryposition = Position(**position) if position else None
+ @model_validator(mode='before')
+ @classmethod
+ def handle_position_alias(cls, data):
+ """Handle 'position' field as alias for 'primary_position'."""
+ if isinstance(data, dict) and 'position' in data and 'primary_position' not in data:
+ data['primary_position'] = data.pop('position')
+ return data
-@dataclass(kw_only=True, repr=False)
class Coach(Person):
"""
- A class to represent a Player.
+ A class to represent a Coach.
Attributes
----------
- jerseynumber : str
- id number of the person
+ jersey_number : str
+ Jersey number of the coach.
job : str
- job of the coach
- jobid : str
- job id of the coach
+ Job of the coach.
+ job_id : str
+ Job ID of the coach.
title : str
- title of the coach
- parentteamid : int
+ Title of the coach.
"""
- jerseynumber: str
+ jersey_number: str = Field(alias="jerseynumber")
job: str
- jobid: str
+ job_id: str = Field(alias="jobid")
title: str
-@dataclass(kw_only=True)
+
class Batter(Person):
"""
A class to represent a Batter.
@@ -224,75 +216,68 @@ class Batter(Person):
pass
-@dataclass(kw_only=True)
class Pitcher(Person):
"""
- A class to represent a Pitcher
+ A class to represent a Pitcher.
"""
pass
-@dataclass(kw_only=True)
class DraftPick(Person):
"""
- Represents a pick made in the MLB draft.
+ A class to represent a pick made in the MLB draft.
Attributes
----------
- bisplayerid : int
+ bis_player_id : int
The unique identifier of the player associated with this draft pick.
- pickround : str
+ pick_round : str
The round of the draft in which this pick was made.
- picknumber : int
+ pick_number : int
The number of the pick in the round.
- roundpicknumber : int
+ round_pick_number : int
The number of the pick overall in the draft.
rank : int
The rank of the player among all players eligible for the draft.
- pickvalue : str
+ pick_value : str
The value of the pick, if known.
- signingbonus : str
+ signing_bonus : str
The signing bonus associated with this pick, if known.
home : Home
Information about the player's home location.
- scoutingreport : str
- A scouting report on the player's abilities.
+ scouting_report : str
+ A scouting report on the player's abilities.
school : School
Information about the player's school or college.
blurb : str
- A brief summary of the player's background and accomplishments.
- headshotlink : str
- A link to a headshot image of the player.
- team : Team or dict
+ A brief summary of the player's background and accomplishments.
+ headshot_link : str
+ A link to a headshot image of the player.
+ team : Team
The team that made this draft pick.
- drafttype : CodeDesc
+ draft_type : CodeDesc
Information about the type of draft in which this pick was made.
- isdrafted : bool
+ is_drafted : bool
Whether or not the player associated with this pick has been drafted.
- ispass : bool
+ is_pass : bool
Whether or not the team passed on making a pick in this round.
year : str
The year in which the draft took place.
"""
-
- bisplayerid: Optional[int] = None
- pickround: str
- picknumber: int
- roundpicknumber: int
+ pick_round: str = Field(alias="pickround")
+ pick_number: int = Field(alias="picknumber")
+ round_pick_number: int = Field(alias="roundpicknumber")
+ home: Home
+ school: School
+ headshot_link: str = Field(alias="headshotlink")
+ team: Team
+ draft_type: CodeDesc = Field(alias="drafttype")
+ is_drafted: bool = Field(alias="isdrafted")
+ is_pass: bool = Field(alias="ispass")
+ year: str
+ bis_player_id: Optional[int] = Field(default=None, alias="bisplayerid")
rank: Optional[int] = None
- pickvalue: Optional[str] = None
- signingbonus: Optional[str] = None
- home: Union[Home , dict]
- scoutingreport: Optional[str] = None
- school: Union[School , dict]
+ pick_value: Optional[str] = Field(default=None, alias="pickvalue")
+ signing_bonus: Optional[str] = Field(default=None, alias="signingbonus")
+ scouting_report: Optional[str] = Field(default=None, alias="scoutingreport")
blurb: Optional[str] = None
- headshotlink: str
- team: Union[Team, dict]
- drafttype: Union[CodeDesc, dict]
- isdrafted: bool
- ispass: bool
- year: str
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
diff --git a/mlbstatsapi/models/schedules/__init__.py b/mlbstatsapi/models/schedules/__init__.py
index cd8723d8..3040f3fe 100644
--- a/mlbstatsapi/models/schedules/__init__.py
+++ b/mlbstatsapi/models/schedules/__init__.py
@@ -1,2 +1,2 @@
from .schedule import Schedule
-from .attributes import ScheduleGames
\ No newline at end of file
+from .attributes import ScheduleGames, ScheduleDates, ScheduleHomeAndAway, ScheduleGameTeam
diff --git a/mlbstatsapi/models/schedules/attributes.py b/mlbstatsapi/models/schedules/attributes.py
index 2a21ea63..dbac859d 100644
--- a/mlbstatsapi/models/schedules/attributes.py
+++ b/mlbstatsapi/models/schedules/attributes.py
@@ -1,221 +1,210 @@
-from dataclasses import dataclass, field
-from typing import Optional, Union, List
+from typing import Optional, List, Any
+from pydantic import Field, field_validator
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.venues import Venue
from mlbstatsapi.models.game.gamedata import GameStatus
from mlbstatsapi.models.teams import Team
from mlbstatsapi.models.leagues import LeagueRecord
-@dataclass(repr=False)
-class ScheduleGameTeam:
+class ScheduleGameTeam(MLBBaseModel):
"""
- A class to represent the sheduled games teams shedule information in a Scheduled Dates game.
+ A class to represent the scheduled game's team schedule information.
Attributes
----------
- leaguerecord : LeagueRecord
- League record for this team
- score : int
- Current score for this team in this game
+ league_record : LeagueRecord
+ League record for this team.
team : Team
- Team info for this game
- iswinner : bool
- If this team is the winner of this game
- splitsquad : bool
- Split squad
- seriesnumber : int
- Series number
+ Team info for this game.
+ split_squad : bool
+ Split squad.
+ series_number : int
+ Series number.
+ score : int
+ Current score for this team in this game.
+ is_winner : bool
+ If this team is the winner of this game.
"""
- leaguerecord: Union[LeagueRecord, dict]
- team: Union[Team, dict]
- splitsquad: bool
- seriesnumber: Optional[int] = None
+ league_record: LeagueRecord = Field(alias="leaguerecord")
+ team: Team
+ split_squad: bool = Field(alias="splitsquad")
+ series_number: Optional[int] = Field(default=None, alias="seriesnumber")
score: Optional[int] = None
- iswinner: Optional[bool] = False
-
- def __post_init__(self):
- self.leaguerecord = LeagueRecord(**self.leaguerecord)
- self.team = Team(**self.team)
+ is_winner: Optional[bool] = Field(default=False, alias="iswinner")
- def __repr__(self):
- return f'ScheduleGameTeam(gamepk={self.leaguerecord}, team={self.team})'
-@dataclass
-class ScheduleHomeAndAway:
+class ScheduleHomeAndAway(MLBBaseModel):
"""
- A class to represent both away and home teams in a Schedules Dates game.
+ A class to represent both away and home teams in a schedule's game.
Attributes
----------
home : ScheduleGameTeam
- Home team info for this game
+ Home team info for this game.
away : ScheduleGameTeam
- Away team info for this game
+ Away team info for this game.
"""
- home: Union[ScheduleGameTeam, dict]
- away: Union[ScheduleGameTeam, dict]
+ home: ScheduleGameTeam
+ away: ScheduleGameTeam
- def __post_init__(self):
- self.home = ScheduleGameTeam(**self.home)
- self.away = ScheduleGameTeam(**self.away)
-
-@dataclass(repr=False)
-class ScheduleGames:
+class ScheduleGames(MLBBaseModel):
"""
- A class to represent a Game in a Schedules Dates.
+ A class to represent a game in a schedule's dates.
Attributes
----------
- gamepk : int
- The games id number
+ game_pk : int
+ The game's ID number.
link : str
- The link for this game
- gametype : str
- This games game type
+ The link for this game.
+ game_type : str
+ This game's game type.
season : str
- The season this game takes place in
- gamedate : str
- The date for this game
- officialdate : str
- The official date for this game
+ The season this game takes place in.
+ game_date : str
+ The date for this game.
+ official_date : str
+ The official date for this game.
status : GameStatus
- The status of this game
+ The status of this game.
teams : ScheduleHomeAndAway
- Holds teams and thier info for this game
- venue : Venue
- The venue this game takes place in
+ Holds teams and their info for this game.
+ venue : Venue
+ The venue this game takes place in.
content : dict
- Content for this game. Havent found a populated reference yet. Stays as dict
- istie : bool
- If this game is a tie
- gamenumber : int
- Game number for this game
- publicfacing : bool
- Is this game public facing
- doubleheader : str
- The double header status for this game, "n','y'?
- gamedaytype : str
- The type of gameday for this game
+ Content for this game.
+ is_tie : bool
+ If this game is a tie.
+ game_number : int
+ Game number for this game.
+ public_facing : bool
+ Is this game public facing.
+ double_header : str
+ The double header status for this game.
+ gameday_type : str
+ The type of gameday for this game.
tiebreaker : str
- Tie breaker for this game, 'n','y'?
- calendareventid : str
- Calender event Id for this game
- seasondisplay : str
- Displayed season for this game
- daynight : str
- Day or night game as a string, 'am','pm'?
- scheduledinnings : int
- Number of scheduled inning for the game
- reversehomeawaystatus : bool
- If reverse home and away?
- gameguid : str = None
- The games guid
- inningbreaklength : int
- Length of break between innings
- gamesinseries : int
- Number of games in current series
- seriesgamenumber : int
- Game number in the current series
- seriesdescription : str
- Description of this current series
- recordsource : str
- Record source
- ifnecessary : str
- If necessary
- ifnecessarydescription : str
- If necessary description
- rescheduledate : str = None
- If game is rescheduled, this is the rescheduled date
- reschedulegamedate : str = None
- rescheduled game date
- rescheduledfrom : str = None
- rescheduled from
- rescheduledfromdate : str = None
- rescheduled from date
- istie : bool = None
- Is tie
+ Tie breaker for this game.
+ calendar_event_id : str
+ Calendar event ID for this game.
+ season_display : str
+ Displayed season for this game.
+ day_night : str
+ Day or night game as a string.
+ scheduled_innings : int
+ Number of scheduled innings for the game.
+ reverse_home_away_status : bool
+ If reverse home and away.
+ series_description : str
+ Description of this current series.
+ record_source : str
+ Record source.
+ if_necessary : str
+ If necessary.
+ if_necessary_description : str
+ If necessary description.
+ game_guid : str
+ The game's GUID.
+ description : str
+ Game description.
+ inning_break_length : int
+ Length of break between innings.
+ games_in_series : int
+ Number of games in current series.
+ series_game_number : int
+ Game number in the current series.
+ reschedule_date : str
+ Rescheduled date if applicable.
+ reschedule_game_date : str
+ Rescheduled game date.
+ rescheduled_from : str
+ Rescheduled from.
+ rescheduled_from_date : str
+ Rescheduled from date.
+ resume_date : str
+ Resume date.
+ resume_game_date : str
+ Resume game date.
+ resumed_from : str
+ Resumed from.
+ resumed_from_date : str
+ Resumed from date.
"""
- gamepk: int
+ game_pk: int = Field(alias="gamepk")
link: str
- gametype: str
+ game_type: str = Field(alias="gametype")
season: str
- gamedate: str
- officialdate: str
+ game_date: str = Field(alias="gamedate")
+ official_date: str = Field(alias="officialdate")
venue: Venue
content: dict
- gamenumber: int
- publicfacing: bool
- doubleheader: str
- gamedaytype: str
+ game_number: int = Field(alias="gamenumber")
+ public_facing: bool = Field(alias="publicfacing")
+ double_header: str = Field(alias="doubleheader")
+ gameday_type: str = Field(alias="gamedaytype")
tiebreaker: str
- calendareventid: str
- seasondisplay: str
- daynight: str
- scheduledinnings: int
- reversehomeawaystatus: bool
- seriesdescription: str
- recordsource: str
- ifnecessary: str
- ifnecessarydescription: str
- status: Union[GameStatus, dict] = field(default_factory=dict)
- teams: Union[ScheduleHomeAndAway, dict] = field(default_factory=dict)
- gameguid: Optional[str] = None
+ calendar_event_id: str = Field(alias="calendareventid")
+ season_display: str = Field(alias="seasondisplay")
+ day_night: str = Field(alias="daynight")
+ scheduled_innings: int = Field(alias="scheduledinnings")
+ reverse_home_away_status: bool = Field(alias="reversehomeawaystatus")
+ series_description: str = Field(alias="seriesdescription")
+ record_source: str = Field(alias="recordsource")
+ if_necessary: str = Field(alias="ifnecessary")
+ if_necessary_description: str = Field(alias="ifnecessarydescription")
+ status: Optional[GameStatus] = None
+ teams: Optional[ScheduleHomeAndAway] = None
+ game_guid: Optional[str] = Field(default=None, alias="gameguid")
description: Optional[str] = None
- inningbreaklength: Optional[int] = None
- rescheduledate: Optional[str] = None
- reschedulegamedate: Optional[str] = None
- rescheduledfrom: Optional[str] = None
- rescheduledfromdate: Optional[str] = None
- istie: Optional[bool] = None
- resumedate: Optional[str] = None
- resumegamedate: Optional[str] = None
- resumedfrom: Optional[str] = None
- resumedfromdate: Optional[str] = None
- seriesgamenumber: Optional[int] = None
- gamesinseries: Optional[int] = None
-
- def __post_init__(self):
- self.status = GameStatus(**self.status) if self.status else self.status
- self.teams = ScheduleHomeAndAway(**self.teams) if self.teams else self.teams
- self.venue = Venue(**self.venue) if self.venue else self.venue
-
- def __repr__(self):
- return f'ScheduleGames(gamepk={self.gamepk}, link={self.link})'
-
-@dataclass(repr=False)
-class ScheduleDates:
+ inning_break_length: Optional[int] = Field(default=None, alias="inningbreaklength")
+ reschedule_date: Optional[str] = Field(default=None, alias="rescheduledate")
+ reschedule_game_date: Optional[str] = Field(default=None, alias="reschedulegamedate")
+ rescheduled_from: Optional[str] = Field(default=None, alias="rescheduledfrom")
+ rescheduled_from_date: Optional[str] = Field(default=None, alias="rescheduledfromdate")
+ is_tie: Optional[bool] = Field(default=None, alias="istie")
+ resume_date: Optional[str] = Field(default=None, alias="resumedate")
+ resume_game_date: Optional[str] = Field(default=None, alias="resumegamedate")
+ resumed_from: Optional[str] = Field(default=None, alias="resumedfrom")
+ resumed_from_date: Optional[str] = Field(default=None, alias="resumedfromdate")
+ series_game_number: Optional[int] = Field(default=None, alias="seriesgamenumber")
+ games_in_series: Optional[int] = Field(default=None, alias="gamesinseries")
+
+ @field_validator('status', 'teams', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
+
+
+class ScheduleDates(MLBBaseModel):
"""
- A class to represent a Schedules Dates.
+ A class to represent a schedule's dates.
Attributes
----------
date : str
- Date for the group of games
- totalitems : int
- Total amount of items for this date
- totalevents : int
- The number of events for this date
- totalgames : int
- The number of games for this date
- totalgamesinprogress : int
- The number of games that are currently in progress for this date
+ Date for the group of games.
+ total_items : int
+ Total amount of items for this date.
+ total_events : int
+ The number of events for this date.
+ total_games : int
+ The number of games for this date.
+ total_games_in_progress : int
+ The number of games that are currently in progress for this date.
games : List[ScheduleGames]
- A list of games for this date
+ A list of games for this date.
events : list
- A list of events for this date. Need to handle this but cant find a populated
- reference for this object. It stays as a list for now.
+ A list of events for this date.
"""
date: str
- totalitems: int
- totalevents: int
- totalgames: int
- totalgamesinprogress: int
- events: List
- games: List[ScheduleGames] = field(default_factory=list)
-
- def __post_init__(self):
- self.games = [ScheduleGames(**game) for game in self.games ] if self.games else self.games
-
- def __repr__(self):
- return f'ScheduleDates(date={self.date}, totalgames={self.totalgames})'
\ No newline at end of file
+ total_items: int = Field(alias="totalitems")
+ total_events: int = Field(alias="totalevents")
+ total_games: int = Field(alias="totalgames")
+ total_games_in_progress: int = Field(alias="totalgamesinprogress")
+ events: List = []
+ games: List[ScheduleGames] = []
diff --git a/mlbstatsapi/models/schedules/schedule.py b/mlbstatsapi/models/schedules/schedule.py
index d1268cd1..5f5b2f34 100644
--- a/mlbstatsapi/models/schedules/schedule.py
+++ b/mlbstatsapi/models/schedules/schedule.py
@@ -1,38 +1,28 @@
from typing import List
-from dataclasses import dataclass, field
-
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from .attributes import ScheduleDates
-@dataclass(repr=False)
-class Schedule:
+class Schedule(MLBBaseModel):
"""
A class to represent a Schedule.
Attributes
----------
- copyright : str
- Copyright
- totalitems : int
- Total items in schedule
- totalevents : int
- Total events in schedule
- totalgames : int
- Total games in schedule
- totalgamesinprogress : int
- Total games in progress in schedule
- dates : ScheduleDates
- List of dates with games in schedule
+ total_items : int
+ Total items in schedule.
+ total_events : int
+ Total events in schedule.
+ total_games : int
+ Total games in schedule.
+ total_games_in_progress : int
+ Total games in progress in schedule.
+ dates : List[ScheduleDates]
+ List of dates with games in schedule.
"""
- totalitems: int
- totalevents: int
- totalgames: int
- totalgamesinprogress: int
- dates: List[ScheduleDates] = field(default_factory=list)
-
- def __post_init__(self):
- self.dates = [ScheduleDates(**date) for date in self.dates if self.dates]
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ total_items: int = Field(alias="totalitems")
+ total_events: int = Field(alias="totalevents")
+ total_games: int = Field(alias="totalgames")
+ total_games_in_progress: int = Field(alias="totalgamesinprogress")
+ dates: List[ScheduleDates] = []
diff --git a/mlbstatsapi/models/seasons/season.py b/mlbstatsapi/models/seasons/season.py
index c709c543..2e90c2d5 100644
--- a/mlbstatsapi/models/seasons/season.py
+++ b/mlbstatsapi/models/seasons/season.py
@@ -1,80 +1,75 @@
-from typing import Optional
-from dataclasses import dataclass
+from typing import Optional
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
-@dataclass(repr=False)
-class Season:
+class Season(MLBBaseModel):
"""
- This class represents a season object
+ A class to represent a season.
Attributes
----------
- seasonid : str
- season id
- haswildcard : bool
- wild card status
- preseasonstartdate : str
- pre-season start date
- preseasonenddate : str
- pre-season end date
- seasonstartdate : str
- season start date
- springstartdate : str
- spring start date
- springenddate : str
- spring end date
- regularseasonstartdate : str
- regular season start date
- lastdate1sthalf : str
- last date 1st half
- allstardate : str
- all star date
- firstdate2ndhalf : str
- first date 2nd half
- regularseasonenddate : str
- regular season end date
- postseasonstartdate : str
- post season start date
- postseasonenddate : str
- post season end date
- seasonenddate : str
- season end date
- offseasonstartdate : str
- off season start date
- offseasonenddate : str
- off season end date
- seasonlevelgamedaytype : str
- season level game day type
- gamelevelgamedaytype : str
- game level game day type
- qualifierplateappearances : float
- qualifier plate appearances
- qualifieroutspitched : int
- qualifier outs pitched
+ season_id : str
+ Season ID.
+ has_wildcard : bool
+ Wild card status.
+ preseason_start_date : str
+ Pre-season start date.
+ preseason_end_date : str
+ Pre-season end date.
+ season_start_date : str
+ Season start date.
+ spring_start_date : str
+ Spring start date.
+ spring_end_date : str
+ Spring end date.
+ regular_season_start_date : str
+ Regular season start date.
+ last_date_1st_half : str
+ Last date of 1st half.
+ all_star_date : str
+ All-star date.
+ first_date_2nd_half : str
+ First date of 2nd half.
+ regular_season_end_date : str
+ Regular season end date.
+ postseason_start_date : str
+ Post season start date.
+ postseason_end_date : str
+ Post season end date.
+ season_end_date : str
+ Season end date.
+ offseason_start_date : str
+ Off season start date.
+ offseason_end_date : str
+ Off season end date.
+ season_level_gameday_type : str
+ Season level game day type.
+ game_level_gameday_type : str
+ Game level game day type.
+ qualifier_plate_appearances : float
+ Qualifier plate appearances.
+ qualifier_outs_pitched : float
+ Qualifier outs pitched.
"""
-
- seasonid: str
- haswildcard: Optional[bool] = None
- preseasonstartdate: Optional[str] = None
- preseasonenddate: Optional[str] = None
- seasonstartdate: Optional[str] = None
- springstartdate: Optional[str] = None
- springenddate: Optional[str] = None
- regularseasonstartdate: Optional[str] = None
- lastdate1sthalf: Optional[str] = None
- allstardate: Optional[str] = None
- firstdate2ndhalf: Optional[str] = None
- regularseasonenddate: Optional[str] = None
- postseasonstartdate: Optional[str] = None
- postseasonenddate: Optional[str] = None
- seasonenddate: Optional[str] = None
- offseasonstartdate: Optional[str] = None
- offseasonenddate: Optional[str] = None
- seasonlevelgamedaytype: Optional[str] = None
- gamelevelgamedaytype: Optional[str] = None
- qualifierplateappearances: Optional[float] = None
- qualifieroutspitched: Optional[int] = None
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ season_id: str = Field(alias="seasonid")
+ has_wildcard: Optional[bool] = Field(default=None, alias="haswildcard")
+ preseason_start_date: Optional[str] = Field(default=None, alias="preseasonstartdate")
+ preseason_end_date: Optional[str] = Field(default=None, alias="preseasonenddate")
+ season_start_date: Optional[str] = Field(default=None, alias="seasonstartdate")
+ spring_start_date: Optional[str] = Field(default=None, alias="springstartdate")
+ spring_end_date: Optional[str] = Field(default=None, alias="springenddate")
+ regular_season_start_date: Optional[str] = Field(default=None, alias="regularseasonstartdate")
+ last_date_1st_half: Optional[str] = Field(default=None, alias="lastdate1sthalf")
+ all_star_date: Optional[str] = Field(default=None, alias="allstardate")
+ first_date_2nd_half: Optional[str] = Field(default=None, alias="firstdate2ndhalf")
+ regular_season_end_date: Optional[str] = Field(default=None, alias="regularseasonenddate")
+ postseason_start_date: Optional[str] = Field(default=None, alias="postseasonstartdate")
+ postseason_end_date: Optional[str] = Field(default=None, alias="postseasonenddate")
+ season_end_date: Optional[str] = Field(default=None, alias="seasonenddate")
+ offseason_start_date: Optional[str] = Field(default=None, alias="offseasonstartdate")
+ offseason_end_date: Optional[str] = Field(default=None, alias="offseasonenddate")
+ season_level_gameday_type: Optional[str] = Field(default=None, alias="seasonlevelgamedaytype")
+ game_level_gameday_type: Optional[str] = Field(default=None, alias="gamelevelgamedaytype")
+ qualifier_plate_appearances: Optional[float] = Field(default=None, alias="qualifierplateappearances")
+ qualifier_outs_pitched: Optional[float] = Field(default=None, alias="qualifieroutspitched")
diff --git a/mlbstatsapi/models/sports/sport.py b/mlbstatsapi/models/sports/sport.py
index 92c200de..4c0826af 100644
--- a/mlbstatsapi/models/sports/sport.py
+++ b/mlbstatsapi/models/sports/sport.py
@@ -1,37 +1,33 @@
-from typing import Optional
-from dataclasses import dataclass, InitVar
+from typing import Optional
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
-@dataclass(repr=False)
-class Sport:
+class Sport(MLBBaseModel):
"""
A class to represent a sport.
Attributes
----------
id : int
- id number of the sport
+ ID number of the sport.
link : str
- link of the sport
- name : str
- name the sport
+ API link for the sport.
+ name : str
+ Name of the sport.
code : str
- Sport code
+ Sport code.
abbreviation : str
- Abbreviation for the sport
- sortorder : int
- Some sort of sorting order
- activestatus : bool
- Is the sport active
+ Abbreviation for the sport.
+ sort_order : int
+ Sorting order.
+ active_status : bool
+ Whether the sport is active.
"""
id: int
link: str
name: Optional[str] = None
code: Optional[str] = None
abbreviation: Optional[str] = None
- sortorder: Optional[int] = None
- activestatus: Optional[bool] = None
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ sort_order: Optional[int] = Field(default=None, alias="sortorder")
+ active_status: Optional[bool] = Field(default=None, alias="activestatus")
diff --git a/mlbstatsapi/models/standings/__init__.py b/mlbstatsapi/models/standings/__init__.py
index 554de97a..65f1579b 100644
--- a/mlbstatsapi/models/standings/__init__.py
+++ b/mlbstatsapi/models/standings/__init__.py
@@ -1,2 +1,2 @@
from .standings import Standings
-from .attributes import Teamrecords
\ No newline at end of file
+from .attributes import TeamRecords, Streak
\ No newline at end of file
diff --git a/mlbstatsapi/models/standings/attributes.py b/mlbstatsapi/models/standings/attributes.py
index 0376481f..ecf20bea 100644
--- a/mlbstatsapi/models/standings/attributes.py
+++ b/mlbstatsapi/models/standings/attributes.py
@@ -1,144 +1,104 @@
-from typing import Union, Optional
-from dataclasses import dataclass
+from typing import Optional
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
+from mlbstatsapi.models.teams import Team
+from mlbstatsapi.models.teams.attributes import TeamRecord
-from mlbstatsapi.models.teams import Team, TeamRecord
-@dataclass
-class Streak:
+class Streak(MLBBaseModel):
"""
-
+ A class to represent a streak.
- Attributes:
- ___________
- streaktype : str
- Steak type
- streaknumber : int
- Streak number
- streakcode : str
- Steak code
+ Attributes
+ ----------
+ streak_type : str
+ Streak type.
+ streak_number : int
+ Streak number.
+ streak_code : str
+ Streak code.
"""
- streaktype: str
- streaknumber: int
- streakcode: str
+ streak_type: str = Field(alias="streaktype")
+ streak_number: int = Field(alias="streaknumber")
+ streak_code: str = Field(alias="streakcode")
-@dataclass(repr=False)
-class Teamrecords(TeamRecord):
+
+class TeamRecords(TeamRecord):
"""
- Team Records
+ A class to represent team standings records.
- Attributes:
- ___________
- team: Team
- The team for which the data belongs to. Can be an instance of the Team class or a dictionary with relevant information about the team.
- season: int
+ Attributes
+ ----------
+ team : Team
+ The team for which the data belongs to.
+ season : int
The season for which the data belongs to.
- streak: Streak
- The streak of the team. Can be an instance of the Streak class or a dictionary with relevant information about the streak.
- divisionrank: str
+ streak : Streak
+ The streak of the team.
+ division_rank : str
The rank of the team in their division.
- leaguerank: str
+ league_rank : str
The rank of the team in their league.
- sportrank: str
+ sport_rank : str
The rank of the team in their sport.
- gamesplayed: int
- The number of games played by the team.
- gamesback: str
- The number of games behind the leader in the division.
- wildcardgamesback: str
- The number of games behind the leader in the wild card race.
- leaguegamesback: str
- The number of games behind the leader in the league.
- springleaguegamesback: str
- The number of games behind the leader in the spring league.
- sportgamesback: str
- The number of games behind the leader in the sport.
- divisiongamesback: str
+ games_back : str
The number of games behind the leader in the division.
- conferencegamesback: str
- The number of games behind the leader in the conference.
- leaguerecord: OverallleagueRecord
- The overall league record of the team. Can be an instance of the OverallleagueRecord class or a dictionary with relevant information about the record.
- lastupdated: str
+ last_updated : str
The date when the data was last updated.
- records: Records
- The records of the team. Can be an instance of the Records class or a dictionary with relevant information about the records.
- runsallowed: int
+ runs_allowed : int
The number of runs allowed by the team.
- runsscored: int
+ runs_scored : int
The number of runs scored by the team.
- divisionchamp: bool
- A flag indicating whether the team is the division champion.
- divisionleader: bool
- A flag indicating whether the team is the leader in their division.
- haswildcard: bool
- A flag indicating whether the team has a wild card spot.
- clinched: bool
- A flag indicating whether the team has clinched a spot in the playoffs.
- eliminationnumber: str
- The number of games the team needs to win or the number of games their opponents need to lose in order to be eliminated from playoff contention.
- wildcardeliminationnumber: str
- The number of games the team needs to win or the number of games their opponents need to lose in order to be eliminated from wild card contention.
- wins: int
- The number of wins of the team.
- losses: int
- The number of losses of the team.
- rundifferential: int
- The run differential of the team (runs scored minus runs allowed).
- winningpercentage: str
- The winning percentage of the team.
- wildcardrank: str
+ division_champ : bool
+ Whether the team is the division champion.
+ has_wildcard : bool
+ Whether the team has a wild card spot.
+ clinched : bool
+ Whether the team has clinched a spot in the playoffs.
+ elimination_number : str
+ The elimination number for playoffs.
+ elimination_number_sport : str
+ The elimination number for sport.
+ elimination_number_league : str
+ The elimination number for league.
+ elimination_number_division : str
+ The elimination number for division.
+ elimination_number_conference : str
+ The elimination number for conference.
+ wildcard_elimination_number : str
+ The wildcard elimination number.
+ run_differential : int
+ The run differential of the team.
+ wildcard_rank : str
The rank of the team in the wild card race.
- wildcardleader: bool
- A flag indicating whether the team is the leader in the wild card race.
- magicnumber: str
- The number of games the team needs to win or the number of games their opponents need to lose in order to clinch a spot in the playoffs.
- clinchindicator: Optional
-
+ wildcard_leader : bool
+ Whether the team is the leader in the wild card race.
+ magic_number : str
+ The magic number for clinching.
+ clinch_indicator : str
+ Clinch indicator.
"""
- team: Union[Team, dict]
+ team: Team
season: int
- streak: Union[Streak, dict]
- divisionrank: str
- leaguerank: str
- sportrank: str
- # gamesplayed: int
- gamesback: str
- # wildcardgamesback: str
- # leaguegamesback: str
- # springleaguegamesback: str
- # sportgamesback: str
- # divisiongamesback: str
- # conferencegamesback: str
- # leaguerecord: Union[OverallleagueRecord, dict]
- lastupdated: str
- # records: Union[Records, dict]
- runsallowed: int
- runsscored: int
- divisionchamp: bool
- # divisionleader: bool
- haswildcard: bool
+ streak: Streak
+ division_rank: str = Field(alias="divisionrank")
+ league_rank: str = Field(alias="leaguerank")
+ sport_rank: str = Field(alias="sportrank")
+ games_back: str = Field(alias="gamesback")
+ last_updated: str = Field(alias="lastupdated")
+ runs_allowed: int = Field(alias="runsallowed")
+ runs_scored: int = Field(alias="runsscored")
+ division_champ: bool = Field(alias="divisionchamp")
+ has_wildcard: bool = Field(alias="haswildcard")
clinched: bool
- eliminationnumber: str
- eliminationnumbersport: str
- eliminationnumberleague: str
- eliminationnumberdivision: str
- eliminationnumberconference: str
- wildcardeliminationnumber: str
- # wins: int
- # losses: int
- rundifferential: int
- # winningpercentage: str
- wildcardrank: Optional[str] = None
- wildcardleader: Optional[bool] = None
- magicnumber: Optional[str] = None
- clinchindicator: Optional[str] = None
-
- def __post_init__(self):
- self.team = Team(**self.team)
- self.streak = Streak(**self.streak)
- # self.leaguerecord = OverallleagueRecord(**self.leaguerecord)
- # self.records = Records(**self.records)
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ elimination_number: str = Field(alias="eliminationnumber")
+ elimination_number_sport: str = Field(alias="eliminationnumbersport")
+ elimination_number_league: str = Field(alias="eliminationnumberleague")
+ elimination_number_division: str = Field(alias="eliminationnumberdivision")
+ elimination_number_conference: str = Field(alias="eliminationnumberconference")
+ wildcard_elimination_number: str = Field(alias="wildcardeliminationnumber")
+ run_differential: int = Field(alias="rundifferential")
+ wildcard_rank: Optional[str] = Field(default=None, alias="wildcardrank")
+ wildcard_leader: Optional[bool] = Field(default=None, alias="wildcardleader")
+ magic_number: Optional[str] = Field(default=None, alias="magicnumber")
+ clinch_indicator: Optional[str] = Field(default=None, alias="clinchindicator")
diff --git a/mlbstatsapi/models/standings/standings.py b/mlbstatsapi/models/standings/standings.py
index 1680b71e..d64c54c5 100644
--- a/mlbstatsapi/models/standings/standings.py
+++ b/mlbstatsapi/models/standings/standings.py
@@ -1,48 +1,37 @@
-from typing import Union, Optional, List
-from dataclasses import dataclass
-
+from typing import Optional, List
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.leagues import League
from mlbstatsapi.models.divisions import Division
from mlbstatsapi.models.sports import Sport
-
-from .attributes import Teamrecords
+from .attributes import TeamRecords
-@dataclass(repr=False)
-class Standings:
+class Standings(MLBBaseModel):
"""
- A class representing a standings in a league.
-
+ A class representing standings in a league.
Attributes
----------
- standingstype : str
+ standings_type : str
A string indicating the type of standings.
- league : league
+ league : League
An object containing information about the league.
division : Division
- An object containing information about the division
+ An object containing information about the division.
sport : Sport
An object containing information about the sport.
- lastupdated : str
+ last_updated : str
A string indicating the last time the standing was updated.
- teamrecords : List[Teamrecords]
- A list of Teamrecord objects containing the data for the teams standings.
+ team_records : List[TeamRecords]
+ A list of TeamRecords objects containing the data for the teams standings.
+ roundrobin : dict
+ Roundrobin data (if applicable).
"""
- standingstype: str
- league: Union[League, dict]
- division: Union[Sport, dict]
- lastupdated: str
- teamrecords: List[Union[Teamrecords, dict]]
- sport: Optional[Union[Sport, dict]] = None
+ standings_type: str = Field(alias="standingstype")
+ league: League
+ division: Division
+ last_updated: str = Field(alias="lastupdated")
+ team_records: List[TeamRecords] = Field(alias="teamrecords")
+ sport: Optional[Sport] = None
roundrobin: Optional[dict] = None
-
- def __post_init__(self):
- self.league = League(**self.league)
- self.division = Division(**self.division)
- self.sport = Sport(**self.sport) if self.sport else None
- self.teamrecords = [Teamrecords(**teamrecord) for teamrecord in self.teamrecords]
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
diff --git a/mlbstatsapi/models/stats/catching.py b/mlbstatsapi/models/stats/catching.py
index 4d2edfbb..c34a1f59 100644
--- a/mlbstatsapi/models/stats/catching.py
+++ b/mlbstatsapi/models/stats/catching.py
@@ -1,37 +1,38 @@
-from dataclasses import dataclass
-from typing import Optional, Union
-
+from typing import Optional, List, ClassVar
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.teams import Team
from mlbstatsapi.models.game import Game
-
from .stats import Split
-@dataclass(repr=False)
-class SimpleCatchingSplit:
+class SimpleCatchingSplit(MLBBaseModel):
"""
- A class to represent a simple catching split
- Age: int
- age at beginning of season
- gamesplayed : int
- The number of games played by the catcher
+ A class to represent a simple catching split.
+
+ Attributes
+ ----------
+ age : int
+ Age at beginning of season.
+ games_played : int
+ The number of games played by the catcher.
runs : int
The number of runs given up while catching.
- homeruns : int
+ home_runs : int
The number of home runs given up while catching.
strikeouts : int
The number of strike outs while catching.
- baseonballs : int
+ base_on_balls : int
The number of base on balls while catching.
- intentionalwalks : int
+ intentional_walks : int
The number of intentional walks while catching.
hits : int
The number of hits while catching.
- hitbypitch : int
+ hit_by_pitch : int
The number of batters hit by a pitch while catching.
avg : str
The batting average while catching.
- atbats : int
+ at_bats : int
The number of at bats while catching.
obp : str
The on base percentage while catching.
@@ -39,274 +40,259 @@ class SimpleCatchingSplit:
The slugging percentage while catching.
ops : str
The on-base slugging while catching.
- see also: https://www.mlb.com/glossary/standard-stats/on-base-plus-slugging
- caughtstealing : int
+ caught_stealing : int
The number of runners caught stealing by the catcher.
- caughtstealingpercentage: str
- percentage of runners caught stealing by the catcher.
- stolenbases : int
+ caught_stealing_percentage : str
+ Percentage of runners caught stealing by the catcher.
+ stolen_bases : int
The number of stolen bases while catching.
- stolenbasepercentage : str
- The stolen base percentage against the catcher.
- earnedruns : int
+ stolen_base_percentage : str
+ The stolen base percentage against the catcher.
+ earned_runs : int
The earned run amount against the catcher.
- battersfaced : int
+ batters_faced : int
The number of batters faced while catching.
- gamespitched : int
+ games_pitched : int
The number of games pitched while catching.
- hitbatsmen : int
+ hit_batsmen : int
The number of batters hit by pitches while catching.
- wildpitches : int
+ wild_pitches : int
The number of wild pitches while catching.
pickoffs : int
The number of pick offs while catching.
- totalbases : int
- The total number of bases
- strikeoutwalkratio : str
+ total_bases : int
+ The total number of bases.
+ strikeout_walk_ratio : str
The strike out to walk ratio while catching.
- catchersinterference : int
- The number of times catcher interference commited
- sacbunts : int
+ catchers_interference : int
+ The number of times catcher interference committed.
+ sac_bunts : int
The number of sac bunts performed while catching.
- sacflies : int
+ sac_flies : int
The number of sac flies while catching.
- passedball : int
+ passed_ball : int
The number of passed balls while catching.
+ pickoff_attempts : int
+ The number of pickoff attempts.
"""
age: Optional[int] = None
- gamesplayed: Optional[int] = None
+ games_played: Optional[int] = Field(default=None, alias="gamesplayed")
runs: Optional[int] = None
- homeruns: Optional[int] = None
+ home_runs: Optional[int] = Field(default=None, alias="homeruns")
strikeouts: Optional[int] = None
- baseonballs: Optional[int] = None
- intentionalwalks: Optional[int] = None
+ base_on_balls: Optional[int] = Field(default=None, alias="baseonballs")
+ intentional_walks: Optional[int] = Field(default=None, alias="intentionalwalks")
hits: Optional[int] = None
- hitbypitch: Optional[int] = None
+ hit_by_pitch: Optional[int] = Field(default=None, alias="hitbypitch")
avg: Optional[str] = None
- atbats: Optional[int] = None
+ at_bats: Optional[int] = Field(default=None, alias="atbats")
obp: Optional[str] = None
slg: Optional[str] = None
ops: Optional[str] = None
- caughtstealing: Optional[int] = None
- caughtstealingpercentage: Optional[str]=None
- stolenbases: Optional[int] = None
- stolenbasepercentage: Optional[str] = None
- earnedruns: Optional[int] = None
- battersfaced: Optional[int] = None
- gamespitched: Optional[int] = None
- hitbatsmen: Optional[int] = None
- wildpitches: Optional[int] = None
+ caught_stealing: Optional[int] = Field(default=None, alias="caughtstealing")
+ caught_stealing_percentage: Optional[str] = Field(default=None, alias="caughtstealingpercentage")
+ stolen_bases: Optional[int] = Field(default=None, alias="stolenbases")
+ stolen_base_percentage: Optional[str] = Field(default=None, alias="stolenbasepercentage")
+ earned_runs: Optional[int] = Field(default=None, alias="earnedruns")
+ batters_faced: Optional[int] = Field(default=None, alias="battersfaced")
+ games_pitched: Optional[int] = Field(default=None, alias="gamespitched")
+ hit_batsmen: Optional[int] = Field(default=None, alias="hitbatsmen")
+ wild_pitches: Optional[int] = Field(default=None, alias="wildpitches")
pickoffs: Optional[int] = None
- totalbases: Optional[int] = None
- strikeoutwalkratio: Optional[str] = None
- catchersinterference: Optional[int] = None
- sacbunts: Optional[int] = None
- sacflies: Optional[int] = None
- passedball: Optional[int] = None
- pickoffattempts: Optional[int] = None
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-
-@dataclass(kw_only=True, repr=False)
+ total_bases: Optional[int] = Field(default=None, alias="totalbases")
+ strikeout_walk_ratio: Optional[str] = Field(default=None, alias="strikeoutwalkratio")
+ catchers_interference: Optional[int] = Field(default=None, alias="catchersinterference")
+ sac_bunts: Optional[int] = Field(default=None, alias="sacbunts")
+ sac_flies: Optional[int] = Field(default=None, alias="sacflies")
+ passed_ball: Optional[int] = Field(default=None, alias="passedball")
+ pickoff_attempts: Optional[int] = Field(default=None, alias="pickoffattempts")
+
+
class CatchingSeason(Split):
"""
- A class to represent a catching season statistic
+ A class to represent a catching season statistic.
Attributes
----------
+ stat : SimpleCatchingSplit
+ The catching split stat.
"""
- _stat = ['season']
- stat: Union[SimpleCatchingSplit, dict]
+ _stat: ClassVar[List[str]] = ['season']
+ stat: SimpleCatchingSplit
- def __post_init__(self):
- self.stat = SimpleCatchingSplit(**self.stat)
- super().__post_init__()
-
-@dataclass(kw_only=True, repr=False)
class CatchingSingleSeason(Split):
"""
- A class to represent a catching statsSingleSeason statistic
+ A class to represent a catching statsSingleSeason statistic.
Attributes
----------
+ stat : SimpleCatchingSplit
+ The catching split stat.
"""
- _stat = ['statsSingleSeason']
- stat: Union[SimpleCatchingSplit, dict]
+ _stat: ClassVar[List[str]] = ['statsSingleSeason']
+ stat: SimpleCatchingSplit
- def __post_init__(self):
- self.stat = SimpleCatchingSplit(**self.stat)
- super().__post_init__()
-@dataclass(kw_only=True, repr=False)
class CatchingYearByYearPlayoffs(Split):
"""
- A class to represent a catching yearByYearPlayoffs statistic
+ A class to represent a catching yearByYearPlayoffs statistic.
Attributes
----------
+ stat : SimpleCatchingSplit
+ The catching split stat.
"""
- _stat = ['yearByYearPlayoffs']
- stat: Union[SimpleCatchingSplit, dict]
+ _stat: ClassVar[List[str]] = ['yearByYearPlayoffs']
+ stat: SimpleCatchingSplit
- def __post_init__(self):
- self.stat = SimpleCatchingSplit(**self.stat)
- super().__post_init__()
-@dataclass(kw_only=True, repr=False)
class CatchingYearByYear(Split):
"""
- A class to represent a catching yearByYear statistic
+ A class to represent a catching yearByYear statistic.
Attributes
----------
+ stat : SimpleCatchingSplit
+ The catching split stat.
"""
- _stat = ['yearByYear']
- stat: Union[SimpleCatchingSplit, dict]
+ _stat: ClassVar[List[str]] = ['yearByYear']
+ stat: SimpleCatchingSplit
- def __post_init__(self):
- self.stat = SimpleCatchingSplit(**self.stat)
- super().__post_init__()
-@dataclass(kw_only=True, repr=False)
class CatchingProjected(Split):
"""
- A class to represent a catching projectedRos statistic
+ A class to represent a catching projectedRos statistic.
Attributes
----------
+ stat : SimpleCatchingSplit
+ The catching split stat.
"""
- _stat = ['projectedRos']
- stat: Union[SimpleCatchingSplit, dict]
+ _stat: ClassVar[List[str]] = ['projectedRos']
+ stat: SimpleCatchingSplit
- def __post_init__(self):
- self.stat = SimpleCatchingSplit(**self.stat)
- super().__post_init__()
-@dataclass(kw_only=True, repr=False)
class CatchingCareer(Split):
"""
- A class to represent a catching career statistic
+ A class to represent a catching career statistic.
Attributes
----------
+ stat : SimpleCatchingSplit
+ The catching split stat.
"""
- _stat = ['career']
- stat: Union[SimpleCatchingSplit, dict]
+ _stat: ClassVar[List[str]] = ['career']
+ stat: SimpleCatchingSplit
- def __post_init__(self):
- self.stat = SimpleCatchingSplit(**self.stat)
- super().__post_init__()
-@dataclass(kw_only=True, repr=False)
class CatchingCareerRegularSeason(Split):
"""
- A class to represent a catching careerRegularSeason statistic
+ A class to represent a catching careerRegularSeason statistic.
Attributes
----------
+ stat : SimpleCatchingSplit
+ The catching split stat.
"""
- _stat = ['careerRegularSeason']
- stat: Union[SimpleCatchingSplit, dict]
+ _stat: ClassVar[List[str]] = ['careerRegularSeason']
+ stat: SimpleCatchingSplit
- def __post_init__(self):
- self.stat = SimpleCatchingSplit(**self.stat)
- super().__post_init__()
-@dataclass(kw_only=True, repr=False)
class CatchingGameLog(Split):
"""
- A class to represent a catching gameLog statistic
+ A class to represent a catching gameLog statistic.
Attributes
----------
+ is_home : bool
+ Is home bool.
+ is_win : bool
+ Is win bool.
+ date : str
+ The date.
+ game : Game
+ The game.
+ opponent : Team
+ The opponent.
"""
- _stat = ['gameLog']
- ishome: bool
- iswin: bool
+ _stat: ClassVar[List[str]] = ['gameLog']
+ is_home: bool = Field(alias="ishome")
+ is_win: bool = Field(alias="iswin")
date: str
- game: Union[Game, dict]
- opponent: Union[Team, dict]
+ game: Game
+ opponent: Team
- def __post_init__(self):
- super().__post_init__()
-@dataclass(kw_only=True, repr=False)
class CatchingLastXGames(Split):
"""
- A class to represent a catching lastXGames statistic
+ A class to represent a catching lastXGames statistic.
Attributes
----------
+ stat : SimpleCatchingSplit
+ The catching split stat.
"""
- _stat = ['lastXGames']
- stat: Union[SimpleCatchingSplit, dict]
+ _stat: ClassVar[List[str]] = ['lastXGames']
+ stat: SimpleCatchingSplit
- def __post_init__(self):
- self.stat = SimpleCatchingSplit(**self.stat)
- super().__post_init__()
-@dataclass(kw_only=True, repr=False)
class CatchingByDateRange(Split):
"""
- A class to represent a catching byDateRange statistic
+ A class to represent a catching byDateRange statistic.
Attributes
----------
+ stat : SimpleCatchingSplit
+ The catching split stat.
"""
- _stat = ['byDateRange']
- stat: Union[SimpleCatchingSplit, dict]
+ _stat: ClassVar[List[str]] = ['byDateRange']
+ stat: SimpleCatchingSplit
- def __post_init__(self):
- self.stat = SimpleCatchingSplit(**self.stat)
- super().__post_init__()
-@dataclass(kw_only=True, repr=False)
class CatchingByDayOfWeek(Split):
"""
- A class to represent a catching byDayOfWeek statistic
+ A class to represent a catching byDayOfWeek statistic.
Attributes
----------
+ day_of_week : int
+ The day of the week.
+ stat : SimpleCatchingSplit
+ The catching split stat.
"""
- _stat = ['byDayOfWeek']
- dayofweek: int
- stat: Union[SimpleCatchingSplit, dict]
+ _stat: ClassVar[List[str]] = ['byDayOfWeek']
+ day_of_week: int = Field(alias="dayofweek")
+ stat: SimpleCatchingSplit
- def __post_init__(self):
- self.stat = SimpleCatchingSplit(**self.stat)
- super().__post_init__()
-@dataclass(kw_only=True, repr=False)
class CatchingHomeAndAway(Split):
"""
- A class to represent a catching homeAndAway statistic
+ A class to represent a catching homeAndAway statistic.
Attributes
----------
+ is_home : bool
+ Is home bool.
+ stat : SimpleCatchingSplit
+ The catching split stat.
"""
- _stat = ['homeAndAway']
- ishome: bool
- stat: Union[SimpleCatchingSplit, dict]
+ _stat: ClassVar[List[str]] = ['homeAndAway']
+ is_home: bool = Field(alias="ishome")
+ stat: SimpleCatchingSplit
- def __post_init__(self):
- self.stat = SimpleCatchingSplit(**self.stat)
- super().__post_init__()
-@dataclass(kw_only=True, repr=False)
class CatchingWinLoss(Split):
"""
- A class to represent a catching winLoss statistic
+ A class to represent a catching winLoss statistic.
Attributes
----------
+ is_win : bool
+ Is win bool.
+ stat : SimpleCatchingSplit
+ The catching split stat.
"""
- _stat = ['winLoss']
- iswin: bool
- stat: Union[SimpleCatchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleCatchingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['winLoss']
+ is_win: bool = Field(alias="iswin")
+ stat: SimpleCatchingSplit
diff --git a/mlbstatsapi/models/stats/fielding.py b/mlbstatsapi/models/stats/fielding.py
index 8a8ac1c8..6b392e7e 100644
--- a/mlbstatsapi/models/stats/fielding.py
+++ b/mlbstatsapi/models/stats/fielding.py
@@ -1,460 +1,492 @@
-from dataclasses import dataclass, field
-from typing import Optional, Union
-
+from typing import Optional, Any, List, ClassVar
+from pydantic import Field, field_validator
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.people import Position
from mlbstatsapi.models.teams import Team
from mlbstatsapi.models.game import Game
+from .stats import Split
+
+
+class SimpleFieldingSplit(MLBBaseModel):
+ """
+ A class to represent a simple fielding split.
-from .stats import Stat, Split
-
-
-@dataclass(repr=False)
-class SimpleFieldingSplit:
- """
- A class to represent a simple fielding split
- age: int
- player age at the start of the season
- gamesplayed: int
- The number of games played
- gamesstarted: int
- The number of games started
- caughtstealing: int
- The number of runners caught stealing
- caughtstealingpercentage: str
- The percentage of runners caught stealing
- stolenbases: int
- The number of stolen bases
- stolenbasepercentage: str
- The stolen base percentage
- assists: int
- The number of assists
- putouts: int
- The number of put outs
- errors: int
- The number of errors commited
- chances: int
- The number of chances
- fielding: str
- The number of fielding
- rangefactorpergame: str
+ Attributes
+ ----------
+ age : int
+ Player age at the start of the season.
+ games_played : int
+ The number of games played.
+ games_started : int
+ The number of games started.
+ caught_stealing : int
+ The number of runners caught stealing.
+ caught_stealing_percentage : str
+ The percentage of runners caught stealing.
+ stolen_bases : int
+ The number of stolen bases.
+ stolen_base_percentage : str
+ The stolen base percentage.
+ assists : int
+ The number of assists.
+ putouts : int
+ The number of put outs.
+ errors : int
+ The number of errors committed.
+ chances : int
+ The number of chances.
+ fielding : str
+ The fielding percentage.
+ range_factor_per_game : str
Range rating per game.
- see also: https://www.mlb.com/glossary/advanced-stats/range-factor
- rangefactorper9inn: str
+ range_factor_per_9_inn : str
Range factor per 9 innings.
- see also: https://www.mlb.com/glossary/advanced-stats/range-factor
- innings: str
+ innings : str
The number of innings played.
- games: int
+ games : int
The number of games played.
- passedball: int
+ passed_ball : int
The number of passed balls.
- doubleplays: int
+ double_plays : int
The number of double plays.
- tripleplays: int
+ triple_plays : int
The number of triple plays.
- catcherera: str
+ catcher_era : str
The catcher ERA of the fielding stat.
- catchersinterference: int
- The number of times catchers interfence was commited.
- wildpitches: int
+ catchers_interference : int
+ The number of times catchers interference was committed.
+ wild_pitches : int
The number of wild pitches.
- throwingerrors: int
+ throwing_errors : int
The number of throwing errors.
- pickoffs: int
+ pickoffs : int
The number of pick offs.
"""
- age:Optional[int]=None
- position: Optional[Union[Position, dict]] = field(default_factory=dict)
- gamesplayed: Optional[int] = None
- gamesstarted: Optional[int] = None
- caughtstealing: Optional[int] = None
- caughtstealingpercentage: Optional[str] = None
- stolenbases: Optional[int] = None
- stolenbasepercentage: Optional[str] = None
+ age: Optional[int] = None
+ position: Optional[Position] = None
+ games_played: Optional[int] = Field(default=None, alias="gamesplayed")
+ games_started: Optional[int] = Field(default=None, alias="gamesstarted")
+ caught_stealing: Optional[int] = Field(default=None, alias="caughtstealing")
+ caught_stealing_percentage: Optional[str] = Field(default=None, alias="caughtstealingpercentage")
+ stolen_bases: Optional[int] = Field(default=None, alias="stolenbases")
+ stolen_base_percentage: Optional[str] = Field(default=None, alias="stolenbasepercentage")
assists: Optional[int] = None
putouts: Optional[int] = None
errors: Optional[int] = None
chances: Optional[int] = None
fielding: Optional[str] = None
- rangefactorpergame: Optional[str] = None
- rangefactorper9inn: Optional[str] = None
+ range_factor_per_game: Optional[str] = Field(default=None, alias="rangefactorpergame")
+ range_factor_per_9_inn: Optional[str] = Field(default=None, alias="rangefactorper9inn")
innings: Optional[str] = None
games: Optional[int] = None
- passedball: Optional[int] = None
- doubleplays: Optional[int] = None
- tripleplays: Optional[int] = None
- catcherera: Optional[str] = None
- catchersinterference: Optional[int] = None
- wildpitches: Optional[int] = None
- throwingerrors: Optional[int] = None
+ passed_ball: Optional[int] = Field(default=None, alias="passedball")
+ double_plays: Optional[int] = Field(default=None, alias="doubleplays")
+ triple_plays: Optional[int] = Field(default=None, alias="tripleplays")
+ catcher_era: Optional[str] = Field(default=None, alias="catcherera")
+ catchers_interference: Optional[int] = Field(default=None, alias="catchersinterference")
+ wild_pitches: Optional[int] = Field(default=None, alias="wildpitches")
+ throwing_errors: Optional[int] = Field(default=None, alias="throwingerrors")
pickoffs: Optional[int] = None
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
+ @field_validator('position', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
+
-@dataclass(kw_only=True, repr=False)
class FieldingSeasonAdvanced(Split):
"""
- A class to represent a fielding season Advanced statistic
+ A class to represent a fielding seasonAdvanced statistic.
+
Attributes
----------
position : Position
- The position of the player
+ The position of the player.
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['seasonAdvanced']
- position: Optional[Union[Position, dict]] = field(default_factory=dict)
- stat: Union[SimpleFieldingSplit, dict]
+ _stat: ClassVar[List[str]] = ['seasonAdvanced']
+ stat: SimpleFieldingSplit
+ position: Optional[Position] = None
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
+ @field_validator('position', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
-@dataclass(kw_only=True, repr=False)
class FieldingCareerAdvanced(Split):
"""
- A class to represent a fielding career Advanced statistic
+ A class to represent a fielding careerAdvanced statistic.
+
Attributes
----------
position : Position
- The position of the player
+ The position of the player.
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['careerAdvanced']
- position: Optional[Union[Position, dict]] = field(default_factory=dict)
- stat: Union[SimpleFieldingSplit, dict]
+ _stat: ClassVar[List[str]] = ['careerAdvanced']
+ stat: SimpleFieldingSplit
+ position: Optional[Position] = None
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
+ @field_validator('position', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
-@dataclass(kw_only=True, repr=False)
class FieldingSingleSeasonAdvanced(Split):
"""
- A class to represent a fielding season statistic
+ A class to represent a fielding statsSingleSeasonAdvanced statistic.
Attributes
----------
position : Position
- The position of the player
+ The position of the player.
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['statsSingleSeasonAdvanced']
- position: Optional[Union[Position, dict]] = field(default_factory=dict)
- stat: Union[SimpleFieldingSplit, dict]
+ _stat: ClassVar[List[str]] = ['statsSingleSeasonAdvanced']
+ stat: SimpleFieldingSplit
+ position: Optional[Position] = None
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
+ @field_validator('position', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
-@dataclass(kw_only=True, repr=False)
class FieldingSeason(Split):
"""
- A class to represent a fielding season statistic
+ A class to represent a fielding season statistic.
Attributes
----------
position : Position
- The position of the player
+ The position of the player.
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['season']
- position: Optional[Union[Position, dict]] = field(default_factory=dict)
- stat: Union[SimpleFieldingSplit, dict]
+ _stat: ClassVar[List[str]] = ['season']
+ stat: SimpleFieldingSplit
+ position: Optional[Position] = None
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
+ @field_validator('position', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
-@dataclass(kw_only=True, repr=False)
class FieldingSingleSeason(Split):
"""
- A class to represent a fielding statsSingleSeason statistic
+ A class to represent a fielding statsSingleSeason statistic.
Attributes
----------
position : Position
- The position of the player
+ The position of the player.
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['statsSingleSeason']
- position: Optional[Union[Position, dict]] = field(default_factory=dict)
- stat: Union[SimpleFieldingSplit, dict]
+ _stat: ClassVar[List[str]] = ['statsSingleSeason']
+ stat: SimpleFieldingSplit
+ position: Optional[Position] = None
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
+ @field_validator('position', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
-@dataclass(kw_only=True, repr=False)
class FieldingCareer(Split):
"""
- A class to represent a fielding career statistic
+ A class to represent a fielding career statistic.
Attributes
----------
position : Position
- The position of the player
+ The position of the player.
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['career', 'careerRegularSeason']
- position: Optional[Union[Position, dict]] = field(default_factory=dict)
- stat: Union[SimpleFieldingSplit, dict]
+ _stat: ClassVar[List[str]] = ['career', 'careerRegularSeason']
+ stat: SimpleFieldingSplit
+ position: Optional[Position] = None
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
+ @field_validator('position', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
-@dataclass(kw_only=True, repr=False)
class FieldingCareerPlayoffs(Split):
"""
- A class to represent a fielding careerPlayoffs statistic
+ A class to represent a fielding careerPlayoffs statistic.
Attributes
----------
position : Position
- The position of the player
+ The position of the player.
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['careerPlayoffs']
- position: Optional[Union[Position, dict]] = field(default_factory=dict)
- stat: Union[SimpleFieldingSplit, dict]
+ _stat: ClassVar[List[str]] = ['careerPlayoffs']
+ stat: SimpleFieldingSplit
+ position: Optional[Position] = None
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
+ @field_validator('position', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
-@dataclass(kw_only=True, repr=False)
class FieldingHomeAndAway(Split):
"""
- A class to represent a fielding homeAndAway statistic
+ A class to represent a fielding homeAndAway statistic.
Attributes
----------
- ishome : bool
- A bool value for is the game at home
+ is_home : bool
+ A bool value for is the game at home.
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['homeAndAway']
- ishome: bool
- stat: Union[SimpleFieldingSplit, dict]
+ _stat: ClassVar[List[str]] = ['homeAndAway']
+ is_home: bool = Field(alias="ishome")
+ stat: SimpleFieldingSplit
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
-
-@dataclass(kw_only=True, repr=False)
class FieldingHomeAndAwayPlayoffs(Split):
"""
- A class to represent a fielding homeAndAwayPlayoffs statistic
+ A class to represent a fielding homeAndAwayPlayoffs statistic.
Attributes
----------
- ishome : bool
- A bool value for is the game at home
+ is_home : bool
+ A bool value for is the game at home.
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['homeAndAwayPlayoffs']
- ishome: bool
- stat: Union[SimpleFieldingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['homeAndAwayPlayoffs']
+ is_home: bool = Field(alias="ishome")
+ stat: SimpleFieldingSplit
-@dataclass(kw_only=True, repr=False)
class FieldingYearByYear(Split):
"""
- A class to represent a fielding yearByYear statistic
+ A class to represent a fielding yearByYear statistic.
Attributes
----------
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['yearByYear']
- stat: Union[SimpleFieldingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['yearByYear']
+ stat: SimpleFieldingSplit
-@dataclass(kw_only=True, repr=False)
class FieldingYearByYearAdvanced(Split):
"""
- A class to represent a fielding yearByYearAdvanced statistic
+ A class to represent a fielding yearByYearAdvanced statistic.
Attributes
----------
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['yearByYearAdvanced']
- stat: Union[SimpleFieldingSplit, dict]
+ _stat: ClassVar[List[str]] = ['yearByYearAdvanced']
+ stat: SimpleFieldingSplit
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
-
-@dataclass(kw_only=True, repr=False)
class FieldingYearByYearPlayoffs(Split):
"""
- A class to represent a fielding yearByYearPlayoffs statistic
+ A class to represent a fielding yearByYearPlayoffs statistic.
Attributes
----------
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['yearByYearPlayoffs']
- stat: Union[SimpleFieldingSplit, dict]
+ _stat: ClassVar[List[str]] = ['yearByYearPlayoffs']
+ stat: SimpleFieldingSplit
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
-@dataclass(kw_only=True, repr=False)
class FieldingWinLoss(Split):
"""
- A class to represent a fielding winLoss statistic
+ A class to represent a fielding winLoss statistic.
Attributes
----------
- iswin : bool
- is the game a win
+ is_win : bool
+ Is the game a win.
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['winLoss']
- iswin: bool
- stat: Union[SimpleFieldingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['winLoss']
+ is_win: bool = Field(alias="iswin")
+ stat: SimpleFieldingSplit
-@dataclass(kw_only=True, repr=False)
class FieldingWinLossPlayoffs(Split):
"""
- A class to represent a fielding winLossPlayoffs statistic
+ A class to represent a fielding winLossPlayoffs statistic.
Attributes
----------
- iswin : bool
- is the game a win
+ is_win : bool
+ Is the game a win.
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['winLossPlayoffs']
- iswin: bool
- stat: Union[SimpleFieldingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['winLossPlayoffs']
+ is_win: bool = Field(alias="iswin")
+ stat: SimpleFieldingSplit
-@dataclass(kw_only=True, repr=False)
class FieldingByDayOfWeek(Split):
"""
- A class to represent a fielding byDayOfWeek statistic
+ A class to represent a fielding byDayOfWeek statistic.
Attributes
----------
+ day_of_week : str
+ The day of the week.
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['byDayOfWeek']
- dayofweek: str
- stat: Union[SimpleFieldingSplit, dict]
+ _stat: ClassVar[List[str]] = ['byDayOfWeek']
+ day_of_week: str = Field(alias="dayofweek")
+ stat: SimpleFieldingSplit
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
-
-@dataclass(kw_only=True, repr=False)
class FieldingByDateRangeAdvanced(Split):
"""
- A class to represent a fielding byDateRangeAdvanced stat
+ A class to represent a fielding byDateRangeAdvanced stat.
Attributes
----------
+ position : Position
+ The position.
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['byDateRangeAdvanced']
- position: Union[Position, dict] = field(default_factory=dict)
-
- def __post_init__(self):
- self.position = Position(**self.position) if self.position else self.position
- stat: Union[SimpleFieldingSplit, dict]
+ _stat: ClassVar[List[str]] = ['byDateRangeAdvanced']
+ stat: SimpleFieldingSplit
+ position: Optional[Position] = None
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
+ @field_validator('position', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
-@dataclass(kw_only=True, repr=False)
class FieldingByMonth(Split):
"""
- A class to represent a fielding byMonth stat
+ A class to represent a fielding byMonth stat.
Attributes
----------
month : int
- the month of the stat
+ The month of the stat.
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['byMonth']
+ _stat: ClassVar[List[str]] = ['byMonth']
month: int
- stat: Union[SimpleFieldingSplit, dict]
+ stat: SimpleFieldingSplit
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
-
-@dataclass(kw_only=True, repr=False)
class FieldingByMonthPlayoffs(Split):
"""
- A class to represent a fielding byMonthPlayoffs stat
+ A class to represent a fielding byMonthPlayoffs stat.
Attributes
----------
month : int
- the month of the stat
+ The month of the stat.
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['byMonthPlayoffs']
+ _stat: ClassVar[List[str]] = ['byMonthPlayoffs']
month: int
- stat: Union[SimpleFieldingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
+ stat: SimpleFieldingSplit
-@dataclass(kw_only=True, repr=False)
class FieldingLastXGames(Split):
"""
- A class to represent a fielding lastXGames stat
+ A class to represent a fielding lastXGames stat.
Attributes
----------
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['lastXGames']
- stat: Union[SimpleFieldingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['lastXGames']
+ stat: SimpleFieldingSplit
-@dataclass(kw_only=True, repr=False)
class FieldingGameLog(Split):
"""
- A class to represent a fielding gameLog stats
+ A class to represent a fielding gameLog stats.
Attributes
----------
+ opponent : Team
+ The opponent.
+ date : str
+ The date.
+ is_home : bool
+ Is home bool.
+ is_win : bool
+ Is win bool.
+ position : Position
+ The position.
+ game : Game
+ The game.
+ stat : SimpleFieldingSplit
+ The fielding split stat.
"""
- _stat = ['gameLog']
- opponent: Union[Team, dict] = field(default_factory=dict)
+ _stat: ClassVar[List[str]] = ['gameLog']
date: str
- ishome: bool
- iswin: bool
- position: Union[Position, dict] = field(default_factory=dict)
- game: Union[Game, dict] = field(default_factory=dict)
- stat: Union[SimpleFieldingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleFieldingSplit(**self.stat)
- super().__post_init__()
-
+ is_home: bool = Field(alias="ishome")
+ is_win: bool = Field(alias="iswin")
+ stat: SimpleFieldingSplit
+ opponent: Optional[Team] = None
+ position: Optional[Position] = None
+ game: Optional[Game] = None
+
+ @field_validator('opponent', 'position', 'game', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
diff --git a/mlbstatsapi/models/stats/game.py b/mlbstatsapi/models/stats/game.py
index ca8f27d1..47268e5c 100644
--- a/mlbstatsapi/models/stats/game.py
+++ b/mlbstatsapi/models/stats/game.py
@@ -1,72 +1,86 @@
-from dataclasses import dataclass, field
-from typing import Optional, Union, List
-
+from typing import Optional, List, ClassVar
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from .stats import Split
-@dataclass
-class SimpleGameStats:
+
+class SimpleGameStats(MLBBaseModel):
"""
- A class to represent a simple game statistics
+ A class to represent simple game statistics.
Attributes
----------
- firstdateplayed : str
- first date of game played
- gamesplayed : int
- number of the games player
- gamesstarted : int
- number of the games started
- lastdateplayed : str
- last date of the game played
+ first_date_played : str
+ First date of game played.
+ games_played : int
+ Number of the games played.
+ games_started : int
+ Number of the games started.
+ last_date_played : str
+ Last date of the game played.
"""
- firstdateplayed: str
- gamesplayed: int
- gamesstarted: int
- lastdateplayed: str
+ first_date_played: str = Field(alias="firstdateplayed")
+ games_played: int = Field(alias="gamesplayed")
+ games_started: int = Field(alias="gamesstarted")
+ last_date_played: str = Field(alias="lastdateplayed")
- def __post_init__(self):
- super().__post_init__()
-@dataclass(kw_only=True)
class SeasonGame(Split):
"""
- A class to represent a game statistic
+ A class to represent a game statistic.
Used for the following stat types:
- season, career, careerRegularSeason, careerPlayoffs, statsSingleSeason
+ season, statsSingleSeason
"""
- type_ = ['season', 'statsSingleSeason']
+ _type: ClassVar[List[str]] = ['season', 'statsSingleSeason']
- def __post_init__(self):
- super().__post_init__()
-@dataclass(kw_only=True)
class CareerGame(Split):
"""
- A class to represent a game statistic
+ A class to represent a career game statistic.
"""
- type_ = ['career']
+ _type: ClassVar[List[str]] = ['career']
- def __post_init__(self):
- super().__post_init__()
-@dataclass(kw_only=True)
-class CareerRegularSeasonGame(Split, SimpleGameStats):
+class CareerRegularSeasonGame(Split):
"""
- A class to represent a game statistic
+ A class to represent a career regular season game statistic.
+
+ Attributes
+ ----------
+ first_date_played : str
+ First date of game played.
+ games_played : int
+ Number of the games played.
+ games_started : int
+ Number of the games started.
+ last_date_played : str
+ Last date of the game played.
"""
- type_ = ['careerRegularSeason']
+ _type: ClassVar[List[str]] = ['careerRegularSeason']
+ first_date_played: Optional[str] = Field(default=None, alias="firstdateplayed")
+ games_played: Optional[int] = Field(default=None, alias="gamesplayed")
+ games_started: Optional[int] = Field(default=None, alias="gamesstarted")
+ last_date_played: Optional[str] = Field(default=None, alias="lastdateplayed")
- def __post_init__(self):
- super().__post_init__()
-@dataclass(kw_only=True)
-class CareerPlayoffsGame(Split, SimpleGameStats):
+class CareerPlayoffsGame(Split):
"""
- A class to represent a game statistic
+ A class to represent a career playoffs game statistic.
+ Attributes
+ ----------
+ first_date_played : str
+ First date of game played.
+ games_played : int
+ Number of the games played.
+ games_started : int
+ Number of the games started.
+ last_date_played : str
+ Last date of the game played.
"""
- type_ = ['careerPlayoffs']
-
- def __post_init__(self):
- super().__post_init__()
\ No newline at end of file
+ _type: ClassVar[List[str]] = ['careerPlayoffs']
+ first_date_played: Optional[str] = Field(default=None, alias="firstdateplayed")
+ games_played: Optional[int] = Field(default=None, alias="gamesplayed")
+ games_started: Optional[int] = Field(default=None, alias="gamesstarted")
+ last_date_played: Optional[str] = Field(default=None, alias="lastdateplayed")
diff --git a/mlbstatsapi/models/stats/hitting.py b/mlbstatsapi/models/stats/hitting.py
index 790f5c99..a7b822a4 100644
--- a/mlbstatsapi/models/stats/hitting.py
+++ b/mlbstatsapi/models/stats/hitting.py
@@ -1,957 +1,919 @@
-from dataclasses import dataclass, field
-from typing import Optional, Union, List
-
+from typing import Optional, List, Any, ClassVar
+from pydantic import Field, field_validator
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.people import Person, Position, Batter, Pitcher
from mlbstatsapi.models.teams import Team
from mlbstatsapi.models.game import Game
-from mlbstatsapi.mlb_module import merge_keys
-from mlbstatsapi.models.data import (
- PitchData,
- HitData,
- Count,
- PlayDetails
-)
-from .stats import (
- Sabermetrics,
- ExpectedStatistics,
- Split
-)
-@dataclass(repr=False)
-class AdvancedHittingSplit:
- """
- A class to represent a advanced hitting statistics
-
- Attributes
- ----------
- age: int
- player age at the beginning of the season
- plateappearances : int
+from mlbstatsapi.models.data import PitchData, HitData, Count, PlayDetails
+from .stats import Sabermetrics, ExpectedStatistics, Split
+
+
+class AdvancedHittingSplit(MLBBaseModel):
+ """
+ A class to represent advanced hitting statistics.
+
+ Attributes
+ ----------
+ age : int
+ Player age at the beginning of the season.
+ plate_appearances : int
The number of plate appearances.
- totalbases : int
+ total_bases : int
The total number of bases.
- leftonbase : int
+ left_on_base : int
The amount of runners left on base.
- sacbunts : int
+ sac_bunts : int
The amount of sac bunts.
- sacflies : int
+ sac_flies : int
The amount of sac flies.
babip : str
Batting Average on Balls in Play.
- see here: https://www.mlb.com/glossary/advanced-stats/babip
- extrabasehits : int
- The amount of extra base hits. e.g doubles, triples, homeruns
- see here: https://www.mlb.com/glossary/standard-stats/extra-base-hit
- hitbypitch : int
+ extra_base_hits : int
+ The amount of extra base hits.
+ hit_by_pitch : int
The amount of times the batter has been hit by a pitch.
gidp : int
The amount of hits that lead to a double play.
- see here: https://www.mlb.com/glossary/standard-stats/ground-into-double-play
- gidpopp : int
- The amount of GIDP opportunities.
- numberofpitches : int
+ gidp_opp : int
+ The amount of GIDP opportunities.
+ number_of_pitches : int
The number of pitches the batter has faced.
- see here: https://www.mlb.com/glossary/standard-stats/number-of-pitches
- pitchesperplateappearance : str
- The avg amount of pitches per plate appearance for the hitter.
- see here: https://www.mlb.com/glossary/advanced-stats/pitches-per-plate-appearance
- walksperplateappearance : str
+ pitches_per_plate_appearance : str
+ The avg amount of pitches per plate appearance.
+ walks_per_plate_appearance : str
The avg walks per plate appearance.
- see here: https://www.mlb.com/glossary/advanced-stats/walk-rate
- strikeoutsperplateappearance : str
+ strikeouts_per_plate_appearance : str
The amount of strike outs per plate appearance.
- see here: https://www.mlb.com/glossary/advanced-stats/plate-appearances-per-strikeout
- homerunsperplateappearance : str
+ home_runs_per_plate_appearance : str
The amount of home runs per plate appearance.
- see here: https://en.wikipedia.org/wiki/At_bats_per_home_run
- walksperstrikeout : str
+ walks_per_strikeout : str
The amount of walks per strike out.
- see here: https://www.mlb.com/glossary/advanced-stats/strikeout-to-walk-ratio
iso : str
- Isolasted power.
- see also: https://www.mlb.com/glossary/advanced-stats/isolated-power
- reachedonerror : int
- The amount of times the batter has reached base on a error.
- see also: https://www.mlb.com/glossary/standard-stats/reached-on-error
+ Isolated power.
+ reached_on_error : int
+ The amount of times the batter has reached base on an error.
walkoffs : int
The amount of times the batter has walked off a game.
- see also: https://www.mlb.com/glossary/standard-stats/walk-off
flyouts : int
The amount of flyouts for the batter.
- see also: https://www.mlb.com/glossary/standard-stats/flyout
- totalswings : int
- The amount of swings the batter has taken at the plate.
- swingandmisses : int
- The amount of swing and misses the batter has taken at the plate.
- ballsinplay : int
+ total_swings : int
+ The amount of swings the batter has taken.
+ swing_and_misses : int
+ The amount of swing and misses.
+ balls_in_play : int
The amount of balls the batter has put in play.
popouts : int
- The amount of popouts the batter has put in play.
+ The amount of popouts.
lineouts : int
- The amount of lineouts the batter has put in play.
+ The amount of lineouts.
groundouts : int
- The amount of groundouts the batter has hit into.
- flyhits : int
- The amount of fly hits the batter has hit.
- pophits : int
- The amount of pop hits the batter has hit.
- groundhits : int
- The amount of ground hits the batter has hit.
- linehits : int
- The amount of line hits the batter has hit.
+ The amount of groundouts.
+ fly_hits : int
+ The amount of fly hits.
+ pop_hits : int
+ The amount of pop hits.
+ ground_hits : int
+ The amount of ground hits.
+ line_hits : int
+ The amount of line hits.
"""
age: Optional[int] = None
- plateappearances: Optional[int] = None
- totalbases: Optional[int] = None
- leftonbase: Optional[int] = None
- sacbunts: Optional[int] = None
- sacflies: Optional[int] = None
+ plate_appearances: Optional[int] = Field(default=None, alias="plateappearances")
+ total_bases: Optional[int] = Field(default=None, alias="totalbases")
+ left_on_base: Optional[int] = Field(default=None, alias="leftonbase")
+ sac_bunts: Optional[int] = Field(default=None, alias="sacbunts")
+ sac_flies: Optional[int] = Field(default=None, alias="sacflies")
babip: Optional[str] = None
- extrabasehits: Optional[int] = None
- hitbypitch: Optional[int] = None
+ extra_base_hits: Optional[int] = Field(default=None, alias="extrabasehits")
+ hit_by_pitch: Optional[int] = Field(default=None, alias="hitbypitch")
gidp: Optional[int] = None
- gidpopp: Optional[int] = None
- numberofpitches: Optional[int] = None
- pitchesperplateappearance: Optional[str] = None
- walksperplateappearance: Optional[str] = None
- strikeoutsperplateappearance: Optional[str] = None
- homerunsperplateappearance: Optional[str] = None
- walksperstrikeout: Optional[str] = None
+ gidp_opp: Optional[int] = Field(default=None, alias="gidpopp")
+ number_of_pitches: Optional[int] = Field(default=None, alias="numberofpitches")
+ pitches_per_plate_appearance: Optional[str] = Field(default=None, alias="pitchesperplateappearance")
+ walks_per_plate_appearance: Optional[str] = Field(default=None, alias="walksperplateappearance")
+ strikeouts_per_plate_appearance: Optional[str] = Field(default=None, alias="strikeoutsperplateappearance")
+ home_runs_per_plate_appearance: Optional[str] = Field(default=None, alias="homerunsperplateappearance")
+ walks_per_strikeout: Optional[str] = Field(default=None, alias="walksperstrikeout")
iso: Optional[str] = None
- reachedonerror: Optional[int] = None
+ reached_on_error: Optional[int] = Field(default=None, alias="reachedonerror")
walkoffs: Optional[int] = None
flyouts: Optional[int] = None
- totalswings: Optional[int] = None
- swingandmisses: Optional[int] = None
- ballsinplay: Optional[int] = None
+ total_swings: Optional[int] = Field(default=None, alias="totalswings")
+ swing_and_misses: Optional[int] = Field(default=None, alias="swingandmisses")
+ balls_in_play: Optional[int] = Field(default=None, alias="ballsinplay")
popouts: Optional[int] = None
lineouts: Optional[int] = None
groundouts: Optional[int] = None
- flyhits: Optional[int] = None
- pophits: Optional[int] = None
- groundhits: Optional[int] = None
- linehits: Optional[int] = None
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-
-@dataclass(repr=False)
-class SimpleHittingSplit:
- """
- A class to represent a simple hitting statistics
- age: int
- players age at the beginning of the season
- gamesplayed : int
+ fly_hits: Optional[int] = Field(default=None, alias="flyhits")
+ pop_hits: Optional[int] = Field(default=None, alias="pophits")
+ ground_hits: Optional[int] = Field(default=None, alias="groundhits")
+ line_hits: Optional[int] = Field(default=None, alias="linehits")
+
+
+class SimpleHittingSplit(MLBBaseModel):
+ """
+ A class to represent simple hitting statistics.
+
+ Attributes
+ ----------
+ age : int
+ Player's age at the beginning of the season.
+ games_played : int
The number of games played by the batter.
flyouts : int
- The number flyouts hit by the batter
+ The number of flyouts hit by the batter.
groundouts : int
The amount of groundouts hit by the batter.
airouts : int
- The amount of air hits by the batter.
+ The amount of air outs by the batter.
runs : int
The amount of runs plated by the batter.
doubles : int
The amount of doubles hit by the batter.
triples : int
The amount of triples hit by the batter.
- homeruns : int
- The amount of homeruns hit by the batter.
+ home_runs : int
+ The amount of home runs hit by the batter.
strikeouts : int
The amount of strikeouts for the batter.
- baseonballs : int
- The amount of base on balls (walks) for the batter.
- intentionalwalks : int
+ base_on_balls : int
+ The amount of base on balls (walks) for the batter.
+ intentional_walks : int
The number of intentional walks for the batter.
hits : int
The number of hits for the batter.
- hitbypitch : int
+ hit_by_pitch : int
The number of pitches the batter has been hit by.
avg : str
The batting avg of the batter.
- atbats : int
+ at_bats : int
The number of at bats of the batter.
obp : str
The on base percentage of the batter.
- see also: https://www.mlb.com/glossary/standard-stats/on-base-percentage
slg : str
The slugging percentage of the batter.
- see also: https://www.mlb.com/glossary/standard-stats/slugging-percentage
ops : str
- The on-base plug slugging of the batter.
- see also: https://www.mlb.com/glossary/standard-stats/on-base-plus-slugging
- caughtstealing : int
+ The on-base plus slugging of the batter.
+ caught_stealing : int
The amount of times the batter has been caught stealing.
- stolenbases : int
- The amount of stolen bases acheived by the batter.
- stolenbasepercentage : int
+ caught_stealing_percentage : str
+ The caught stealing percentage.
+ stolen_bases : int
+ The amount of stolen bases achieved by the batter.
+ stolen_base_percentage : int
The stolen base percentage of the batter.
- groundintodoubleplay : int
+ ground_into_double_play : int
The number of times the batter has hit into a double play.
- groundintotripleplay : int
+ ground_into_triple_play : int
The number of times the batter has hit into a triple play.
- numberofpitches : int
- The number of pitches the batter has faced.
- plateappearances : int
- The number of plate appearances of the batter.
- totalbases : int
- The number of bases acheived by batter.
+ number_of_pitches : int
+ The number of pitches the batter has faced.
+ plate_appearances : int
+ The number of plate appearances of the batter.
+ total_bases : int
+ The number of bases achieved by batter.
rbi : int
The number of Runs Batted In by the batter.
- see also: https://www.mlb.com/glossary/standard-stats/runs-batted-in
- leftonbase : int
+ left_on_base : int
The number of runners left on base by the batter.
- sacbunts : int
+ sac_bunts : int
The number of sac bunts performed by the batter.
- sacflies : int
+ sac_flies : int
The number of sac flies performed by the batter.
babip : str
The batting average of balls in play of the batter.
- see also: https://www.mlb.com/glossary/advanced-stats/babip
- groundoutstoairouts : int
+ groundouts_to_airouts : int
The groundout-to-airout ratio of the batter.
- see also: https://www.mlb.com/glossary/advanced-stats/babip
- catchersinterference : int
+ catchers_interference : int
The number of times the batter has reached base due to catchers interference.
- see also: https://www.mlb.com/glossary/rules/catcher-interference
- atbatsperhomerun : int
- The number of bats per home run of the batter.
+ at_bats_per_home_run : int
+ The number of at bats per home run of the batter.
"""
age: Optional[int] = None
- gamesplayed: Optional[int] = None
+ games_played: Optional[int] = Field(default=None, alias="gamesplayed")
flyouts: Optional[int] = None
groundouts: Optional[int] = None
airouts: Optional[int] = None
runs: Optional[int] = None
doubles: Optional[int] = None
triples: Optional[int] = None
- homeruns: Optional[int] = None
+ home_runs: Optional[int] = Field(default=None, alias="homeruns")
strikeouts: Optional[int] = None
- baseonballs: Optional[int] = None
- intentionalwalks: Optional[int] = None
+ base_on_balls: Optional[int] = Field(default=None, alias="baseonballs")
+ intentional_walks: Optional[int] = Field(default=None, alias="intentionalwalks")
hits: Optional[int] = None
- hitbypitch: Optional[int] = None
+ hit_by_pitch: Optional[int] = Field(default=None, alias="hitbypitch")
avg: Optional[str] = None
- atbats: Optional[int] = None
+ at_bats: Optional[int] = Field(default=None, alias="atbats")
obp: Optional[str] = None
slg: Optional[str] = None
ops: Optional[str] = None
- caughtstealing: Optional[int] = None
- caughtstealingpercentage: Optional[str] = None
- stolenbases: Optional[int] = None
- stolenbasepercentage: Optional[int] = None
- groundintodoubleplay: Optional[int] = None
- groundintotripleplay: Optional[int] = None
- numberofpitches: Optional[int] = None
- plateappearances: Optional[int] = None
- totalbases: Optional[int] = None
+ caught_stealing: Optional[int] = Field(default=None, alias="caughtstealing")
+ caught_stealing_percentage: Optional[str] = Field(default=None, alias="caughtstealingpercentage")
+ stolen_bases: Optional[int] = Field(default=None, alias="stolenbases")
+ stolen_base_percentage: Optional[str] = Field(default=None, alias="stolenbasepercentage")
+ ground_into_double_play: Optional[int] = Field(default=None, alias="groundintodoubleplay")
+ ground_into_triple_play: Optional[int] = Field(default=None, alias="groundintotripleplay")
+ number_of_pitches: Optional[int] = Field(default=None, alias="numberofpitches")
+ plate_appearances: Optional[int] = Field(default=None, alias="plateappearances")
+ total_bases: Optional[int] = Field(default=None, alias="totalbases")
rbi: Optional[int] = None
- leftonbase: Optional[int] = None
- sacbunts: Optional[int] = None
- sacflies: Optional[int] = None
+ left_on_base: Optional[int] = Field(default=None, alias="leftonbase")
+ sac_bunts: Optional[int] = Field(default=None, alias="sacbunts")
+ sac_flies: Optional[int] = Field(default=None, alias="sacflies")
babip: Optional[str] = None
- groundoutstoairouts: Optional[int] = None
- catchersinterference: Optional[int] = None
- atbatsperhomerun: Optional[int] = None
+ groundouts_to_airouts: Optional[str] = Field(default=None, alias="groundoutstoairouts")
+ catchers_interference: Optional[int] = Field(default=None, alias="catchersinterference")
+ at_bats_per_home_run: Optional[str] = Field(default=None, alias="atbatsperhomerun")
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-@dataclass(kw_only=True, repr=False)
class HittingWinLoss(Split):
"""
- A class to represent a hitting winLoss statistic
+ A class to represent a hitting winLoss statistic.
Attributes
----------
- iswin : bool
- the bool to hold if a win or not for hitting winLoss
- stat : dict
- the hitting split stat
+ is_win : bool
+ The bool to hold if a win or not.
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- _stat = ['winLoss']
- iswin: bool
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['winLoss']
+ is_win: bool = Field(alias="iswin")
+ stat: SimpleHittingSplit
-@dataclass(kw_only=True, repr=False)
class HittingWinLossPlayoffs(Split):
"""
- A class to represent a hitting winLossPlayoffs statistic
+ A class to represent a hitting winLossPlayoffs statistic.
Attributes
----------
- iswin : bool
- the bool to hold if a win or not for hitting winLoss
- stat : dict
- the hitting split stat
+ is_win : bool
+ The bool to hold if a win or not.
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- _stat = ['winLossPlayoffs']
- iswin: bool
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['winLossPlayoffs']
+ is_win: bool = Field(alias="iswin")
+ stat: SimpleHittingSplit
-@dataclass(kw_only=True, repr=False)
class HittingHomeAndAway(Split):
"""
- A class to represent a hitting homeAndAway statistic
+ A class to represent a hitting homeAndAway statistic.
Attributes
----------
- ishome : bool
- the bool to hold if it ishome hitting homeAndAway
- stat : dict
- the hitting split stat
+ is_home : bool
+ The bool to hold if it is home.
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- _stat = ['homeAndAway']
- ishome: bool
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['homeAndAway']
+ is_home: bool = Field(alias="ishome")
+ stat: SimpleHittingSplit
-@dataclass(kw_only=True, repr=False)
class HittingHomeAndAwayPlayoffs(Split):
"""
- A class to represent a hitting homeAndAway Playoff statistic
+ A class to represent a hitting homeAndAway Playoff statistic.
Attributes
----------
- ishome : bool
- the bool to hold if it ishome hitting homeAndAway
- stat : dict
- the hitting split stat
+ is_home : bool
+ The bool to hold if it is home.
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- _stat = ['homeAndAwayPlayoffs']
- ishome: bool
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['homeAndAwayPlayoffs']
+ is_home: bool = Field(alias="ishome")
+ stat: SimpleHittingSplit
+
-@dataclass(kw_only=True, repr=False)
class HittingCareer(Split):
"""
- A class to represent a hitting career, careerRegularSeason or careerPlayoffs statistic
+ A class to represent a hitting career, careerRegularSeason or careerPlayoffs statistic.
Attributes
----------
- stat : dict
- the hitting split stat
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- _stat = ['career', 'careerRegularSeason', 'careerPlayoffs']
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- super().__post_init__()
- self.stat = SimpleHittingSplit(**self.stat)
+ _stat: ClassVar[List[str]] = ['career', 'careerRegularSeason', 'careerPlayoffs']
+ stat: SimpleHittingSplit
-@dataclass(kw_only=True, repr=False)
class HittingSeason(Split):
"""
- A class to represent a hitting season statistic
+ A class to represent a hitting season statistic.
Attributes
----------
- stat : dict
- the hitting split stat
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- _stat = ['season']
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- super().__post_init__()
- self.stat = SimpleHittingSplit(**self.stat)
+ _stat: ClassVar[List[str]] = ['season']
+ stat: SimpleHittingSplit
+
-@dataclass(kw_only=True, repr=False)
class HittingSingleSeason(Split):
"""
- A class to represent a hitting statsSingleSeason statistic
+ A class to represent a hitting statsSingleSeason statistic.
Attributes
----------
- stat : dict
- the hitting split stat
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- _stat = ['statsSingleSeason']
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- super().__post_init__()
- self.stat = SimpleHittingSplit(**self.stat)
+ _stat: ClassVar[List[str]] = ['statsSingleSeason']
+ stat: SimpleHittingSplit
+
-@dataclass(kw_only=True, repr=False)
class HittingSeasonAdvanced(Split):
"""
- A class to represent a hitting seasonAdvanced statistic
+ A class to represent a hitting seasonAdvanced statistic.
Attributes
----------
- stat : dict
- the hitting split stat
+ stat : AdvancedHittingSplit
+ The hitting split stat.
"""
- _stat = ['seasonAdvanced']
- stat: Union[AdvancedHittingSplit, dict]
+ _stat: ClassVar[List[str]] = ['seasonAdvanced']
+ stat: AdvancedHittingSplit
- def __post_init__(self):
- super().__post_init__()
- self.stat = AdvancedHittingSplit(**self.stat)
-@dataclass(kw_only=True, repr=False)
class HittingCareerAdvanced(Split):
"""
- A class to represent a hitting season statistic
+ A class to represent a hitting careerAdvanced statistic.
Attributes
----------
+ stat : AdvancedHittingSplit
+ The hitting split stat.
"""
- _stat = ['careerAdvanced']
- stat: Union[AdvancedHittingSplit, dict]
+ _stat: ClassVar[List[str]] = ['careerAdvanced']
+ stat: AdvancedHittingSplit
- def __post_init__(self):
- self.stat = AdvancedHittingSplit(**self.stat)
- super().__post_init__()
-@dataclass(kw_only=True, repr=False)
class HittingYearByYear(Split):
"""
- A class to represent a hitting yearbyyear or yearByYearPlayoffs statistic
+ A class to represent a hitting yearByYear statistic.
Attributes
----------
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- _stat = ['yearByYear']
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['yearByYear']
+ stat: SimpleHittingSplit
-@dataclass(kw_only=True, repr=False)
class HittingYearByYearPlayoffs(Split):
"""
- A class to represent a hitting yearByYearPlayoffs statistic
+ A class to represent a hitting yearByYearPlayoffs statistic.
Attributes
----------
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- _stat = ['yearByYearPlayoffs']
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['yearByYearPlayoffs']
+ stat: SimpleHittingSplit
-@dataclass(kw_only=True, repr=False)
class OpponentsFacedHitting(Split):
"""
- A class to represent a hitting opponentsFaced statistic
+ A class to represent a hitting opponentsFaced statistic.
Attributes
----------
- batter : Person
- the batter of that stat object
- fieldingteam : Team
- the defence team of the stat object
- pitcher : Person
- the pitcher of that stat object
+ batter : Batter
+ The batter of that stat object.
+ fielding_team : Team
+ The defence team of the stat object.
+ pitcher : Pitcher
+ The pitcher of that stat object.
group : str
- stat group
+ Stat group.
"""
- _stat = ['opponentsFaced']
+ _stat: ClassVar[List[str]] = ['opponentsFaced']
group: str
- batter: Union[Batter, dict]
- fieldingteam: Union[Team, dict]
- pitcher: Union[Pitcher, dict]
+ batter: Batter
+ fielding_team: Team = Field(alias="fieldingteam")
+ pitcher: Pitcher
- def __post_init__(self):
- super().__post_init__()
-@dataclass(kw_only=True, repr=False)
class HittingSabermetrics(Split):
"""
- A class to represent a hitting sabermetric statistic
+ A class to represent a hitting sabermetric statistic.
+ Attributes
+ ----------
+ stat : Sabermetrics
+ The sabermetric statistics.
"""
- _stat = ['sabermetrics']
- stat: Union[Sabermetrics, dict]
+ _stat: ClassVar[List[str]] = ['sabermetrics']
+ stat: Sabermetrics
- def __post_init__(self):
- self.stat = Sabermetrics(**self.stat)
- super().__post_init__()
-@dataclass(kw_only=True, repr=False)
class HittingGameLog(Split):
"""
- A class to represent a gamelog stat for a hitter
+ A class to represent a gamelog stat for a hitter.
Attributes
----------
- positionsplayed : List[Position]
+ positions_played : List[Position]
+ List of positions played.
stat : SimpleHittingSplit
- ishome : bool
- bool to hold ishome
- iswin : bool
- bool to hold iswin
+ The hitting split stat.
+ is_home : bool
+ Bool to hold is home.
+ is_win : bool
+ Bool to hold is win.
game : Game
- Game of the log
+ Game of the log.
date : str
- date of the log
- gametype : str
- type of game
+ Date of the log.
opponent : Team
- Team of the opponent
- sport : Sport
- Sport of the stat
- league : League
- League of the stat
- player : Person
- Player of the stat
- """
- ishome: bool
- iswin: bool
- game: Union[Game, dict]
+ Team of the opponent.
+ """
+ _stat: ClassVar[List[str]] = ['gameLog']
+ is_home: bool = Field(alias="ishome")
+ is_win: bool = Field(alias="iswin")
+ game: Game
date: str
- opponent: Union[Team, dict]
- _stat = ['gameLog']
- positionsplayed: Optional[List[Position]] = field(default_factory=list)
- stat: Union[SimpleHittingSplit, dict] = field(default_factory=dict)
-
- def __post_init__(self):
- if self.positionsplayed:
- self.positionsplayed = [Position(**position) for position in self.positionsplayed]
- self.stat = SimpleHittingSplit(**self.stat) if self.stat else self.stat
- super().__post_init__()
-
-@dataclass(kw_only=True, repr=False)
-class HittingPlay:
- """
- A class to represent a gamelog stat for a hitter
-
- Attributes
- ----------
- """
- details: Union[PlayDetails, dict]
- count: Union[Count, dict]
- ispitch: bool
- pitchnumber: Optional[int] = None
- atbatnumber: Optional[int] = None
- index: Optional[str] = None
- playid: Optional[str] = None
- pitchdata: Optional[Union[PitchData, dict]] = field(default_factory=dict)
- hitdata: Optional[Union[HitData, dict]] = field(default_factory=dict)
- starttime: Optional[str] = None
- endtime: Optional[str] = None
+ opponent: Team
+ positions_played: Optional[List[Position]] = Field(default=[], alias="positionsplayed")
+ stat: Optional[SimpleHittingSplit] = None
+
+ @field_validator('stat', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
+
+
+class HittingPlay(MLBBaseModel):
+ """
+ A class to represent a play stat for a hitter.
+
+ Attributes
+ ----------
+ details : PlayDetails
+ Play details.
+ count : Count
+ The count.
+ is_pitch : bool
+ Is pitch bool.
+ pitch_number : int
+ Pitch number.
+ at_bat_number : int
+ At bat number.
+ index : str
+ Index.
+ play_id : str
+ Play ID.
+ pitch_data : PitchData
+ Pitch data.
+ hit_data : HitData
+ Hit data.
+ start_time : str
+ Start time.
+ end_time : str
+ End time.
+ type : str
+ Type.
+ """
+ details: PlayDetails
+ count: Count
+ is_pitch: bool = Field(alias="ispitch")
+ pitch_number: Optional[int] = Field(default=None, alias="pitchnumber")
+ at_bat_number: Optional[int] = Field(default=None, alias="atbatnumber")
+ index: Optional[int] = None
+ play_id: Optional[str] = Field(default=None, alias="playid")
+ pitch_data: Optional[PitchData] = Field(default=None, alias="pitchdata")
+ hit_data: Optional[HitData] = Field(default=None, alias="hitdata")
+ start_time: Optional[str] = Field(default=None, alias="starttime")
+ end_time: Optional[str] = Field(default=None, alias="endtime")
type: Optional[str] = None
+ @field_validator('pitch_data', 'hit_data', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
- def __post_init__(self):
- self.details = PlayDetails(**self.details)
- self.count = Count(**self.count)
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-
-@dataclass(kw_only=True, repr=False)
class HittingPlayLog(Split):
"""
- A class to represent a gamelog stat for a hitter
+ A class to represent a play log stat for a hitter.
Attributes
----------
- season : str
- season for the stat
+ stat : HittingPlay
+ Information regarding the play for the stat.
opponent : Team
- opponent
+ Opponent.
date : str
- date of log
- gametype : str
- game type code
- ishome : bool
- is the game at home bool
- pitcher : Person
- pitcher of the log
- batter : Person
- batter of the log
+ Date of log.
+ is_home : bool
+ Is the game at home bool.
+ pitcher : Pitcher
+ Pitcher of the log.
+ batter : Batter
+ Batter of the log.
game : Game
- the game of the log
-
+ The game of the log.
"""
- stat: Union[HittingPlay, dict]
- opponent: Optional[Union[Team, dict]] = field(default_factory=dict)
+ _stat: ClassVar[List[str]] = ['playLog']
+ stat: HittingPlay
+ opponent: Optional[Team] = None
date: Optional[str] = None
- ishome: Optional[bool] = None
- pitcher: Optional[Union[Pitcher, dict]] = field(default_factory=dict)
- batter: Optional[Union[Batter, dict]] = field(default_factory=dict)
- game: Optional[Union[Game, dict]] = field(default_factory=dict)
-
- _stat = ['playLog']
+ is_home: Optional[bool] = Field(default=None, alias="ishome")
+ pitcher: Optional[Pitcher] = None
+ batter: Optional[Batter] = None
+ game: Optional[Game] = None
+
+ @field_validator('stat', mode='before')
+ @classmethod
+ def extract_play(cls, v: Any) -> Any:
+ """Extract play from stat dict."""
+ if isinstance(v, dict) and 'play' in v:
+ return v['play']
+ return v
+
+ @field_validator('opponent', 'pitcher', 'batter', 'game', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
- def __post_init__(self):
- self.stat = HittingPlay(**self.stat['play'])
- super().__post_init__()
-@dataclass(kw_only=True, repr=False)
class HittingPitchLog(Split):
"""
- A class to represent a gamelog stat for a hitter
+ A class to represent a pitch log stat for a hitter.
Attributes
----------
- season : str
- season for the stat
- stat : PlayLog
- information regarding the play for the stat
+ stat : HittingPlay
+ Information regarding the play for the stat.
opponent : Team
- opponent
+ Opponent.
date : str
- date of log
- gametype : str
- game type code
- ishome : bool
- is the game at home bool
- pitcher : Person
- pitcher of the log
- batter : Person
- batter of the log
+ Date of log.
+ is_home : bool
+ Is the game at home bool.
+ pitcher : Pitcher
+ Pitcher of the log.
+ batter : Batter
+ Batter of the log.
game : Game
- the game of the log
-
+ The game of the log.
+ play_id : str
+ Play ID.
"""
- stat: PlayDetails
- _stat = ['pitchLog']
- opponent: Union[Team, dict]
+ _stat: ClassVar[List[str]] = ['pitchLog']
+ stat: HittingPlay
+ opponent: Team
date: str
- ishome: bool
- pitcher: Union[Pitcher, dict]
- batter: Union[Batter, dict]
- game: Union[Game, dict]
- playid: Optional[str] = None
+ is_home: bool = Field(alias="ishome")
+ pitcher: Pitcher
+ batter: Batter
+ game: Game
+ play_id: Optional[str] = Field(default=None, alias="playid")
- def __post_init__(self):
- self.stat = HittingPlay(**self.stat['play'])
- super().__post_init__()
+ @field_validator('stat', mode='before')
+ @classmethod
+ def extract_play(cls, v: Any) -> Any:
+ """Extract play from stat dict."""
+ if isinstance(v, dict) and 'play' in v:
+ return v['play']
+ return v
-@dataclass(kw_only=True, repr=False)
class HittingLastXGames(Split):
"""
- A class to represent a lastXGames statistic
+ A class to represent a lastXGames statistic.
Attributes
----------
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- _stat = ['lastXGames']
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['lastXGames']
+ stat: SimpleHittingSplit
-@dataclass(kw_only=True, repr=False)
class HittingDateRange(Split):
"""
- A class to represent a byDateRange statistic
+ A class to represent a byDateRange statistic.
Attributes
----------
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- _stat = ['byDateRange']
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['byDateRange']
+ stat: SimpleHittingSplit
-@dataclass(kw_only=True, repr=False)
class HittingDateRangeAdvanced(Split):
"""
- A class to represent a byDateRangeAdvanced statistic
+ A class to represent a byDateRangeAdvanced statistic.
Attributes
----------
+ stat : AdvancedHittingSplit
+ The hitting split stat.
"""
- _stat = ['byDateRangeAdvanced']
- stat: Union[AdvancedHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = AdvancedHittingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['byDateRangeAdvanced']
+ stat: AdvancedHittingSplit
-@dataclass(kw_only=True, repr=False)
class HittingDateRangeAdvancedByMonth(Split):
"""
- A class to represent a byDateRangeAdvanced statistic
+ A class to represent a byDateRangeAdvanced by month statistic.
Attributes
----------
+ stat : AdvancedHittingSplit
+ The hitting split stat.
"""
- _stat = ['byDateRangeAdvancedbyMonth']
- stat: Union[AdvancedHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = AdvancedHittingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['byDateRangeAdvancedbyMonth']
+ stat: AdvancedHittingSplit
-@dataclass(kw_only=True, repr=False)
class HittingByMonth(Split):
"""
- A class to represent a byMonth hitting statistic
+ A class to represent a byMonth hitting statistic.
Attributes
----------
+ month : int
+ The month.
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- _stat = ['byMonth']
+ _stat: ClassVar[List[str]] = ['byMonth']
month: int
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- super().__post_init__()
+ stat: SimpleHittingSplit
-@dataclass(kw_only=True, repr=False)
class HittingByMonthPlayoffs(Split):
"""
- A class to represent a yearByYear hitting statistic
+ A class to represent a byMonthPlayoffs hitting statistic.
Attributes
----------
- month : str
- the month of the stat
+ month : int
+ The month of the stat.
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- _stat = ['byMonthPlayoffs']
+ _stat: ClassVar[List[str]] = ['byMonthPlayoffs']
month: int
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- super().__post_init__()
+ stat: SimpleHittingSplit
-@dataclass(kw_only=True, repr=False)
class HittingDayOfWeek(Split):
"""
- A class to represent a yearByYear hitting statistic
+ A class to represent a byDayOfWeek hitting statistic.
Attributes
----------
- dayofweek : int
- the day of the week
+ day_of_week : int
+ The day of the week.
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- _stat = ['byDayOfWeek']
- dayofweek: int
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
+ _stat: ClassVar[List[str]] = ['byDayOfWeek']
+ day_of_week: int = Field(alias="dayofweek")
+ stat: SimpleHittingSplit
-@dataclass(kw_only=True, repr=False)
class HittingDayOfWeekPlayoffs(Split):
"""
- A class to represent a yearByYear hitting statistic
+ A class to represent a byDayOfWeekPlayoffs hitting statistic.
Attributes
----------
- dayofweek : int
- the day of the week
+ day_of_week : int
+ The day of the week.
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- _stat = ['byDayOfWeekPlayoffs']
- dayofweek: int
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['byDayOfWeekPlayoffs']
+ day_of_week: int = Field(alias="dayofweek")
+ stat: SimpleHittingSplit
+
-@dataclass(kw_only=True, repr=False)
class HittingExpectedStatistics(Split):
"""
- A class to represent a excepted statistics statType: expectedStatistics.
+ A class to represent expected statistics statType: expectedStatistics.
+
Attributes
----------
- avg : str
- slg : str
- woba : str
- wobaCon : str
- rank : int
+ stat : ExpectedStatistics
+ The expected statistics.
"""
- _stat = ['expectedStatistics']
- stat: Union[ExpectedStatistics, dict]
-
- def __post_init__(self):
- self.stat = ExpectedStatistics(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['expectedStatistics']
+ stat: ExpectedStatistics
-@dataclass(kw_only=True, repr=False)
class HittingVsTeam(Split):
"""
- A class to represent a vsTeam hitting statistic
+ A class to represent a vsTeam hitting statistic.
+
+ Requires the use of the opposingTeamId parameter.
- requires the use of the opposingTeamId parameter
Attributes
----------
- dayofweek : int
- the day of the week
+ opponent : Team
+ The opponent team.
+ batter : Batter
+ The batter.
+ pitcher : Pitcher
+ The pitcher.
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- _stat = ['vsTeam']
- opponent: Union[Team, dict]
- batter: Optional[Union[Batter, dict]] = field(default_factory=dict)
- pitcher: Optional[Union[Pitcher, dict]] = field(default_factory=dict)
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['vsTeam']
+ opponent: Team
+ stat: SimpleHittingSplit
+ batter: Optional[Batter] = None
+ pitcher: Optional[Pitcher] = None
+
+ @field_validator('batter', 'pitcher', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
+
-@dataclass(kw_only=True, repr=False)
class HittingVsTeamTotal(Split):
"""
- A class to represent a vsTeamTotal hitting statistic
+ A class to represent a vsTeamTotal hitting statistic.
- requires the use of the opposingTeamId parameter
+ Requires the use of the opposingTeamId parameter.
Attributes
----------
+ opponent : Team
+ Opponent team.
+ batter : Batter
+ Batting person.
+ pitcher : Pitcher
+ Pitching person.
+ stat : SimpleHittingSplit
+ The hitting split stat.
+ """
+ _stat: ClassVar[List[str]] = ['vsTeamTotal']
opponent: Team
- opponent team
- batter: Person
- batting person
- pitcher: Person
- pitching person
- """
- _stat = ['vsTeamTotal']
- opponent: Union[Team, dict]
- batter: Optional[Union[Batter, dict]] = field(default_factory=dict)
- pitcher: Optional[Union[Pitcher, dict]] = field(default_factory=dict)
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- super().__post_init__()
-
-@dataclass(kw_only=True, repr=False)
+ stat: SimpleHittingSplit
+ batter: Optional[Batter] = None
+ pitcher: Optional[Pitcher] = None
+
+ @field_validator('batter', 'pitcher', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
+
+
class HittingVsTeam5Y(Split):
"""
- A class to represent a vsTeam5Y hitting statistic
+ A class to represent a vsTeam5Y hitting statistic.
- requires the use of the opposingTeamId parameter
+ Requires the use of the opposingTeamId parameter.
Attributes
----------
+ opponent : Team
+ Opponent team.
+ batter : Batter
+ The batter.
+ pitcher : Pitcher
+ The pitcher.
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- _stat = ['vsTeam5Y']
- opponent: Union[Team, dict]
- batter: Optional[Union[Batter, dict]] = field(default_factory=dict)
- pitcher: Optional[Union[Pitcher, dict]] = field(default_factory=dict)
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['vsTeam5Y']
+ opponent: Team
+ stat: SimpleHittingSplit
+ batter: Optional[Batter] = None
+ pitcher: Optional[Pitcher] = None
+
+ @field_validator('batter', 'pitcher', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
+
-@dataclass(kw_only=True, repr=False)
class HittingVsPlayer(Split):
"""
- A class to represent a yearByYear hitting statistic
+ A class to represent a vsPlayer hitting statistic.
- This class is for the stat type vsPlayer*
-
- Requires the param opposingPlayerId set
+ Requires the param opposingPlayerId set.
Attributes
----------
pitcher : Pitcher
- The pitcher of the hitting vsplayer stat
+ The pitcher of the hitting vsplayer stat.
batter : Batter
- The batter of the hitting vsplayer stat
+ The batter of the hitting vsplayer stat.
opponent : Team
- The team of the hitting vsplayer stat
- """
- _stat = ['vsPlayer']
- pitcher: Union[Pitcher, dict]
- batter: Union[Batter, dict]
- opponent: Optional[Union[Team, dict]] = field(default_factory=dict)
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- super().__post_init__()
-
-@dataclass(kw_only=True, repr=False)
-class HittingVsPlayerTotal(Split):
+ The team of the hitting vsplayer stat.
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- A class to represent a yearByYear hitting statistic
+ _stat: ClassVar[List[str]] = ['vsPlayer']
+ pitcher: Pitcher
+ batter: Batter
+ stat: SimpleHittingSplit
+ opponent: Optional[Team] = None
- This class is for the stat type vsPlayer*
+ @field_validator('opponent', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
- Requires the param opposingPlayerId set
+
+class HittingVsPlayerTotal(Split):
+ """
+ A class to represent a vsPlayerTotal hitting statistic.
+
+ Requires the param opposingPlayerId set.
Attributes
----------
pitcher : Pitcher
- The pitcher of the hitting vsplayer stat
+ The pitcher of the hitting vsplayer stat.
batter : Batter
- The batter of the hitting vsplayer stat
+ The batter of the hitting vsplayer stat.
opponent : Team
- The team of the hitting vsplayer stat
- """
- _stat = ['vsPlayerTotal']
- pitcher: Union[Pitcher, dict]
- batter: Union[Batter, dict]
- opponent: Optional[Union[Team, dict]] = field(default_factory=dict)
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- super().__post_init__()
-
-@dataclass(kw_only=True, repr=False)
-class HittingVsPlayer5Y(Split):
+ The team of the hitting vsplayer stat.
+ stat : SimpleHittingSplit
+ The hitting split stat.
"""
- A class to represent a yearByYear hitting statistic
+ _stat: ClassVar[List[str]] = ['vsPlayerTotal']
+ pitcher: Pitcher
+ batter: Batter
+ stat: SimpleHittingSplit
+ opponent: Optional[Team] = None
- This class is for the stat type vsPlayer*
+ @field_validator('opponent', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
- Requires the param opposingPlayerId set
+
+class HittingVsPlayer5Y(Split):
+ """
+ A class to represent a vsPlayer5Y hitting statistic.
+
+ Requires the param opposingPlayerId set.
Attributes
----------
pitcher : Pitcher
- The pitcher of the hitting vsplayer stat
- batter : Batter
- The batter of the hitting vsplayer stat
+ The pitcher of the hitting vsplayer stat.
+ batter : Person
+ The batter of the hitting vsplayer stat.
opponent : Team
- The team of the hitting vsplayer stat
- """
- _stat = ['vsPlayer5Y']
- pitcher: Union[Pitcher, dict]
- batter: Union[Person, dict]
- opponent: Optional[Union[Team, dict]] = field(default_factory=dict)
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- super().__post_init__()
+ The team of the hitting vsplayer stat.
+ stat : SimpleHittingSplit
+ The hitting split stat.
+ """
+ _stat: ClassVar[List[str]] = ['vsPlayer5Y']
+ stat: SimpleHittingSplit
+ pitcher: Optional[Pitcher] = None
+ batter: Optional[Person] = None
+ opponent: Optional[Team] = None
+
+ @field_validator('opponent', 'pitcher', 'batter', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
diff --git a/mlbstatsapi/models/stats/pitching.py b/mlbstatsapi/models/stats/pitching.py
index 2eb4a0c7..92190fb7 100644
--- a/mlbstatsapi/models/stats/pitching.py
+++ b/mlbstatsapi/models/stats/pitching.py
@@ -1,37 +1,28 @@
-from dataclasses import InitVar, dataclass, field
-from typing import Optional, Union, List
-
+from typing import Optional, List, Any, ClassVar
+from pydantic import Field, field_validator
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.people import Person, Pitcher, Batter
from mlbstatsapi.models.teams import Team
from mlbstatsapi.models.game import Game
-from mlbstatsapi.mlb_module import merge_keys
-from mlbstatsapi.models.data import (
- Count,
- PlayDetails,
-
-)
-
+from mlbstatsapi.models.data import Count, PlayDetails
from .stats import Sabermetrics, ExpectedStatistics, Split
from .hitting import SimpleHittingSplit
-@dataclass(repr=False)
-class SimplePitchingSplit:
+class SimplePitchingSplit(MLBBaseModel):
"""
- A class to represent a advanced pitching statistics
-
- attributes are all optional as there is no documentation for the stats endpoint
+ A class to represent simple pitching statistics.
Attributes
----------
summary : str
- Summary of stats for the pitcher
- gamesplayed : int
+ Summary of stats for the pitcher.
+ games_played : int
The games played by the pitcher.
- gamesstarted : int
+ games_started : int
The games started by the pitcher.
flyouts : int
- The number of flyouts for the pitcher
+ The number of flyouts for the pitcher.
groundouts : int
The number of groundouts for the pitcher.
airouts : int
@@ -42,42 +33,41 @@ class SimplePitchingSplit:
The number of doubles given up by the pitcher.
triples : int
The number of triples given up by the pitcher.
- homeruns : int
+ home_runs : int
The number of home runs given up by the pitcher.
strikeouts : int
The number of strike outs performed by the pitcher.
- baseonballs : int
+ base_on_balls : int
The number of base on balls (walks) performed by the pitcher.
- intentionalwalks : int
+ intentional_walks : int
The number of intentional walks performed by the pitcher.
hits : int
The number of hits given up by the pitcher.
- hitbypitch : int
+ hit_by_pitch : int
The number of batters hit by the pitcher.
- avg : int
+ avg : str
The batting avg against the pitcher.
- atbats : int
+ at_bats : int
The at bats pitched by the pitcher.
obp : str
- The on base percentage again the pitcher.
+ The on base percentage against the pitcher.
slg : str
The slugging percentage against the pitcher.
ops : str
The on base slugging against the pitcher.
- see also: https://www.mlb.com/glossary/standard-stats/on-base-plus-slugging
- caughtstealing : int
+ caught_stealing : int
The number of runners caught stealing against the pitcher.
- stolenbases : int
+ stolen_bases : int
The number of stolen bases while pitching.
- stolenbasepercentage : int
+ stolen_base_percentage : str
The stolen base percentage while pitching.
- groundintodoubleplay : int
- The number of hits against
- numberofpitches : int
+ ground_into_double_play : int
+ The number of double plays hit into.
+ number_of_pitches : int
The number of pitches thrown.
era : str
The earned run average of the pitcher.
- inningspitched : int
+ innings_pitched : str
The number of innings pitched by the pitcher.
wins : int
The number of wins by the pitcher.
@@ -85,660 +75,593 @@ class SimplePitchingSplit:
The number of losses by the pitcher.
saves : int
The number of saves by the pitcher.
- saveopportunities : int
+ save_opportunities : int
The number of save opportunities by the pitcher.
holds : int
The number of holds by the pitcher.
- blownsaves : int
+ blown_saves : int
The number of blown saves performed by the pitcher.
- earnedruns : int
+ earned_runs : int
The number of earned runs given up by the pitcher.
whip : str
The number of walks and hits per inning pitched.
- see also: https://www.mlb.com/glossary/standard-stats/walks-and-hits-per-inning-pitched
outs : int
- The number of outs
- gamespitched : int
+ The number of outs.
+ games_pitched : int
The number of games pitched.
- completegames : int
+ complete_games : int
The number of complete games pitched.
shutouts : int
The number of shut outs pitched.
strikes : int
- The number of strikes thown by the pitcher.
- hitbatsmen : int
+ The number of strikes thrown by the pitcher.
+ hit_batsmen : int
The number of batters hit by a pitch.
- strikepercentage : str
+ strike_percentage : str
The strike percentage thrown by the pitcher.
- wildpitches : int
- The number of wild pitches thown by the pitcher.
+ wild_pitches : int
+ The number of wild pitches thrown by the pitcher.
balks : int
- The number of balks commited by the pitcher.
- totalbases : int
+ The number of balks committed by the pitcher.
+ total_bases : int
The total bases given up by the pitcher.
pickoffs : int
The number of pick offs performed by the pitcher.
- winpercentage : str
- The winpercentage of the pitcher.
- groundoutstoairouts : str
+ win_percentage : str
+ The win percentage of the pitcher.
+ groundouts_to_airouts : str
The groundout-to-airout ratio of the pitcher.
- gamesfinished : int
+ games_finished : int
The number of games finished by the pitcher.
- pitchesperinning : str
- The number of pitches thown per inning by the pitcher.
- strikeoutsper9inn : str
- The number of strike outs per 9 innings by the pitcher
- strikeoutwalkratio : str
+ pitches_per_inning : str
+ The number of pitches thrown per inning by the pitcher.
+ strikeouts_per_9_inn : str
+ The number of strike outs per 9 innings by the pitcher.
+ strikeout_walk_ratio : str
The strike out to walk ratio of the pitcher.
- hitsper9inn : str
+ hits_per_9_inn : str
The number of hits per 9 innings pitched.
- walksper9inn : str
+ walks_per_9_inn : str
The number of walks per 9 innings pitched.
- homerunsper9 : str
+ home_runs_per_9 : str
The number of home runs per 9 innings pitched.
- runsscoredper9 : str
+ runs_scored_per_9 : str
The number of runs scored per 9 innings pitched.
- sacbunts : int
+ sac_bunts : int
The number of sac bunts given up when pitched.
- catchersinterference : int
- The number of times a runner has reached from catchers interference while pitching.
- battersfaced : int
+ catchers_interference : int
+ The number of times a runner has reached from catchers interference.
+ batters_faced : int
The number of batters faced by the pitcher.
- sacflies : int
+ sac_flies : int
The number of sac flies given up by the pitcher.
- inheritedrunnersscored : int
+ inherited_runners_scored : int
The number of inherited runners scored by the pitcher.
- inheritedrunners : int
+ inherited_runners : int
The number of inherited runners for the pitcher.
age : int
The age of the pitcher.
- caughtstealingpercentage : str
+ caught_stealing_percentage : str
The caught stealing percentage for the pitcher.
"""
summary: Optional[str] = None
age: Optional[int] = None
- gamesplayed: Optional[int] = None
- gamesstarted: Optional[int] = None
+ games_played: Optional[int] = Field(default=None, alias="gamesplayed")
+ games_started: Optional[int] = Field(default=None, alias="gamesstarted")
flyouts: Optional[int] = None
groundouts: Optional[int] = None
airouts: Optional[int] = None
runs: Optional[int] = None
doubles: Optional[int] = None
triples: Optional[int] = None
- homeruns: Optional[int] = None
+ home_runs: Optional[int] = Field(default=None, alias="homeruns")
strikeouts: Optional[int] = None
- baseonballs: Optional[int] = None
- intentionalwalks: Optional[int] = None
+ base_on_balls: Optional[int] = Field(default=None, alias="baseonballs")
+ intentional_walks: Optional[int] = Field(default=None, alias="intentionalwalks")
hits: Optional[int] = None
- hitbypitch: Optional[int] = None
+ hit_by_pitch: Optional[int] = Field(default=None, alias="hitbypitch")
avg: Optional[str] = None
- atbats: Optional[int] = None
+ at_bats: Optional[int] = Field(default=None, alias="atbats")
obp: Optional[str] = None
slg: Optional[str] = None
ops: Optional[str] = None
- caughtstealing: Optional[int] = None
- caughtstealingpercentage: Optional[str]=None
- stolenbases: Optional[int] = None
- stolenbasepercentage: Optional[str] = None
- groundintodoubleplay: Optional[int] = None
- numberofpitches: Optional[int] = None
+ caught_stealing: Optional[int] = Field(default=None, alias="caughtstealing")
+ caught_stealing_percentage: Optional[str] = Field(default=None, alias="caughtstealingpercentage")
+ stolen_bases: Optional[int] = Field(default=None, alias="stolenbases")
+ stolen_base_percentage: Optional[str] = Field(default=None, alias="stolenbasepercentage")
+ ground_into_double_play: Optional[int] = Field(default=None, alias="groundintodoubleplay")
+ number_of_pitches: Optional[int] = Field(default=None, alias="numberofpitches")
era: Optional[str] = None
- inningspitched: Optional[str] = None
+ innings_pitched: Optional[str] = Field(default=None, alias="inningspitched")
wins: Optional[int] = None
losses: Optional[int] = None
saves: Optional[int] = None
- saveopportunities: Optional[int] = None
+ save_opportunities: Optional[int] = Field(default=None, alias="saveopportunities")
holds: Optional[int] = None
- blownsaves: Optional[int] = None
- earnedruns: Optional[int] = None
+ blown_saves: Optional[int] = Field(default=None, alias="blownsaves")
+ earned_runs: Optional[int] = Field(default=None, alias="earnedruns")
whip: Optional[str] = None
outs: Optional[int] = None
- gamespitched: Optional[int] = None
- completegames: Optional[int] = None
+ games_pitched: Optional[int] = Field(default=None, alias="gamespitched")
+ complete_games: Optional[int] = Field(default=None, alias="completegames")
shutouts: Optional[int] = None
strikes: Optional[int] = None
- strikepercentage: Optional[str] = None
- hitbatsmen: Optional[int] = None
+ strike_percentage: Optional[str] = Field(default=None, alias="strikepercentage")
+ hit_batsmen: Optional[int] = Field(default=None, alias="hitbatsmen")
balks: Optional[int] = None
- wildpitches: Optional[int] = None
+ wild_pitches: Optional[int] = Field(default=None, alias="wildpitches")
pickoffs: Optional[int] = None
- totalbases: Optional[int] = None
- groundoutstoairouts: Optional[str] = None
- winpercentage: Optional[str] = None
- pitchesperinning: Optional[str] = None
- gamesfinished: Optional[int] = None
- strikeoutwalkratio: Optional[str] = None
- strikeoutsper9inn: Optional[str] = None
- walksper9inn: Optional[str] = None
- hitsper9inn: Optional[str] = None
- runsscoredper9: Optional[str] = None
- homerunsper9: Optional[str] = None
- catchersinterference: Optional[int] = None
- sacbunts: Optional[int] = None
- sacflies: Optional[int] = None
- battersfaced: Optional[int] = None
- inheritedrunners: Optional[int] = None
- inheritedrunnersscored: Optional[int] = None
+ total_bases: Optional[int] = Field(default=None, alias="totalbases")
+ groundouts_to_airouts: Optional[str] = Field(default=None, alias="groundoutstoairouts")
+ win_percentage: Optional[str] = Field(default=None, alias="winpercentage")
+ pitches_per_inning: Optional[str] = Field(default=None, alias="pitchesperinning")
+ games_finished: Optional[int] = Field(default=None, alias="gamesfinished")
+ strikeout_walk_ratio: Optional[str] = Field(default=None, alias="strikeoutwalkratio")
+ strikeouts_per_9_inn: Optional[str] = Field(default=None, alias="strikeoutsper9inn")
+ walks_per_9_inn: Optional[str] = Field(default=None, alias="walksper9inn")
+ hits_per_9_inn: Optional[str] = Field(default=None, alias="hitsper9inn")
+ runs_scored_per_9: Optional[str] = Field(default=None, alias="runsscoredper9")
+ home_runs_per_9: Optional[str] = Field(default=None, alias="homerunsper9")
+ catchers_interference: Optional[int] = Field(default=None, alias="catchersinterference")
+ sac_bunts: Optional[int] = Field(default=None, alias="sacbunts")
+ sac_flies: Optional[int] = Field(default=None, alias="sacflies")
+ batters_faced: Optional[int] = Field(default=None, alias="battersfaced")
+ inherited_runners: Optional[int] = Field(default=None, alias="inheritedrunners")
+ inherited_runners_scored: Optional[int] = Field(default=None, alias="inheritedrunnersscored")
balls: Optional[int] = None
- outspitched: Optional[int] = None
+ outs_pitched: Optional[int] = Field(default=None, alias="outspitched")
rbi: Optional[int] = None
- age: Optional[int] = None
- caughtstealingpercentage: Optional[str] = None
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-
-@dataclass(repr=False)
-class AdvancedPitchingSplit:
+class AdvancedPitchingSplit(MLBBaseModel):
"""
- A class to represent a advanced pitching statistics
-
- winningpercentage : str
+ A class to represent advanced pitching statistics.
+
+ Attributes
+ ----------
+ age : int
+ The age of the pitcher.
+ winning_percentage : str
The winning percentage of the pitcher.
- runsscoredper9 : str
- The number of runs scored per 9 innings
- battersfaced : int
- The number of batters faced
+ runs_scored_per_9 : str
+ The number of runs scored per 9 innings.
+ batters_faced : int
+ The number of batters faced.
babip : str
The BABIP of the pitcher.
obp : str
- The on base percentage again the pitcher.
+ The on base percentage against the pitcher.
slg : str
The slugging percentage against the pitcher.
ops : str
The on base slugging against the pitcher.
- see also: https://www.mlb.com/glossary/standard-stats/on-base-plus-slugging
- strikeoutsper9 : str
- The number of strike outs per 9 innings by the pitcher
- baseonballsper9 : str
- The number of base on balls per 9 innings by the pitcher.
- homerunsper9 : str
- The number of home runs per 9 innings by the pitcher.
- hitsper9 : str
- The number of hits per 9 innings by the pitcher.
- strikesoutstowalks : str
- The strike out to walk ratio of the pitcher.
- stolenbases : int
- The number of stolen bases while pitching.
- caughtstealing : int
- The number of runners caught stealing by the pitcher.
- qualitystarts : int
- The number of quality starts performed by the pitcher.
- gamesfinished : int
- The number of games finished performed by the pitcher.
+ strikeouts_per_9 : str
+ The number of strike outs per 9 innings.
+ base_on_balls_per_9 : str
+ The number of base on balls per 9 innings.
+ home_runs_per_9 : str
+ The number of home runs per 9 innings.
+ hits_per_9 : str
+ The number of hits per 9 innings.
+ strikeouts_to_walks : str
+ The strike out to walk ratio.
+ stolen_bases : int
+ The number of stolen bases while pitching.
+ caught_stealing : int
+ The number of runners caught stealing.
+ quality_starts : int
+ The number of quality starts.
+ games_finished : int
+ The number of games finished.
doubles : int
- The number of doubles given up by the pitcher.
+ The number of doubles given up.
triples : int
- The number of triples given up by the pitcher.
+ The number of triples given up.
gidp : int
The amount of hits that lead to a double play.
- see here: https://www.mlb.com/glossary/standard-stats/ground-into-double-play
- gidpopp : int
- The amount of GIDP opportunities.
- wildpitches : int
- The number of wild pitches thown by the pitcher.
+ gidp_opp : int
+ The amount of GIDP opportunities.
+ wild_pitches : int
+ The number of wild pitches thrown.
balks : int
- The number of balks commited by the pitcher.
+ The number of balks committed.
pickoffs : int
- The number of pick offs attempted by the pitcher.
- totalswings : int
+ The number of pick offs attempted.
+ total_swings : int
The number of swings against the pitcher.
- swingandmisses : int
- The number of swing and misses against the pitcher.
- ballsinplay : int
- The number of balls put into play against the pitcher.
- runsupport : int
- The number of run support
- strikepercentage : str
- The strike percentage thown by the pitcher.
- pitchesperinning : str
- The number of pitches per inning
- pitchesperplateappearance : str
- The avg number of pitches per plate appearance of the pitcher.
- walksperplateappearance : str
- The number of walks per plate appearance for the pitcher.
- strikeoutsperplateappearance : str
- The strike outs per plate appearance for the pitcher.
- homerunsperplateappearance : str
- The home runs per plate appearance for the pitcher.
- walksperstrikeout : str
- The walk per strike out ratio of the pitcher
+ swing_and_misses : int
+ The number of swing and misses.
+ balls_in_play : int
+ The number of balls put into play.
+ run_support : int
+ The number of run support.
+ strike_percentage : str
+ The strike percentage thrown.
+ pitches_per_inning : str
+ The number of pitches per inning.
+ pitches_per_plate_appearance : str
+ The avg number of pitches per plate appearance.
+ walks_per_plate_appearance : str
+ The number of walks per plate appearance.
+ strikeouts_per_plate_appearance : str
+ The strike outs per plate appearance.
+ home_runs_per_plate_appearance : str
+ The home runs per plate appearance.
+ walks_per_strikeout : str
+ The walk per strike out ratio.
iso : str
- Isolasted power.
- see also: https://www.mlb.com/glossary/advanced-stats/isolated-power
+ Isolated power.
flyouts : int
- The number of ly outs given up by the pitcher.
+ The number of fly outs given up.
popouts : int
- The number of pop outs given up by the pitcher.
+ The number of pop outs given up.
lineouts : int
- The number of line outs given up by the pitcher.
+ The number of line outs given up.
groundouts : int
- The number of ground outs given up by the pitcher.
- flyhits : int
- The number of fly hits given up by the pitcher.
- pophits : int
- The number of pop hits given up by the pitcher.
- linehits : int
- The number of line hits given up by the pitcher.
- groundhits : int
- The number of ground hits given up by the pitcher.
- inheritedrunners : int
- The number of inherited runners for the pitcher.
- inheritedrunnersscored : int
- The number of inherited runners scored for the pitcher.
- bequeathedrunners : int
+ The number of ground outs given up.
+ fly_hits : int
+ The number of fly hits given up.
+ pop_hits : int
+ The number of pop hits given up.
+ line_hits : int
+ The number of line hits given up.
+ ground_hits : int
+ The number of ground hits given up.
+ inherited_runners : int
+ The number of inherited runners.
+ inherited_runners_scored : int
+ The number of inherited runners scored.
+ bequeathed_runners : int
The number of bequeathed runners.
- see also: https://www.mlb.com/glossary/advanced-stats/bequeathed-runners
- bequeathedrunnersscored : int
+ bequeathed_runners_scored : int
The number of bequeathed runners scored.
- see also: https://www.mlb.com/glossary/advanced-stats/bequeathed-runners
"""
age: Optional[int] = None
- winningpercentage: Optional[str] = None
- runsscoredper9: Optional[str] = None
- battersfaced: Optional[int] = None
+ winning_percentage: Optional[str] = Field(default=None, alias="winningpercentage")
+ runs_scored_per_9: Optional[str] = Field(default=None, alias="runsscoredper9")
+ batters_faced: Optional[int] = Field(default=None, alias="battersfaced")
babip: Optional[str] = None
obp: Optional[str] = None
slg: Optional[str] = None
ops: Optional[str] = None
- strikeoutsper9: Optional[str] = None
- baseonballsper9: Optional[str] = None
- homerunsper9: Optional[str] = None
- hitsper9: Optional[str] = None
- strikesoutstowalks: Optional[str] = None
- stolenbases: Optional[int] = None
- caughtstealing: Optional[int] = None
- qualitystarts: Optional[int] = None
- gamesfinished: Optional[int] = None
+ strikeouts_per_9: Optional[str] = Field(default=None, alias="strikeoutsper9")
+ base_on_balls_per_9: Optional[str] = Field(default=None, alias="baseonballsper9")
+ home_runs_per_9: Optional[str] = Field(default=None, alias="homerunsper9")
+ hits_per_9: Optional[str] = Field(default=None, alias="hitsper9")
+ strikeouts_to_walks: Optional[str] = Field(default=None, alias="strikesoutstowalks")
+ stolen_bases: Optional[int] = Field(default=None, alias="stolenbases")
+ caught_stealing: Optional[int] = Field(default=None, alias="caughtstealing")
+ quality_starts: Optional[int] = Field(default=None, alias="qualitystarts")
+ games_finished: Optional[int] = Field(default=None, alias="gamesfinished")
doubles: Optional[int] = None
triples: Optional[int] = None
gidp: Optional[int] = None
- gidpopp: Optional[int] = None
- wildpitches: Optional[int] = None
+ gidp_opp: Optional[int] = Field(default=None, alias="gidpopp")
+ wild_pitches: Optional[int] = Field(default=None, alias="wildpitches")
balks: Optional[int] = None
pickoffs: Optional[int] = None
- totalswings: Optional[int] = None
- swingandmisses: Optional[int] = None
- strikeoutsminuswalkspercentage: Optional[str] = None
- gidppercentage: Optional[str] = None
- battersfacedpergame: Optional[str] = None
- buntsfailed: Optional[int] = None
- buntsmissedtipped: Optional[int] = None
- whiffpercentage: Optional[int] = None
- ballsinplay: Optional[int] = None
- runsupport: Optional[int] = None
- strikepercentage: Optional[str] = None
- pitchesperinning: Optional[str] = None
- pitchesperplateappearance: Optional[str] = None
- walksperplateappearance: Optional[str] = None
- strikeoutsperplateappearance: Optional[str] = None
- homerunsperplateappearance: Optional[str] = None
- walksperstrikeout: Optional[str] = None
+ total_swings: Optional[int] = Field(default=None, alias="totalswings")
+ swing_and_misses: Optional[int] = Field(default=None, alias="swingandmisses")
+ strikeouts_minus_walks_percentage: Optional[str] = Field(default=None, alias="strikeoutsminuswalkspercentage")
+ gidp_percentage: Optional[str] = Field(default=None, alias="gidppercentage")
+ batters_faced_per_game: Optional[str] = Field(default=None, alias="battersfacedpergame")
+ bunts_failed: Optional[int] = Field(default=None, alias="buntsfailed")
+ bunts_missed_tipped: Optional[int] = Field(default=None, alias="buntsmissedtipped")
+ whiff_percentage: Optional[str] = Field(default=None, alias="whiffpercentage")
+ balls_in_play: Optional[int] = Field(default=None, alias="ballsinplay")
+ run_support: Optional[int] = Field(default=None, alias="runsupport")
+ strike_percentage: Optional[str] = Field(default=None, alias="strikepercentage")
+ pitches_per_inning: Optional[str] = Field(default=None, alias="pitchesperinning")
+ pitches_per_plate_appearance: Optional[str] = Field(default=None, alias="pitchesperplateappearance")
+ walks_per_plate_appearance: Optional[str] = Field(default=None, alias="walksperplateappearance")
+ strikeouts_per_plate_appearance: Optional[str] = Field(default=None, alias="strikeoutsperplateappearance")
+ home_runs_per_plate_appearance: Optional[str] = Field(default=None, alias="homerunsperplateappearance")
+ walks_per_strikeout: Optional[str] = Field(default=None, alias="walksperstrikeout")
iso: Optional[str] = None
flyouts: Optional[int] = None
popouts: Optional[int] = None
lineouts: Optional[int] = None
groundouts: Optional[int] = None
- flyhits: Optional[int] = None
- pophits: Optional[int] = None
- linehits: Optional[int] = None
- groundhits: Optional[int] = None
- inheritedrunners: Optional[int] = None
- inheritedrunnersscored: Optional[int] = None
- bequeathedrunners: Optional[int] = None
- bequeathedrunnersscored: Optional[int] = None
- inningspitchedpergame: Optional[str] = None
- flyballpercentage: Optional[str] = None
-
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
+ fly_hits: Optional[int] = Field(default=None, alias="flyhits")
+ pop_hits: Optional[int] = Field(default=None, alias="pophits")
+ line_hits: Optional[int] = Field(default=None, alias="linehits")
+ ground_hits: Optional[int] = Field(default=None, alias="groundhits")
+ inherited_runners: Optional[int] = Field(default=None, alias="inheritedrunners")
+ inherited_runners_scored: Optional[int] = Field(default=None, alias="inheritedrunnersscored")
+ bequeathed_runners: Optional[int] = Field(default=None, alias="bequeathedrunners")
+ bequeathed_runners_scored: Optional[int] = Field(default=None, alias="bequeathedrunnersscored")
+ innings_pitched_per_game: Optional[str] = Field(default=None, alias="inningspitchedpergame")
+ flyball_percentage: Optional[str] = Field(default=None, alias="flyballpercentage")
-@dataclass(kw_only=True, repr=False)
class PitchingSabermetrics(Split):
"""
- A class to represent a pitching sabermetric statistics
+ A class to represent pitching sabermetric statistics.
Attributes
----------
- fip : float
- Fielding Independent Pitching
- fipminus : float
- Fielding Independent Pitching Minus
- ra9war : float
- Runs Allowed 9 innings Wins Above Replacement
- rar : float
- Runs Above Replacement
- war : float
- Wins Above Replacement
- gametype : str
- the gametype code of the pitching season
- numteams : str
- the number of teams for the pitching season
- """
- _stat = ['sabermetrics']
- stat: Union[Sabermetrics, dict]
-
- def __post_init__(self):
- self.stat = Sabermetrics(**self.stat)
- super().__post_init__()
-
-
-@dataclass(kw_only=True, repr=False)
+ stat : Sabermetrics
+ The sabermetric statistics.
+ """
+ _stat: ClassVar[List[str]] = ['sabermetrics']
+ stat: Sabermetrics
+
+
class PitchingSeason(Split):
"""
- A class to represent a pitching season statistic
+ A class to represent a pitching season statistic.
Attributes
----------
+ stat : SimplePitchingSplit
+ The pitching split stat.
"""
- _stat = ['season', 'statsSingleSeason']
- stat: Union[SimplePitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimplePitchingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['season', 'statsSingleSeason']
+ stat: SimplePitchingSplit
-@dataclass(kw_only=True, repr=False)
class PitchingCareer(Split):
"""
- A class to represent a pitching season statistic
+ A class to represent a pitching career statistic.
Attributes
----------
+ stat : SimplePitchingSplit
+ The pitching split stat.
"""
- _stat = ['career']
- stat: Union[SimplePitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimplePitchingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['career']
+ stat: SimplePitchingSplit
-@dataclass(kw_only=True, repr=False)
class PitchingCareerAdvanced(Split):
"""
- A class to represent a pitching season statistic
+ A class to represent a pitching careerAdvanced statistic.
Attributes
----------
+ stat : AdvancedPitchingSplit
+ The pitching split stat.
"""
- _stat = ['careerAdvanced']
- stat: Union[AdvancedPitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = AdvancedPitchingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['careerAdvanced']
+ stat: AdvancedPitchingSplit
-@dataclass(kw_only=True, repr=False)
class PitchingYearByYear(Split):
"""
- A class to represent a yearByYear season statistic
+ A class to represent a pitching yearByYear statistic.
Attributes
----------
+ stat : SimplePitchingSplit
+ The pitching split stat.
"""
- _stat = ['yearByYear']
- stat: Union[SimplePitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimplePitchingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['yearByYear']
+ stat: SimplePitchingSplit
+
-@dataclass(kw_only=True, repr=False)
class PitchingYearByYearPlayoffs(Split):
"""
- A class to represent a yearByYear season statistic
+ A class to represent a pitching yearByYearPlayoffs statistic.
Attributes
----------
+ stat : SimplePitchingSplit
+ The pitching split stat.
"""
- _stat = ['yearByYearPlayoffs']
- stat: Union[SimplePitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimplePitchingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['yearByYearPlayoffs']
+ stat: SimplePitchingSplit
+
-@dataclass(kw_only=True, repr=False)
class PitchingYearByYearAdvanced(Split):
"""
- A class to represent a pitching yearByYear statistic
+ A class to represent a pitching yearByYearAdvanced statistic.
Attributes
----------
+ stat : AdvancedPitchingSplit
+ The pitching split stat.
"""
- _stat = ['yearByYearAdvanced']
- stat: Union[AdvancedPitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = AdvancedPitchingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['yearByYearAdvanced']
+ stat: AdvancedPitchingSplit
+
-@dataclass(kw_only=True, repr=False)
class PitchingSeasonAdvanced(Split):
"""
- A class to represent a pitching seasonAdvanced statistic
+ A class to represent a pitching seasonAdvanced statistic.
Attributes
----------
+ stat : AdvancedPitchingSplit
+ The pitching split stat.
"""
- _stat = ['seasonAdvanced']
- stat: Union[AdvancedPitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = AdvancedPitchingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['seasonAdvanced']
+ stat: AdvancedPitchingSplit
+
-@dataclass(kw_only=True, repr=False)
class PitchingSingleSeasonAdvanced(Split):
"""
- A class to represent a pitching seasonAdvanced statistic
+ A class to represent a pitching statsSingleSeasonAdvanced statistic.
Attributes
----------
+ stat : AdvancedPitchingSplit
+ The pitching split stat.
"""
- _stat = ['statsSingleSeasonAdvanced']
- stat: Union[AdvancedPitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = AdvancedPitchingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['statsSingleSeasonAdvanced']
+ stat: AdvancedPitchingSplit
+
-@dataclass(kw_only=True, repr=False)
class PitchingGameLog(Split):
"""
- A class to represent a gamelog stat for a pitcher
+ A class to represent a gamelog stat for a pitcher.
Attributes
----------
- ishome : bool
- bool to hold ishome
- iswin : bool
- bool to hold iswin
+ is_home : bool
+ Bool to hold is home.
+ is_win : bool
+ Bool to hold is win.
game : Game
- Game of the log
+ Game of the log.
date : str
- date of the log
- gametype : str
- type of game
+ Date of the log.
opponent : Team
- Team of the opponent
- """
- ishome: bool
- iswin: bool
- game: Union[Game, dict]
+ Team of the opponent.
+ stat : SimplePitchingSplit
+ The pitching split stat.
+ """
+ _stat: ClassVar[List[str]] = ['gameLog']
+ is_home: bool = Field(alias="ishome")
+ is_win: bool = Field(alias="iswin")
+ game: Game
date: str
- opponent: Union[Team, dict]
- _stat = ['gameLog']
- stat: Union[SimplePitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimplePitchingSplit(**self.stat)
- super().__post_init__()
+ opponent: Team
+ stat: SimplePitchingSplit
-@dataclass
-class PitchingPlay:
+
+class PitchingPlay(MLBBaseModel):
"""
- A class to represent a gamelog stat for a hitter
+ A class to represent a play stat for a pitcher.
Attributes
----------
- details : dict
- a dict containing PlayDetails
- count : dict
- a dict containing the pitch Count
- pitchnumber : int
- pitcher number
- atbatnumber : int
- at bat number
- ispitch : bool
- ispitch bool
- playid : str
- A play id
- """
- details: Union[PlayDetails, dict]
- count: Union[Count, dict]
- pitchnumber: int
- atbatnumber: int
- ispitch: bool
- playid: str
-
- def __post_init__(self):
- self.details = PlayDetails(**self.details)
- self.count = Count(**self.count)
-
-@dataclass(kw_only=True, repr=False)
+ details : PlayDetails
+ Play details.
+ count : Count
+ The count.
+ pitch_number : int
+ Pitch number.
+ at_bat_number : int
+ At bat number.
+ is_pitch : bool
+ Is pitch bool.
+ play_id : str
+ Play ID.
+ """
+ details: PlayDetails
+ count: Count
+ pitch_number: int = Field(alias="pitchnumber")
+ at_bat_number: int = Field(alias="atbatnumber")
+ is_pitch: bool = Field(alias="ispitch")
+ play_id: str = Field(alias="playid")
+
+
class PitchingLog(Split):
"""
A class to represent a pitchLog stat for a pitcher.
Attributes
----------
+ stat : PitchingPlay
+ Information regarding the play for the stat.
season : str
- season for the stat
- stat : PlayLog
- information regarding the play for the stat
- team : Team
- team of the stat
- player : Person
- player of the stat
+ Season for the stat.
opponent : Team
- opponent
+ Opponent.
date : str
- date of log
- gametype : str
- game type code
- ishome : bool
- is the game at home bool
- pitcher : Person
- pitcher of the log
- batter : Person
- batter of the log
+ Date of log.
+ is_home : bool
+ Is the game at home bool.
+ pitcher : Pitcher
+ Pitcher of the log.
+ batter : Batter
+ Batter of the log.
game : Game
- the game of the log
-
+ The game of the log.
"""
- _stat = ['pitchLog']
- stat: Union[PitchingPlay, dict]
+ _stat: ClassVar[List[str]] = ['pitchLog']
+ stat: PitchingPlay
season: str
- opponent: Union[Team, dict]
+ opponent: Team
date: str
- ishome: bool
- pitcher: Union[Pitcher, dict]
- batter: Union[Batter, dict]
- game: Union[Game, dict]
+ is_home: bool = Field(alias="ishome")
+ pitcher: Pitcher
+ batter: Batter
+ game: Game
+
+ @field_validator('stat', mode='before')
+ @classmethod
+ def extract_play(cls, v: Any) -> Any:
+ """Extract play from stat dict."""
+ if isinstance(v, dict) and 'play' in v:
+ return v['play']
+ return v
- def __post_init__(self):
- self.stat = PitchingPlay(**self.stat['play'])
- super().__post_init__()
-@dataclass(kw_only=True, repr=False)
class PitchingPlayLog(Split):
"""
A class to represent a playLog stat for a pitcher.
Attributes
----------
+ stat : PitchingPlay
+ Information regarding the play for the stat.
season : str
- season for the stat
- stat : PlayLog
- information regarding the play for the stat
- team : Team
- team of the stat
- player : Person
- player of the stat
+ Season for the stat.
opponent : Team
- opponent
+ Opponent.
date : str
- date of log
- gametype : str
- game type code
- ishome : bool
- is the game at home bool
- pitcher : Person
- pitcher of the log
- batter : Person
- batter of the log
+ Date of log.
+ is_home : bool
+ Is the game at home bool.
+ pitcher : Pitcher
+ Pitcher of the log.
+ batter : Batter
+ Batter of the log.
game : Game
- the game of the log
-
+ The game of the log.
"""
- _stat = ['playLog']
- stat: Union[PitchingPlay, dict]
+ _stat: ClassVar[List[str]] = ['playLog']
+ stat: PitchingPlay
season: str
- opponent: Union[Team, dict]
+ opponent: Team
date: str
- ishome: bool
- pitcher: Union[Pitcher, dict]
- batter: Union[Batter, dict]
- game: Union[Game, dict]
+ is_home: bool = Field(alias="ishome")
+ pitcher: Pitcher
+ batter: Batter
+ game: Game
+
+ @field_validator('stat', mode='before')
+ @classmethod
+ def extract_play(cls, v: Any) -> Any:
+ """Extract play from stat dict."""
+ if isinstance(v, dict) and 'play' in v:
+ return v['play']
+ return v
- def __post_init__(self):
- self.stat = PitchingPlay(**self.stat['play'])
- super().__post_init__()
-@dataclass(kw_only=True, repr=False)
class PitchingByDateRange(Split):
"""
A class to represent a byDateRange stat for a pitcher.
Attributes
----------
- dayofweek : int
+ day_of_week : int
+ The day of the week.
+ stat : SimplePitchingSplit
+ The pitching split stat.
"""
- _stat = ['byDateRange']
- dayofweek: Optional[int] = None
- stat: Union[SimplePitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimplePitchingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['byDateRange']
+ stat: SimplePitchingSplit
+ day_of_week: Optional[int] = Field(default=None, alias="dayofweek")
+
-@dataclass(kw_only=True, repr=False)
class PitchingByDateRangeAdvanced(Split):
"""
A class to represent a byDateRangeAdvanced stat for a pitcher.
Attributes
----------
- dayofweek : int
+ day_of_week : int
+ The day of the week.
+ stat : AdvancedPitchingSplit
+ The pitching split stat.
"""
- _stat = ['byDateRangeAdvanced']
- dayofweek: Optional[int] = None
- stat: Union[AdvancedPitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = AdvancedPitchingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['byDateRangeAdvanced']
+ stat: AdvancedPitchingSplit
+ day_of_week: Optional[int] = Field(default=None, alias="dayofweek")
+
-@dataclass(kw_only=True, repr=False)
class PitchingByMonth(Split):
"""
A class to represent a byMonth stat for a pitcher.
@@ -746,16 +669,15 @@ class PitchingByMonth(Split):
Attributes
----------
month : int
+ The month.
+ stat : SimplePitchingSplit
+ The pitching split stat.
"""
- _stat = ['byMonth']
+ _stat: ClassVar[List[str]] = ['byMonth']
month: int
- stat: Union[SimplePitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimplePitchingSplit(**self.stat)
- super().__post_init__()
+ stat: SimplePitchingSplit
+
-@dataclass(kw_only=True, repr=False)
class PitchingByMonthPlayoffs(Split):
"""
A class to represent a byMonthPlayoffs stat for a pitcher.
@@ -763,134 +685,127 @@ class PitchingByMonthPlayoffs(Split):
Attributes
----------
month : int
+ The month.
+ stat : SimplePitchingSplit
+ The pitching split stat.
"""
- _stat = ['byMonthPlayoffs']
+ _stat: ClassVar[List[str]] = ['byMonthPlayoffs']
month: int
- stat: Union[SimplePitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimplePitchingSplit(**self.stat)
- super().__post_init__()
+ stat: SimplePitchingSplit
+
-@dataclass(kw_only=True, repr=False)
class PitchingByDayOfWeek(Split):
"""
A class to represent a byDayOfWeek stat for a pitcher.
Attributes
----------
- dayofweek : int
+ day_of_week : int
+ The day of the week.
+ stat : SimplePitchingSplit
+ The pitching split stat.
"""
- _stat = ['byDayOfWeek']
- dayofweek: Optional[int] = None
- stat: Union[SimplePitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimplePitchingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['byDayOfWeek']
+ stat: SimplePitchingSplit
+ day_of_week: Optional[int] = Field(default=None, alias="dayofweek")
+
-@dataclass(kw_only=True, repr=False)
class PitchingByDayOfWeekPlayOffs(Split):
"""
A class to represent a byDayOfWeekPlayoffs stat for a pitcher.
Attributes
----------
- dayofweek : int
+ day_of_week : int
+ The day of the week.
+ stat : SimplePitchingSplit
+ The pitching split stat.
"""
- _stat = ['byDayOfWeekPlayoffs']
- dayofweek: Optional[int] = None
- stat: Union[SimplePitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimplePitchingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['byDayOfWeekPlayoffs']
+ stat: SimplePitchingSplit
+ day_of_week: Optional[int] = Field(default=None, alias="dayofweek")
+
-@dataclass(kw_only=True, repr=False)
class PitchingHomeAndAway(Split):
"""
A class to represent a homeAndAway stat for a pitcher.
Attributes
----------
- ishome : bool
+ is_home : bool
+ Is home bool.
+ stat : SimplePitchingSplit
+ The pitching split stat.
"""
- _stat = ['homeAndAway']
- ishome: bool
- stat: Union[SimplePitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimplePitchingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['homeAndAway']
+ is_home: bool = Field(alias="ishome")
+ stat: SimplePitchingSplit
+
-@dataclass(kw_only=True, repr=False)
class PitchingHomeAndAwayPlayoffs(Split):
"""
A class to represent a homeAndAwayPlayoffs stat for a pitcher.
Attributes
----------
- ishome : bool
+ is_home : bool
+ Is home bool.
+ stat : SimplePitchingSplit
+ The pitching split stat.
"""
- _stat = ['homeAndAwayPlayoffs']
- ishome: bool
- stat: Union[SimplePitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimplePitchingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['homeAndAwayPlayoffs']
+ is_home: bool = Field(alias="ishome")
+ stat: SimplePitchingSplit
+
-@dataclass(kw_only=True, repr=False)
class PitchingWinLoss(Split):
"""
A class to represent a winLoss stat for a pitcher.
Attributes
----------
- iswin : bool
+ is_win : bool
+ Is win bool.
+ stat : SimplePitchingSplit
+ The pitching split stat.
"""
- _stat = ['winLoss']
- iswin: bool
- stat: Union[SimplePitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimplePitchingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['winLoss']
+ is_win: bool = Field(alias="iswin")
+ stat: SimplePitchingSplit
+
-@dataclass(kw_only=True, repr=False)
class PitchingWinLossPlayoffs(Split):
"""
A class to represent a winLossPlayoffs stat for a pitcher.
Attributes
----------
- iswin : bool
+ is_win : bool
+ Is win bool.
+ stat : SimplePitchingSplit
+ The pitching split stat.
"""
- _stat = ['winLossPlayoffs']
- iswin: bool
- stat: Union[SimplePitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimplePitchingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['winLossPlayoffs']
+ is_win: bool = Field(alias="iswin")
+ stat: SimplePitchingSplit
+
-@dataclass(kw_only=True, repr=False)
class PitchingRankings(Split):
"""
A class to represent a rankingsByYear stat for a pitcher.
Attributes
----------
+ outs_pitched : int
+ Outs pitched.
+ stat : SimplePitchingSplit
+ The pitching split stat.
"""
- _stat = ['rankingsByYear']
- outspitched: Optional[int] = None
- stat: Union[SimplePitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimplePitchingSplit(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['rankingsByYear']
+ stat: SimplePitchingSplit
+ outs_pitched: Optional[int] = Field(default=None, alias="outspitched")
+
-@dataclass(kw_only=True, repr=False)
class PitchingOpponentsFaced(Split):
"""
A class to represent an opponentsFaced stat for a pitcher.
@@ -898,178 +813,216 @@ class PitchingOpponentsFaced(Split):
Attributes
----------
group : str
- pitch : Person
- batter : Person
- battingteam : Team
- """
- _stat = ['opponentsFaced']
+ The stat group.
+ pitcher : Pitcher
+ The pitcher.
+ batter : Batter
+ The batter.
+ batting_team : Team
+ The batting team.
+ """
+ _stat: ClassVar[List[str]] = ['opponentsFaced']
group: str
- pitcher: Union[Pitcher, dict]
- batter: Union[Batter, dict]
- battingteam: Union[Team, dict]
+ pitcher: Pitcher
+ batter: Batter
+ batting_team: Team = Field(alias="battingteam")
- def __post_init__(self):
- self.pitcher = Pitcher(**self.pitcher) if self.pitcher else self.pitcher
- self.batter = Batter(**self.batter) if self.batter else self.batter
- self.battingteam = Team(**self.battingteam) if self.battingteam else self.battingteam
- super().__post_init__()
-@dataclass(kw_only=True, repr=False)
class PitchingExpectedStatistics(Split):
"""
A class to represent an expectedStatistics stat for a pitcher.
Attributes
----------
- avg : str
- slg : str
- woba : str
- wobaCon : str
- rank : int
+ stat : ExpectedStatistics
+ The expected statistics.
"""
- _stat = ['expectedStatistics']
- stat: Union[ExpectedStatistics, dict]
-
- def __post_init__(self):
- self.stat = ExpectedStatistics(**self.stat)
- super().__post_init__()
+ _stat: ClassVar[List[str]] = ['expectedStatistics']
+ stat: ExpectedStatistics
-
-@dataclass(kw_only=True, repr=False)
class PitchingVsPlayer5Y(Split):
"""
- A class to represent a vsPlayer5Y pitching statistic
+ A class to represent a vsPlayer5Y pitching statistic.
- requires the use of opposingTeamId params
+ Requires the use of opposingPlayerId params.
Attributes
----------
- """
- _stat = ['vsPlayer5Y']
- opponent: Union[Team, dict]
- batter: Optional[Union[Batter, dict]] = field(default_factory=dict)
- pitcher: Optional[Union[Pitcher, dict]] = field(default_factory=dict)
- stat: Union[SimplePitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimplePitchingSplit(**self.stat)
- self.pitcher = Pitcher(**self.pitcher) if self.pitcher else self.pitcher
- self.batter = Batter(**self.batter) if self.batter else self.batter
- self.opponent = Team(**self.opponent) if self.opponent else self.opponent
- super().__post_init__()
-
-
-@dataclass(kw_only=True, repr=False)
+ opponent : Team
+ The opponent team.
+ batter : Batter
+ The batter.
+ pitcher : Pitcher
+ The pitcher.
+ stat : SimplePitchingSplit
+ The pitching split stat.
+ """
+ _stat: ClassVar[List[str]] = ['vsPlayer5Y']
+ opponent: Team
+ stat: SimplePitchingSplit
+ batter: Optional[Batter] = None
+ pitcher: Optional[Pitcher] = None
+
+ @field_validator('batter', 'pitcher', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
+
+
class PitchingVsPlayer(Split):
"""
- A class to represent a vsPlayer pitching statistic
+ A class to represent a vsPlayer pitching statistic.
- requires the use of opposingTeamId params
+ Requires the use of opposingPlayerId params.
Attributes
----------
- """
- _stat = ['vsPlayer']
- opponent: Union[Team, dict]
- batter: Optional[Union[Batter, dict]] = field(default_factory=dict)
- pitcher: Optional[Union[Pitcher, dict]] = field(default_factory=dict)
- stat: Union[SimplePitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimplePitchingSplit(**self.stat)
- self.pitcher = Pitcher(**self.pitcher) if self.pitcher else self.pitcher
- self.batter = Batter(**self.batter) if self.batter else self.batter
- self.opponent = Team(**self.opponent) if self.opponent else self.opponent
- super().__post_init__()
-
-
-@dataclass(kw_only=True, repr=False)
+ opponent : Team
+ The opponent team.
+ batter : Batter
+ The batter.
+ pitcher : Pitcher
+ The pitcher.
+ stat : SimplePitchingSplit
+ The pitching split stat.
+ """
+ _stat: ClassVar[List[str]] = ['vsPlayer']
+ opponent: Team
+ stat: SimplePitchingSplit
+ batter: Optional[Batter] = None
+ pitcher: Optional[Pitcher] = None
+
+ @field_validator('batter', 'pitcher', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
+
+
class PitchingVsPlayerTotal(Split):
"""
- A class to represent a vsPlayerTotal pitching statistic
+ A class to represent a vsPlayerTotal pitching statistic.
- requires the use of opposingTeamId params
+ Requires the use of opposingPlayerId params.
Attributes
----------
- """
- _stat = ['vsPlayerTotal']
- opponent: Optional[Union[Team, dict]] = field(default_factory=dict)
- batter: Optional[Union[Batter, dict]] = field(default_factory=dict)
- pitcher: Optional[Union[Pitcher, dict]] = field(default_factory=dict)
- stat: Union[SimplePitchingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimplePitchingSplit(**self.stat)
- self.pitcher = Pitcher(**self.pitcher) if self.pitcher else self.pitcher
- self.batter = Batter(**self.batter) if self.batter else self.batter
- self.opponent = Team(**self.opponent) if self.opponent else self.opponent
- super().__post_init__()
+ opponent : Team
+ The opponent team.
+ batter : Batter
+ The batter.
+ pitcher : Pitcher
+ The pitcher.
+ stat : SimplePitchingSplit
+ The pitching split stat.
+ """
+ _stat: ClassVar[List[str]] = ['vsPlayerTotal']
+ stat: SimplePitchingSplit
+ opponent: Optional[Team] = None
+ batter: Optional[Batter] = None
+ pitcher: Optional[Pitcher] = None
+
+ @field_validator('opponent', 'batter', 'pitcher', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
# These stat_types return a hitting stat for a pitching stat group
-# odd, but need to deal with it.
-@dataclass(kw_only=True, repr=False)
class PitchingVsTeam(Split):
"""
- A class to represent a vsTeam pitching statistic
+ A class to represent a vsTeam pitching statistic.
Attributes
----------
- """
- _stat = ['vsTeam']
- opponent: Union[Team, dict]
- batter: Optional[Union[Batter, dict]] = field(default_factory=dict)
- pitcher: Optional[Union[Pitcher, dict]] = field(default_factory=dict)
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.pitcher = Pitcher(**self.pitcher) if self.pitcher else self.pitcher
- self.batter = Batter(**self.batter) if self.batter else self.batter
- self.opponent = Team(**self.opponent) if self.opponent else self.opponent
- self.stat = SimpleHittingSplit(**self.stat)
- super().__post_init__()
-
-
-@dataclass(kw_only=True, repr=False)
+ opponent : Team
+ The opponent team.
+ batter : Batter
+ The batter.
+ pitcher : Pitcher
+ The pitcher.
+ stat : SimpleHittingSplit
+ The hitting split stat.
+ """
+ _stat: ClassVar[List[str]] = ['vsTeam']
+ opponent: Team
+ stat: SimpleHittingSplit
+ batter: Optional[Batter] = None
+ pitcher: Optional[Pitcher] = None
+
+ @field_validator('batter', 'pitcher', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
+
+
class PitchingVsTeamTotal(Split):
"""
- A class to represent a vsTeamTotal pitching statistic
+ A class to represent a vsTeamTotal pitching statistic.
Attributes
----------
- """
- _stat = ['vsTeamTotal']
- opponent: Union[Team, dict]
- batter: Optional[Union[Batter, dict]] = field(default_factory=dict)
- pitcher: Optional[Union[Pitcher, dict]] = field(default_factory=dict)
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- self.pitcher = Pitcher(**self.pitcher) if self.pitcher else self.pitcher
- self.batter = Batter(**self.batter) if self.batter else self.batter
- self.opponent = Team(**self.opponent) if self.opponent else self.opponent
- super().__post_init__()
-
-@dataclass(kw_only=True, repr=False)
+ opponent : Team
+ The opponent team.
+ batter : Batter
+ The batter.
+ pitcher : Pitcher
+ The pitcher.
+ stat : SimpleHittingSplit
+ The hitting split stat.
+ """
+ _stat: ClassVar[List[str]] = ['vsTeamTotal']
+ opponent: Team
+ stat: SimpleHittingSplit
+ batter: Optional[Batter] = None
+ pitcher: Optional[Pitcher] = None
+
+ @field_validator('batter', 'pitcher', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
+
+
class PitchingVsTeam5Y(Split):
"""
- A class to represent a vsTeam5Y pitching statistic
+ A class to represent a vsTeam5Y pitching statistic.
Attributes
----------
- """
- _stat = ['vsTeam5Y']
- opponent: Union[Team, dict]
- batter: Optional[Union[Batter, dict]] = field(default_factory=dict)
- pitcher: Optional[Union[Pitcher, dict]] = field(default_factory=dict)
- stat: Union[SimpleHittingSplit, dict]
-
- def __post_init__(self):
- self.stat = SimpleHittingSplit(**self.stat)
- self.pitcher = Pitcher(**self.pitcher) if self.pitcher else self.pitcher
- self.batter = Batter(**self.batter) if self.batter else self.batter
- self.opponent = Team(**self.opponent) if self.opponent else self.opponent
- super().__post_init__()
+ opponent : Team
+ The opponent team.
+ batter : Batter
+ The batter.
+ pitcher : Pitcher
+ The pitcher.
+ stat : SimpleHittingSplit
+ The hitting split stat.
+ """
+ _stat: ClassVar[List[str]] = ['vsTeam5Y']
+ opponent: Team
+ stat: SimpleHittingSplit
+ batter: Optional[Batter] = None
+ pitcher: Optional[Pitcher] = None
+
+ @field_validator('batter', 'pitcher', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
diff --git a/mlbstatsapi/models/stats/running.py b/mlbstatsapi/models/stats/running.py
index 261e4035..6a9685eb 100644
--- a/mlbstatsapi/models/stats/running.py
+++ b/mlbstatsapi/models/stats/running.py
@@ -1,29 +1,22 @@
-from dataclasses import dataclass, field
-from typing import Optional, Union, List
-
+from typing import List, ClassVar
from mlbstatsapi.models.people import Batter, Pitcher
-
from .stats import Stat
-@dataclass(kw_only=True)
+
class RunningOpponentsFaced(Stat):
"""
- A class to represent a running opponentsFaced statistic
+ A class to represent a running opponentsFaced statistic.
Attributes
----------
batter : Batter
- The batter of the stat
+ The batter of the stat.
group : str
- The stat group of the stat
+ The stat group of the stat.
pitcher : Pitcher
- The pitcher of the stat
+ The pitcher of the stat.
"""
- _stat = ['opponentsFaced']
- batter: Union[Batter, dict]
- group: str
- pitcher: Union[Pitcher, dict]
-
- def __post_init__(self):
- self.batter = Batter(**self.batter) if self.batter else self.batter
- self.pitcher = Pitcher(**self.pitcher) if self.batter else self.batter
\ No newline at end of file
+ _stat: ClassVar[List[str]] = ['opponentsFaced']
+ batter: Batter
+ group: str
+ pitcher: Pitcher
diff --git a/mlbstatsapi/models/stats/stats.py b/mlbstatsapi/models/stats/stats.py
index 9403dd83..56b5bd41 100644
--- a/mlbstatsapi/models/stats/stats.py
+++ b/mlbstatsapi/models/stats/stats.py
@@ -1,310 +1,338 @@
-from dataclasses import dataclass, field
-from typing import Optional, Union, List
-
+from typing import Optional, List, Any, ClassVar
+from pydantic import Field, field_validator
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.teams import Team
from mlbstatsapi.models.people import Person, Batter, Position
from mlbstatsapi.models.sports import Sport
from mlbstatsapi.models.leagues import League
from mlbstatsapi.models.data import CodeDesc
-@dataclass
-class PitchArsenalSplit:
+
+class PitchArsenalSplit(MLBBaseModel):
"""
- A class to represent a pitching pitch arsenal split
+ A class to represent a pitching pitch arsenal split.
Attributes
----------
percentage : float
+ Percentage of this pitch type.
count : int
- totalPitches : int
- averageSpeed : float
- type : Union[CodeDesc, dict]
+ Count of this pitch type.
+ total_pitches : int
+ Total pitches thrown.
+ average_speed : float
+ Average speed of this pitch type.
+ type : CodeDesc
+ The pitch type code and description.
"""
percentage: float
count: int
- totalpitches: int
- averagespeed: float
- type: Union[CodeDesc, dict]
+ total_pitches: int = Field(alias="totalpitches")
+ average_speed: float = Field(alias="averagespeed")
+ type: CodeDesc
+
-@dataclass
-class ExpectedStatistics:
+class ExpectedStatistics(MLBBaseModel):
"""
- a class to hold a code and a description
+ A class to hold expected statistics.
Attributes
----------
+ avg : str
+ Expected batting average.
+ slg : str
+ Expected slugging.
+ woba : str
+ Expected wOBA.
+ wobacon : str
+ Expected wOBA on contact.
"""
avg: str
slg: str
woba: str
wobacon: str
-@dataclass(repr=False)
-class Sabermetrics:
+
+class Sabermetrics(MLBBaseModel):
"""
- a class to hold a code and a description
+ A class to hold sabermetric statistics.
Attributes
----------
woba : float
- wRaa : float
- wRc : float
- wRcPlus : float
+ Weighted on-base average.
+ wraa : float
+ Weighted runs above average.
+ wrc : float
+ Weighted runs created.
+ wrc_plus : float
+ Weighted runs created plus.
rar : float
+ Runs above replacement.
war : float
+ Wins above replacement.
batting : float
+ Batting runs.
fielding : float
- baseRunning : float
+ Fielding runs.
+ base_running : float
+ Base running runs.
positional : float
- wLeague : float
+ Positional adjustment.
+ w_league : float
+ League adjustment.
replacement : float
+ Replacement level runs.
spd : float
+ Speed score.
ubr : float
- wGdp : float
- wSb : float
+ Ultimate base running.
+ w_gdp : float
+ Weighted grounded into double play runs.
+ w_sb : float
+ Weighted stolen base runs.
"""
-
woba: Optional[float] = None
wraa: Optional[float] = None
wrc: Optional[float] = None
- wrcplus: Optional[float] = None
+ wrc_plus: Optional[float] = Field(default=None, alias="wrcplus")
rar: Optional[float] = None
war: Optional[float] = None
batting: Optional[float] = None
fielding: Optional[float] = None
- baserunning: Optional[float] = None
+ base_running: Optional[float] = Field(default=None, alias="baserunning")
positional: Optional[float] = None
- wleague: Optional[float] = None
+ w_league: Optional[float] = Field(default=None, alias="wleague")
replacement: Optional[float] = None
spd: Optional[float] = None
ubr: Optional[float] = None
- wgdp: Optional[float] = None
- wsb: Optional[float] = None
+ w_gdp: Optional[float] = Field(default=None, alias="wgdp")
+ w_sb: Optional[float] = Field(default=None, alias="wsb")
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-
-@dataclass(kw_only=True, repr=False)
-class Split:
+class Split(MLBBaseModel):
"""
- Base class for splits
+ Base class for splits.
Attributes
----------
season : str
- numteams : int
- numleagues : int
- gametype : str
+ The season.
+ num_teams : int
+ Number of teams.
+ num_leagues : int
+ Number of leagues.
+ game_type : str
+ The game type.
rank : int
+ The rank.
position : Position
+ The position.
team : Team
+ The team.
player : Person
+ The player.
sport : Sport
+ The sport.
league : League
+ The league.
"""
season: Optional[str] = None
- numteams: Optional[int] = None
- numleagues: Optional[int] = None
- gametype: Optional[str] = None
+ num_teams: Optional[int] = Field(default=None, alias="numteams")
+ num_leagues: Optional[int] = Field(default=None, alias="numleagues")
+ game_type: Optional[str] = Field(default=None, alias="gametype")
rank: Optional[int] = None
- position: Optional[Union[Position, dict]] = field(default_factory=dict)
- team: Optional[Union[Team, dict]] = field(default_factory=dict)
- player: Optional[Union[Person, dict]] = field(default_factory=dict)
- sport: Optional[Union[Sport, dict]] = field(default_factory=dict)
- league: Optional[Union[League, dict]] = field(default_factory=dict)
-
- def __post_init__(self):
- self.position = Position(**self.position) if self.position else self.position
- self.team = Team(**self.team) if self.team else self.team
- self.sport = Sport(**self.sport) if self.sport else self.sport
- self.league = League(**self.league) if self.league else self.league
- self.player = Person(**self.player) if self.player else self.player
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-
-
-@dataclass(kw_only=True, repr=False)
-class Stat:
+ position: Optional[Position] = None
+ team: Optional[Team] = None
+ player: Optional[Person] = None
+ sport: Optional[Sport] = None
+ league: Optional[League] = None
+
+ @field_validator('position', 'team', 'player', 'sport', 'league', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
+
+
+class Stat(MLBBaseModel):
"""
- Base class for stats
+ Base class for stats.
Attributes
----------
group : str
- type of the stat group
+ Type of the stat group.
type : str
- type of the stat
- totalsplits : int
- The number of split objects
+ Type of the stat.
+ total_splits : int
+ The number of split objects.
exemptions : list
- not sure what this is
+ Exemptions list.
splits : list
- a list of split objects
+ A list of split objects.
"""
group: str
type: str
- totalsplits: int
- exemptions: Optional[List] = field(default_factory=list)
- splits: Optional[List] = field(default_factory=list)
+ total_splits: int = Field(alias="totalsplits")
+ exemptions: Optional[List] = []
+ splits: Optional[List] = []
- def __repr__(self):
- return f'Stat(group={self.group}, type={self.type})'
-@dataclass(kw_only=True)
class PitchArsenal(Split):
"""
- A class to represent a pitcharsenal stat for a hitter and pitcher
+ A class to represent a pitcharsenal stat for a hitter and pitcher.
Attributes
----------
+ stat : PitchArsenalSplit
+ The pitch arsenal statistics.
"""
- _stat = ['pitchArsenal']
- stat: Union[PitchArsenalSplit, dict]
-
- def __post_init__(self):
- self.stat = PitchArsenalSplit(**self.stat)
+ _stat: ClassVar[List[str]] = ['pitchArsenal']
+ stat: PitchArsenalSplit
-@dataclass(kw_only=True)
-class ZoneCodes:
+class ZoneCodes(MLBBaseModel):
"""
- A class to represent a zone code statistic used in hot cold zones
+ A class to represent a zone code statistic used in hot cold zones.
Attributes
----------
zone : str
- zone code location
+ Zone code location.
color : str
- rgba code for the color of zone
+ RGBA code for the color of zone.
temp : str
- temp description of the zone
+ Temperature description of the zone.
value : str
- batting percentage of the zone
+ Batting percentage of the zone.
"""
zone: str
value: str
color: Optional[str] = None
temp: Optional[str] = None
-@dataclass(kw_only=True)
-class Zones:
+
+class Zones(MLBBaseModel):
"""
- A class to represent a hot cold zone statistic
+ A class to represent a hot cold zone statistic.
Attributes
----------
name : str
- name of the hot cold zone
+ Name of the hot cold zone.
zones : List[ZoneCodes]
- a list of zone codes to describe the zone
+ A list of zone codes to describe the zone.
"""
name: str
- zones: List[ZoneCodes]
+ zones: List[ZoneCodes] = []
- def __post_init__(self):
- self.zones = [ZoneCodes(**zone) for zone in self.zones]
-@dataclass(kw_only=True)
class HotColdZones(Split):
"""
- A class to represent a hotcoldzone statistic
+ A class to represent a hotcoldzone statistic.
Attributes
----------
stat : Zones
- the holdcoldzones for the stat
+ The hot cold zones for the stat.
"""
+ _stat: ClassVar[List[str]] = ['hotColdZones']
stat: Zones
- _stat = ['hotColdZones']
- def __post_init__(self):
- self.stat = Zones(**self.stat)
-@dataclass
-class Chart:
+class Chart(MLBBaseModel):
"""
- A class to represent a chart for SprayCharts
+ A class to represent a chart for SprayCharts.
Attributes
----------
- leftfield : int
- percentage
- leftcenterfield : int
- percentage
- centerfield : int
- percentage
- rightcenterfield : int
- percentage
- rightfield : int
- percentage
+ left_field : int
+ Left field percentage.
+ left_center_field : int
+ Left center field percentage.
+ center_field : int
+ Center field percentage.
+ right_center_field : int
+ Right center field percentage.
+ right_field : int
+ Right field percentage.
"""
- leftfield: int
- leftcenterfield: int
- centerfield: int
- rightcenterfield: int
- rightfield: int
+ left_field: int = Field(alias="leftfield")
+ left_center_field: int = Field(alias="leftcenterfield")
+ center_field: int = Field(alias="centerfield")
+ right_center_field: int = Field(alias="rightcenterfield")
+ right_field: int = Field(alias="rightfield")
+
-@dataclass(kw_only=True)
class SprayCharts(Split):
+ """
+ A class to represent spray chart statistics.
+ Attributes
+ ----------
+ stat : Chart
+ The spray chart data.
+ batter : Batter
+ The batter.
+ """
+ _stat: ClassVar[List[str]] = ['sprayChart']
+ stat: Chart
+ batter: Optional[Batter] = None
- _stat = ['sprayChart']
- stat: Union[Chart, dict]
- batter: Optional[Union[Batter, dict]] = field(default_factory=dict)
+ @field_validator('batter', mode='before')
+ @classmethod
+ def empty_dict_to_none(cls, v: Any) -> Any:
+ """Convert empty dicts to None."""
+ if isinstance(v, dict) and not v:
+ return None
+ return v
- def __post_init__(self):
- self.batter = Batter(**self.batter) if self.batter else self.batter
- self.stat = Chart(**self.stat)
-@dataclass(kw_only=True)
class OutsAboveAverage(Split):
"""
- A class to represent a outs above average statistic
+ A class to represent an outs above average statistic.
- NOTE: This stat type returns a empty list, or keys with with the value 0
+ NOTE: This stat type returns an empty list, or keys with the value 0.
"""
- _stat = ['outsAboveAverage']
+ _stat: ClassVar[List[str]] = ['outsAboveAverage']
attempts: int
- totaloutsaboveaverageback: int
- totaloutsaboveaveragebackunrounded: int
- outsaboveaveragebackstraight: int
- outsaboveaveragebackstraightunrounded: int
- outsaboveaveragebackleft: int
- outsaboveaveragebackleftunrounded: int
- outsaboveaveragebackright: int
- outsaboveaveragebackrightunrounded: int
- totaloutsaboveaveragein: int
- totaloutsaboveaverageinunrounded: int
- outsaboveaverageinstraight: int
- outsaboveaverageinstraightunrounded: int
- outsaboveaverageinleft: int
- outsaboveaverageinleftunrounded: int
- outsaboveaverageinright: int
- outsaboveaverageinrightunrounded: int
- player: Union[Person, dict]
- gametype: str
-
-
-#
-# These dataclasses are for the game stats end point only
-# url: https://statsapi.mlb.com/api/v1/people/663728/stats/game/715757
-# The gamelog stats in this JSON have different keys set for their stat
-# and group. This breaks my logic of handling stat classes
-#
-
-@dataclass
+ total_outs_above_average_back: int = Field(alias="totaloutsaboveaverageback")
+ total_outs_above_average_back_unrounded: int = Field(alias="totaloutsaboveaveragebackunrounded")
+ outs_above_average_back_straight: int = Field(alias="outsaboveaveragebackstraight")
+ outs_above_average_back_straight_unrounded: int = Field(alias="outsaboveaveragebackstraightunrounded")
+ outs_above_average_back_left: int = Field(alias="outsaboveaveragebackleft")
+ outs_above_average_back_left_unrounded: int = Field(alias="outsaboveaveragebackleftunrounded")
+ outs_above_average_back_right: int = Field(alias="outsaboveaveragebackright")
+ outs_above_average_back_right_unrounded: int = Field(alias="outsaboveaveragebackrightunrounded")
+ total_outs_above_average_in: int = Field(alias="totaloutsaboveaveragein")
+ total_outs_above_average_in_unrounded: int = Field(alias="totaloutsaboveaverageinunrounded")
+ outs_above_average_in_straight: int = Field(alias="outsaboveaverageinstraight")
+ outs_above_average_in_straight_unrounded: int = Field(alias="outsaboveaverageinstraightunrounded")
+ outs_above_average_in_left: int = Field(alias="outsaboveaverageinleft")
+ outs_above_average_in_left_unrounded: int = Field(alias="outsaboveaverageinleftunrounded")
+ outs_above_average_in_right: int = Field(alias="outsaboveaverageinright")
+ outs_above_average_in_right_unrounded: int = Field(alias="outsaboveaverageinrightunrounded")
+ player: Person
+ game_type: str = Field(alias="gametype")
+
+
class PlayerGameLogStat(Split):
"""
- A class to represent a chart for SprayCharts
+ A class to represent a player game log stat.
Attributes
----------
+ type : str
+ The stat type.
+ group : str
+ The stat group.
+ stat : dict
+ The stat data.
"""
+ _stat: ClassVar[List[str]] = ['gameLog']
type: str
group: str
stat: dict
- _stat = ['gameLog']
diff --git a/mlbstatsapi/models/stats/streak.py b/mlbstatsapi/models/stats/streak.py
index 38fbb072..72974a05 100644
--- a/mlbstatsapi/models/stats/streak.py
+++ b/mlbstatsapi/models/stats/streak.py
@@ -1,4 +1,3 @@
-from dataclasses import dataclass, field
-from typing import Optional, Union
-
-from .stats import Splits
\ No newline at end of file
+# Streak module - placeholder for future implementation
+# Original file imported from .stats import Splits which doesn't exist
+# This file is kept for backwards compatibility
diff --git a/mlbstatsapi/models/teams/__init__.py b/mlbstatsapi/models/teams/__init__.py
index 091851d1..a841fca9 100644
--- a/mlbstatsapi/models/teams/__init__.py
+++ b/mlbstatsapi/models/teams/__init__.py
@@ -1,2 +1,10 @@
from .team import Team
-from .attributes import TeamRecord
\ No newline at end of file
+from .attributes import (
+ Record,
+ OverallLeagueRecord,
+ TypeRecords,
+ DivisionRecords,
+ LeagueRecords,
+ Records,
+ TeamRecord,
+)
\ No newline at end of file
diff --git a/mlbstatsapi/models/teams/attributes.py b/mlbstatsapi/models/teams/attributes.py
index 4bd92ca7..81307666 100644
--- a/mlbstatsapi/models/teams/attributes.py
+++ b/mlbstatsapi/models/teams/attributes.py
@@ -1,185 +1,167 @@
-from typing import Union, Optional, List
-from dataclasses import dataclass
-
+from typing import Optional, List
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.divisions import Division
from mlbstatsapi.models.leagues import League
-@dataclass
-class Record:
+
+class Record(MLBBaseModel):
"""
- Record
+ A class to represent a basic record.
- Attributes:
- ___________
+ Attributes
+ ----------
wins : int
- Number of wins
+ Number of wins.
losses : int
- Number of losses
+ Number of losses.
pct : str
- Percentage
+ Winning percentage.
"""
wins: int
losses: int
pct: str
-@dataclass
-class OverallleagueRecord(Record):
+
+class OverallLeagueRecord(Record):
"""
- Overall League Record
-
+ A class to represent overall league record.
- Attributes:
- ___________
+ Attributes
+ ----------
wins : int
- Overall number of wins in league
+ Overall number of wins in league.
losses : int
- Overall number of losses in league
+ Overall number of losses in league.
pct : str
- Overall percentage in league
+ Overall percentage in league.
+ ties : int
+ Number of ties.
"""
ties: int
-@dataclass
-class Typerecords(Record):
+
+class TypeRecords(Record):
"""
- Type records
+ A class to represent type records.
- Attributes:
- ___________
+ Attributes
+ ----------
wins : int
- Number of wins in type
+ Number of wins in type.
losses : int
- Number of losses in type
+ Number of losses in type.
pct : str
- Percentage in type
+ Percentage in type.
type : str
- Type of record
+ Type of record.
"""
type: str
-@dataclass
-class Divisionrecords(Record):
+
+class DivisionRecords(Record):
"""
- Division records
+ A class to represent division records.
- Attributes:
- ___________
+ Attributes
+ ----------
wins : int
- Number of wins in division
+ Number of wins in division.
losses : int
- Number of losses in division
+ Number of losses in division.
pct : str
- Percentage in division
- division : Divison
- Division
+ Percentage in division.
+ division : Division
+ Division.
"""
- division: Union[Division, dict]
+ division: Division
-@dataclass
-class Leaguerecords(Record):
+
+class LeagueRecords(Record):
"""
- League records
+ A class to represent league records.
- Attributes:
- ___________
+ Attributes
+ ----------
wins : int
- Number of wins in league
+ Number of wins in league.
losses : int
- Number of losses in league
+ Number of losses in league.
pct : str
- Percentage in league
+ Percentage in league.
league : League
- League
+ League.
"""
- league: Union[League, dict]
+ league: League
+
-@dataclass
-class Records:
- """"
+class Records(MLBBaseModel):
+ """
A class representing the records of a team.
- Attributes:
- ___________
- splitrecords : Typerecords
- A list of split records
- divisionrecords : Divisionrecords
- A list of division records
- overallrecords : Typerecords
- A list of overall records
- leaguerecords : Leaguerecords
- A list of league records
- expectedrecords : Typerecords
- A list of expected records
+ Attributes
+ ----------
+ split_records : List[TypeRecords]
+ A list of split records.
+ division_records : List[DivisionRecords]
+ A list of division records.
+ overall_records : List[TypeRecords]
+ A list of overall records.
+ league_records : List[LeagueRecords]
+ A list of league records.
+ expected_records : List[TypeRecords]
+ A list of expected records.
"""
- splitrecords: Optional[List[Union[Typerecords, dict]]] = None
- divisionrecords: Optional[List[Union[Divisionrecords, dict]]] = None
- overallrecords: Optional[List[Union[Typerecords, dict]]] = None
- leaguerecords: Optional[List[Union[Leaguerecords, dict]]] = None
- expectedrecords: Optional[List[Union[Typerecords, dict]]] = None
-
- def __post_init__(self):
- self.splitrecords = [Typerecords(**splitrecord) for splitrecord in self.splitrecords] if self.splitrecords else None
- self.divisionrecords = [Divisionrecords(**divisionrecord) for divisionrecord in self.divisionrecords] if self.divisionrecords else None
- self.overallrecords = [Typerecords(**overallrecord) for overallrecord in self.overallrecords] if self.overallrecords else None
- self.leaguerecords = [Leaguerecords(**leaguerecord) for leaguerecord in self.leaguerecords] if self.leaguerecords else None
- self.expectedrecords = [Typerecords(**expectedrecord) for expectedrecord in self.expectedrecords] if self.expectedrecords else None
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-
-@dataclass(repr=False)
-class TeamRecord:
+ split_records: Optional[List[TypeRecords]] = Field(default=None, alias="splitrecords")
+ division_records: Optional[List[DivisionRecords]] = Field(default=None, alias="divisionrecords")
+ overall_records: Optional[List[TypeRecords]] = Field(default=None, alias="overallrecords")
+ league_records: Optional[List[LeagueRecords]] = Field(default=None, alias="leaguerecords")
+ expected_records: Optional[List[TypeRecords]] = Field(default=None, alias="expectedrecords")
+
+
+class TeamRecord(MLBBaseModel):
"""
- A class to represent a teams current record.
+ A class to represent a team's current record.
- Attributes
+ Attributes
----------
- gamesplayed: int
+ games_played : int
The number of games played by the team.
- wildcardgamesback: str
+ wildcard_games_back : str
The number of games behind the leader in the wild card race.
- leaguegamesback: str
+ league_games_back : str
The number of games behind the leader in the league.
- springleaguegamesback: str
+ spring_league_games_back : str
The number of games behind the leader in the spring league.
- sportgamesback: str
+ sport_games_back : str
The number of games behind the leader in the sport.
- divisiongamesback: str
+ division_games_back : str
The number of games behind the leader in the division.
- conferencegamesback: str
+ conference_games_back : str
The number of games behind the leader in the conference.
- leaguerecord: OverallleagueRecord
- The overall league record of the team. Can be an instance of the OverallleagueRecord class or a dictionary with relevant information about the record.
- records: Records
- The records of the team. Can be an instance of the Records class or a dictionary with relevant information about the records.
- divisionleader: bool
- A flag indicating whether the team is the leader in their division.
- wins: int
+ league_record : OverallLeagueRecord
+ The overall league record of the team.
+ records : Records
+ The records of the team.
+ division_leader : bool
+ Whether the team is the leader in their division.
+ wins : int
The number of wins of the team.
- losses: int
+ losses : int
The number of losses of the team.
- winningpercentage: str
+ winning_percentage : str
The winning percentage of the team.
"""
- gamesplayed: int
- wildcardgamesback: str
- leaguegamesback: str
- springleaguegamesback: str
- sportgamesback: str
- divisiongamesback: str
- conferencegamesback: str
- leaguerecord: Union[OverallleagueRecord, dict]
- records: Union[Records, dict]
- divisionleader: bool
+ games_played: int = Field(alias="gamesplayed")
+ wildcard_games_back: str = Field(alias="wildcardgamesback")
+ league_games_back: str = Field(alias="leaguegamesback")
+ spring_league_games_back: str = Field(alias="springleaguegamesback")
+ sport_games_back: str = Field(alias="sportgamesback")
+ division_games_back: str = Field(alias="divisiongamesback")
+ conference_games_back: str = Field(alias="conferencegamesback")
+ league_record: OverallLeagueRecord = Field(alias="leaguerecord")
+ records: Records
+ division_leader: bool = Field(alias="divisionleader")
wins: int
losses: int
- winningpercentage: str
-
- def __post_init__(self):
- self.leaguerecord = OverallleagueRecord(**self.leaguerecord)
- self.records = Records(**self.records)
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ winning_percentage: str = Field(alias="winningpercentage")
diff --git a/mlbstatsapi/models/teams/team.py b/mlbstatsapi/models/teams/team.py
index 1bb8ff48..c16063fb 100644
--- a/mlbstatsapi/models/teams/team.py
+++ b/mlbstatsapi/models/teams/team.py
@@ -1,105 +1,89 @@
-from typing import List, Dict, Union, Optional
-from dataclasses import dataclass, field
-
+from typing import Optional
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from mlbstatsapi.models.leagues import League
from mlbstatsapi.models.venues import Venue
from mlbstatsapi.models.divisions import Division
from mlbstatsapi.models.sports import Sport
-
from .attributes import TeamRecord
-# from mlbstatsapi.models.standings import Teamrecords
-@dataclass(repr=False)
-class Team:
+class Team(MLBBaseModel):
"""
A class to represent a Team.
Attributes
----------
id : int
- id number of the team
- name : str
- name of the team
+ ID number of the team.
link : str
- The API link for the team
- springleague : League
- The spring league of the team
- allstarstatus : str
- The all status status of the team
- season : str
- The team's current season
+ The API link for the team.
+ name : str
+ Name of the team.
+ spring_league : League
+ The spring league of the team.
+ all_star_status : str
+ The all-star status of the team.
+ season : int
+ The team's current season.
venue : Venue
- The team's home venue
- springvenue : Venue
- The team's spring venue
- teamcode : str
- team code
- filecode : str
- filecode name of the team
+ The team's home venue.
+ spring_venue : Venue
+ The team's spring venue.
+ team_code : str
+ Team code.
+ file_code : str
+ File code name of the team.
abbreviation : str
- The abbreviation of the team name
- teamname : str
- The team name
- locationname : str
- The location of the team
- firstyearofplay : str
- The first year the team began play
+ The abbreviation of the team name.
+ team_name : str
+ The team name.
+ location_name : str
+ The location of the team.
+ first_year_of_play : str
+ The first year the team began play.
league : League
- The league of the team
+ The league of the team.
division : Division
- The division the team is in
+ The division the team is in.
sport : Sport
- The sport of the team
- shortname : str
- The shortname of the team
+ The sport of the team.
+ short_name : str
+ The short name of the team.
record : TeamRecord
- The record of the team
- franchisename : str
- The franchisename of the team
- clubname : str
- The clubname of the team
- active : str
- Active status of the team
- parentorgname : str
- The name of the parent team or org
- parentorgid : str
- The id of the partent team or org
+ The record of the team.
+ franchise_name : str
+ The franchise name of the team.
+ club_name : str
+ The club name of the team.
+ active : bool
+ Active status of the team.
+ parent_org_name : str
+ The name of the parent team or org.
+ parent_org_id : int
+ The ID of the parent team or org.
"""
id: int
link: str
- name: Optional[str] = field(default_factory=dict)
- springleague: Union[League, dict] = field(default_factory=dict)
- allstarstatus: Optional[str] = None
- season: Optional[str] = None
- venue: Union[Venue, dict] = field(default_factory=dict)
- springvenue: Union[Venue, dict] = field(default_factory=dict)
- teamcode: Optional[str] = None
- filecode: Optional[str] = None
+ name: Optional[str] = None
+ spring_league: Optional[League] = Field(default=None, alias="springleague")
+ all_star_status: Optional[str] = Field(default=None, alias="allstarstatus")
+ season: Optional[int] = None
+ venue: Optional[Venue] = None
+ spring_venue: Optional[Venue] = Field(default=None, alias="springvenue")
+ team_code: Optional[str] = Field(default=None, alias="teamcode")
+ file_code: Optional[str] = Field(default=None, alias="filecode")
abbreviation: Optional[str] = None
- teamname: Optional[str] = None
- locationname: Optional[str] = None
- firstyearofplay: Optional[str] = None
- league: Union[League, dict] = field(default_factory=dict)
- division: Union[Division, dict] = field(default_factory=dict)
- sport: Union[Sport, dict] = field(default_factory=dict)
- shortname: Optional[str] = None
- record: Union[TeamRecord, dict] = None
- franchisename: Optional[str] = None
- clubname: Optional[str] = None
- active: Optional[str] = None
- parentorgname: Optional[str] = None
- parentorgid: Optional[str] = None
-
- def __post_init__(self):
- self.springleague = League(**self.springleague) if self.springleague else self.springleague
- self.venue = Venue(**self.venue) if self.venue else self.venue
- self.springvenue = Venue(**self.springvenue) if self.springvenue else self.springvenue
- self.league = League(**self.league) if self.league else self.league
- self.division = Division(**self.division) if self.division else self.division
- self.record = TeamRecord(**self.record) if self.record else self.record
- self.sport = Sport(**self.sport) if self.sport else self.sport
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ team_name: Optional[str] = Field(default=None, alias="teamname")
+ location_name: Optional[str] = Field(default=None, alias="locationname")
+ first_year_of_play: Optional[str] = Field(default=None, alias="firstyearofplay")
+ league: Optional[League] = None
+ division: Optional[Division] = None
+ sport: Optional[Sport] = None
+ short_name: Optional[str] = Field(default=None, alias="shortname")
+ record: Optional[TeamRecord] = None
+ franchise_name: Optional[str] = Field(default=None, alias="franchisename")
+ club_name: Optional[str] = Field(default=None, alias="clubname")
+ active: Optional[bool] = None
+ parent_org_name: Optional[str] = Field(default=None, alias="parentorgname")
+ parent_org_id: Optional[int] = Field(default=None, alias="parentorgid")
diff --git a/mlbstatsapi/models/venues/attributes.py b/mlbstatsapi/models/venues/attributes.py
index 6be91b50..5e8a9531 100644
--- a/mlbstatsapi/models/venues/attributes.py
+++ b/mlbstatsapi/models/venues/attributes.py
@@ -1,125 +1,123 @@
-from typing import Optional, Union
-from dataclasses import dataclass, field
+from typing import Optional
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
-@dataclass
-class VenueDefaultCoordinates:
+
+class VenueDefaultCoordinates(MLBBaseModel):
"""
- A class to represent a venue.
+ A class to represent venue coordinates.
Attributes
----------
latitude : float
- The latatude coordinate for this venue
+ The latitude coordinate for this venue.
longitude : float
- The longitude coordinate for this venue
+ The longitude coordinate for this venue.
"""
latitude: float
longitude: float
-@dataclass(repr=False)
-class Location:
+
+class Location(MLBBaseModel):
"""
- A class to represent a Location used by venue.
+ A class to represent a location used by venue.
Attributes
----------
+ city : str
+ City the venue is in.
+ country : str
+ Country this venue is in.
+ state_abbrev : str
+ The state's abbreviation.
address1 : str
- Venues first address line
+ Venue's first address line.
address2 : str
- Venues second address line
- city : str
- City the venue is in
+ Venue's second address line.
+ address3 : str
+ Venue's third address line.
state : str
- The State the venue is in
- stateAbbrev : str
- The staes abbreviation
- postalCode : str
- Postal code for this venue
- defaultCoordinates : VenueDefaultCoordinates
- Long and lat for this venues location
- country : str
- What country this venue is in
+ The state the venue is in.
+ postal_code : str
+ Postal code for this venue.
phone : str
- Phone number for this venue
+ Phone number for this venue.
+ azimuth_angle : float
+ Azimuth angle for this venue.
+ elevation : int
+ Elevation for this venue.
+ default_coordinates : VenueDefaultCoordinates
+ Latitude and longitude for this venue's location.
"""
city: str
country: str
- stateabbrev: Optional[str] = None
+ state_abbrev: Optional[str] = Field(default=None, alias="stateabbrev")
address1: Optional[str] = None
state: Optional[str] = None
- postalcode: Optional[str] = None
+ postal_code: Optional[str] = Field(default=None, alias="postalcode")
phone: Optional[str] = None
address2: Optional[str] = None
address3: Optional[str] = None
- azimuthangle: Optional[str] = None
- elevation: Optional[str] = None
- defaultcoordinates: Optional[Union[VenueDefaultCoordinates, dict]] = field(default_factory=dict)
-
- def __post_init__(self):
- self.defaultcoordinates = VenueDefaultCoordinates(**self.defaultcoordinates) if self.defaultcoordinates else self.defaultcoordinates
+ azimuth_angle: Optional[float] = Field(default=None, alias="azimuthangle")
+ elevation: Optional[int] = None
+ default_coordinates: Optional[VenueDefaultCoordinates] = Field(default=None, alias="defaultcoordinates")
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
-@dataclass
-class TimeZone:
+class TimeZone(MLBBaseModel):
"""
- A class to represent a TimeZone Used by venue.
+ A class to represent a timezone used by venue.
Attributes
----------
id : str
- id string for a venues timezone
+ ID string for a venue's timezone.
offset : int
- The offset for this timezone from
+ The offset for this timezone.
tz : str
- Timezone string
+ Timezone string.
+ offset_at_game_time : int
+ Offset at game time.
"""
id: str
offset: int
tz: str
- offsetatgametime: Optional[int] = None
+ offset_at_game_time: Optional[int] = Field(default=None, alias="offsetatgametime")
-@dataclass(repr=False)
-class FieldInfo:
+
+class FieldInfo(MLBBaseModel):
"""
- A class to represent a venue Field info.
+ A class to represent venue field info.
Attributes
----------
capacity : int
- Capacity for this venue
- turfType : str
- The type of turf in this venue
- roofType : str
- What kind of roof for this venue
- leftLine : int
- Distance down the left line
+ Capacity for this venue.
+ turf_type : str
+ The type of turf in this venue.
+ roof_type : str
+ What kind of roof for this venue.
+ left_line : int
+ Distance down the left line.
left : int
- Distance to left
- leftCenter : int
- Distance to left center
+ Distance to left.
+ left_center : int
+ Distance to left center.
center : int
- Distance to center
- rightCenter : int
- Distance to right center
+ Distance to center.
+ right_center : int
+ Distance to right center.
right : int
- Distance to right
- rightLine : int
- Distance to right line
+ Distance to right.
+ right_line : int
+ Distance to right line.
"""
capacity: Optional[int] = None
- turftype: Optional[str] = None
- rooftype: Optional[str] = None
- leftline: Optional[int] = None
+ turf_type: Optional[str] = Field(default=None, alias="turftype")
+ roof_type: Optional[str] = Field(default=None, alias="rooftype")
+ left_line: Optional[int] = Field(default=None, alias="leftline")
left: Optional[int] = None
- leftcenter: Optional[int] = None
+ left_center: Optional[int] = Field(default=None, alias="leftcenter")
center: Optional[int] = None
- rightcenter: Optional[int] = None
+ right_center: Optional[int] = Field(default=None, alias="rightcenter")
right: Optional[int] = None
- rightline: Optional[int] = None
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ right_line: Optional[int] = Field(default=None, alias="rightline")
diff --git a/mlbstatsapi/models/venues/venue.py b/mlbstatsapi/models/venues/venue.py
index aad50759..e8ea7929 100644
--- a/mlbstatsapi/models/venues/venue.py
+++ b/mlbstatsapi/models/venues/venue.py
@@ -1,45 +1,37 @@
-from typing import Optional, Union
-from dataclasses import dataclass
+from typing import Optional
+from pydantic import Field
+from mlbstatsapi.models.base import MLBBaseModel
from .attributes import Location, TimeZone, FieldInfo
-@dataclass(repr=False)
-class Venue:
+
+class Venue(MLBBaseModel):
"""
A class to represent a venue.
Attributes
----------
id : int
- id for this venue
- name : str
- Name for this venue
+ ID for this venue.
link : str
- Link to venues endpoint
+ Link to venue's endpoint.
+ name : str
+ Name for this venue.
location : Location
- Location for this venue
+ Location for this venue.
timezone : TimeZone
- Timezone for this venue
- fieldinfo : FieldInfo
- Info on this venue's field
+ Timezone for this venue.
+ field_info : FieldInfo
+ Info on this venue's field.
active : bool
- Is this field currently active
+ Whether this field is currently active.
season : str
- This field holds the season
+ The season.
"""
- id: int
- link: str
- name: Optional[str] = None
- location: Optional[Union[Location, dict]] = None
- timezone: Optional[Union[TimeZone, dict]] = None
- fieldinfo: Optional[Union[FieldInfo, dict]] = None
- active: Optional[bool] = None
- season: Optional[str] = None
-
- def __post_init__(self):
- self.location = Location(**self.location) if self.location else self.location
- self.timezone = TimeZone(**self.timezone) if self.timezone else self.timezone
- self.fieldinfo = FieldInfo(**self.fieldinfo) if self.fieldinfo else self.fieldinfo
-
- def __repr__(self) -> str:
- kws = [f'{key}={value}' for key, value in self.__dict__.items() if value is not None and value]
- return "{}({})".format(type(self).__name__, ", ".join(kws))
\ No newline at end of file
+ id: int
+ link: str
+ name: Optional[str] = None
+ location: Optional[Location] = None
+ timezone: Optional[TimeZone] = None
+ field_info: Optional[FieldInfo] = Field(default=None, alias="fieldinfo")
+ active: Optional[bool] = None
+ season: Optional[str] = None
diff --git a/poetry.lock b/poetry.lock
index 615c660b..52de79e8 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,5 +1,16 @@
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
+[[package]]
+name = "annotated-types"
+version = "0.7.0"
+description = "Reusable constraint types to use with typing.Annotated"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
+ {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
+]
+
[[package]]
name = "build"
version = "1.4.0"
@@ -257,6 +268,160 @@ files = [
dev = ["pre-commit", "tox"]
testing = ["coverage", "pytest", "pytest-benchmark"]
+[[package]]
+name = "pydantic"
+version = "2.12.5"
+description = "Data validation using Python type hints"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d"},
+ {file = "pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49"},
+]
+
+[package.dependencies]
+annotated-types = ">=0.6.0"
+pydantic-core = "2.41.5"
+typing-extensions = ">=4.14.1"
+typing-inspection = ">=0.4.2"
+
+[package.extras]
+email = ["email-validator (>=2.0.0)"]
+timezone = ["tzdata"]
+
+[[package]]
+name = "pydantic-core"
+version = "2.41.5"
+description = "Core functionality for Pydantic validation and serialization"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146"},
+ {file = "pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2"},
+ {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97"},
+ {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9"},
+ {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52"},
+ {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941"},
+ {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a"},
+ {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c"},
+ {file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2"},
+ {file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556"},
+ {file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49"},
+ {file = "pydantic_core-2.41.5-cp310-cp310-win32.whl", hash = "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba"},
+ {file = "pydantic_core-2.41.5-cp310-cp310-win_amd64.whl", hash = "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9"},
+ {file = "pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6"},
+ {file = "pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b"},
+ {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a"},
+ {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8"},
+ {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e"},
+ {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1"},
+ {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b"},
+ {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b"},
+ {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284"},
+ {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594"},
+ {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e"},
+ {file = "pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b"},
+ {file = "pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe"},
+ {file = "pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f"},
+ {file = "pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7"},
+ {file = "pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0"},
+ {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69"},
+ {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75"},
+ {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05"},
+ {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc"},
+ {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c"},
+ {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5"},
+ {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c"},
+ {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294"},
+ {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1"},
+ {file = "pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d"},
+ {file = "pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815"},
+ {file = "pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3"},
+ {file = "pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9"},
+ {file = "pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34"},
+ {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0"},
+ {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33"},
+ {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e"},
+ {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2"},
+ {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586"},
+ {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d"},
+ {file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740"},
+ {file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e"},
+ {file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858"},
+ {file = "pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36"},
+ {file = "pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11"},
+ {file = "pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd"},
+ {file = "pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a"},
+ {file = "pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14"},
+ {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1"},
+ {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66"},
+ {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869"},
+ {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2"},
+ {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375"},
+ {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553"},
+ {file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90"},
+ {file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07"},
+ {file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb"},
+ {file = "pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23"},
+ {file = "pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf"},
+ {file = "pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0"},
+ {file = "pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a"},
+ {file = "pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3"},
+ {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c"},
+ {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612"},
+ {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d"},
+ {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9"},
+ {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660"},
+ {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9"},
+ {file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3"},
+ {file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf"},
+ {file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470"},
+ {file = "pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa"},
+ {file = "pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c"},
+ {file = "pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008"},
+ {file = "pydantic_core-2.41.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:8bfeaf8735be79f225f3fefab7f941c712aaca36f1128c9d7e2352ee1aa87bdf"},
+ {file = "pydantic_core-2.41.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:346285d28e4c8017da95144c7f3acd42740d637ff41946af5ce6e5e420502dd5"},
+ {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a75dafbf87d6276ddc5b2bf6fae5254e3d0876b626eb24969a574fff9149ee5d"},
+ {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7b93a4d08587e2b7e7882de461e82b6ed76d9026ce91ca7915e740ecc7855f60"},
+ {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8465ab91a4bd96d36dde3263f06caa6a8a6019e4113f24dc753d79a8b3a3f82"},
+ {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:299e0a22e7ae2b85c1a57f104538b2656e8ab1873511fd718a1c1c6f149b77b5"},
+ {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:707625ef0983fcfb461acfaf14de2067c5942c6bb0f3b4c99158bed6fedd3cf3"},
+ {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425"},
+ {file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0384e2e1021894b1ff5a786dbf94771e2986ebe2869533874d7e43bc79c6f504"},
+ {file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:f0cd744688278965817fd0839c4a4116add48d23890d468bc436f78beb28abf5"},
+ {file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:753e230374206729bf0a807954bcc6c150d3743928a73faffee51ac6557a03c3"},
+ {file = "pydantic_core-2.41.5-cp39-cp39-win32.whl", hash = "sha256:873e0d5b4fb9b89ef7c2d2a963ea7d02879d9da0da8d9d4933dee8ee86a8b460"},
+ {file = "pydantic_core-2.41.5-cp39-cp39-win_amd64.whl", hash = "sha256:e4f4a984405e91527a0d62649ee21138f8e3d0ef103be488c1dc11a80d7f184b"},
+ {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034"},
+ {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c"},
+ {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2"},
+ {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad"},
+ {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd"},
+ {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc"},
+ {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56"},
+ {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b"},
+ {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8"},
+ {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a"},
+ {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b"},
+ {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2"},
+ {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093"},
+ {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a"},
+ {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963"},
+ {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a"},
+ {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26"},
+ {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808"},
+ {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc"},
+ {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1"},
+ {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84"},
+ {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770"},
+ {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f"},
+ {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51"},
+ {file = "pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e"},
+]
+
+[package.dependencies]
+typing-extensions = ">=4.14.1"
+
[[package]]
name = "pygments"
version = "2.19.2"
@@ -410,6 +575,20 @@ files = [
{file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"},
]
+[[package]]
+name = "typing-inspection"
+version = "0.4.2"
+description = "Runtime typing introspection tools"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"},
+ {file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"},
+]
+
+[package.dependencies]
+typing-extensions = ">=4.12.0"
+
[[package]]
name = "urllib3"
version = "2.6.3"
@@ -449,4 +628,4 @@ type = ["pytest-mypy"]
[metadata]
lock-version = "2.0"
python-versions = ">=3.10"
-content-hash = "0dea405a869e2eab4fcecf63f0167133bf79afa9385ecfb9b7a8e6b69423c24e"
+content-hash = "7413638efb3c23e0e04b32ca1cf4a49cb1838cd5c30a00ac987f79c2e688b77f"
diff --git a/pyproject.toml b/pyproject.toml
index eca7b6e8..ea3f4a9c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "python-mlb-statsapi"
-version = "0.6.2"
+version = "0.7.0"
description = "mlbstatsapi python wrapper"
authors = [
"Matthew Spah ",
@@ -23,6 +23,7 @@ classifiers = [
[tool.poetry.dependencies]
python = ">=3.10"
requests = ">=2"
+pydantic = "^2.0"
[tool.poetry.group.dev.dependencies]
pytest = "^8.0"
diff --git a/tests/external_tests/attendance/test_attendance.py b/tests/external_tests/attendance/test_attendance.py
index b5ee5525..5eea7ad2 100644
--- a/tests/external_tests/attendance/test_attendance.py
+++ b/tests/external_tests/attendance/test_attendance.py
@@ -1,8 +1,10 @@
import unittest
from unittest.mock import Mock, patch
+from pydantic import ValidationError
from mlbstatsapi.models.attendances import Attendance, attendance
from mlbstatsapi import Mlb
+
class TestAttendance(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
@@ -12,13 +14,13 @@ def setUpClass(cls) -> None:
cls.attendance_team_home = cls.mlb.get_attendance(team_id=134)
cls.attendance_season = cls.mlb.get_attendance(team_id=113, params=params)
-
@classmethod
def tearDownClass(cls) -> None:
pass
- def test_attendance_instance_type_error(self):
- with self.assertRaises(TypeError):
+ def test_attendance_instance_validation_error(self):
+ """Pydantic raises ValidationError when required fields are missing."""
+ with self.assertRaises(ValidationError):
attendance = Attendance()
def test_attendance_instance_position_arguments(self):
@@ -31,8 +33,22 @@ def test_attendance_has_attributes(self):
self.assertIsInstance(self.attendance_team_home, Attendance)
self.assertIsInstance(self.attendance_season, Attendance)
self.assertTrue(hasattr(self.attendance_team_away, "records"))
- self.assertTrue(hasattr(self.attendance_team_away, "aggregatetotals"))
+ self.assertTrue(hasattr(self.attendance_team_away, "aggregate_totals"))
self.assertTrue(hasattr(self.attendance_team_home, "records"))
- self.assertTrue(hasattr(self.attendance_team_home, "aggregatetotals"))
+ self.assertTrue(hasattr(self.attendance_team_home, "aggregate_totals"))
self.assertTrue(hasattr(self.attendance_season, "records"))
- self.assertTrue(hasattr(self.attendance_season, "aggregatetotals"))
+ self.assertTrue(hasattr(self.attendance_season, "aggregate_totals"))
+
+ def test_attendance_pythonic_field_names(self):
+ """Test that Pythonic field names work correctly."""
+ record = self.attendance_team_away.records[0]
+ # Verify snake_case field names are accessible
+ self.assertIsNotNone(record.openings_total)
+ self.assertIsNotNone(record.games_total)
+ self.assertIsNotNone(record.attendance_average_ytd)
+ self.assertIsNotNone(record.game_type)
+
+ # Verify aggregate totals use snake_case
+ totals = self.attendance_team_away.aggregate_totals
+ self.assertIsNotNone(totals.openings_total_away)
+ self.assertIsNotNone(totals.attendance_total)
diff --git a/tests/external_tests/division/test_division.py b/tests/external_tests/division/test_division.py
index da1f0249..98eeaffe 100644
--- a/tests/external_tests/division/test_division.py
+++ b/tests/external_tests/division/test_division.py
@@ -1,4 +1,5 @@
import unittest
+from pydantic import ValidationError
from mlbstatsapi.models.divisions import Division
from mlbstatsapi import Mlb
@@ -14,7 +15,8 @@ def tearDownClass(cls) -> None:
pass
def test_divisions_instance_type_error(self):
- with self.assertRaises(TypeError):
+ """Pydantic raises ValidationError when required fields are missing."""
+ with self.assertRaises(ValidationError):
division = Division()
def test_divisions_instance_position_arguments(self):
@@ -28,11 +30,11 @@ def test_divisions_has_attributes(self):
self.assertTrue(hasattr(self.division, "name"))
self.assertTrue(hasattr(self.division, "link"))
self.assertTrue(hasattr(self.division, "season"))
- self.assertTrue(hasattr(self.division, "nameshort"))
+ self.assertTrue(hasattr(self.division, "name_short"))
self.assertTrue(hasattr(self.division, "abbreviation"))
self.assertTrue(hasattr(self.division, "league"))
self.assertTrue(hasattr(self.division, "sport"))
- self.assertTrue(hasattr(self.division, "haswildcard"))
- self.assertTrue(hasattr(self.division, "sortorder"))
- self.assertTrue(hasattr(self.division, "numplayoffteams"))
+ self.assertTrue(hasattr(self.division, "has_wildcard"))
+ self.assertTrue(hasattr(self.division, "sort_order"))
+ self.assertTrue(hasattr(self.division, "num_playoff_teams"))
self.assertTrue(hasattr(self.division, "active"))
diff --git a/tests/external_tests/drafts/test_draft.py b/tests/external_tests/drafts/test_draft.py
index 93ac81e8..ba431e74 100644
--- a/tests/external_tests/drafts/test_draft.py
+++ b/tests/external_tests/drafts/test_draft.py
@@ -1,4 +1,4 @@
-import unittest
+import unittest
from mlbstatsapi import Mlb
from mlbstatsapi.models.drafts import Round
@@ -40,8 +40,8 @@ def test_get_draft_by_year_id(self):
draftpick = draftpicks[0]
- # draft pick should have attrs set
- self.assertTrue(draftpick.pickround)
+ # draft pick should have attrs set (using Pythonic field name)
+ self.assertTrue(draftpick.pick_round)
def test_get_draft_by_year_id_404(self):
"""This test should return a 200 and """
diff --git a/tests/external_tests/game/test_game.py b/tests/external_tests/game/test_game.py
index b6125a70..5fc05aef 100644
--- a/tests/external_tests/game/test_game.py
+++ b/tests/external_tests/game/test_game.py
@@ -27,5 +27,27 @@ def test_game_creation(self):
def test_game_attrs(self):
self.assertTrue(hasattr(self.game, "metadata"))
- self.assertTrue(hasattr(self.game, "gamedata"))
- self.assertTrue(hasattr(self.game, "livedata"))
+ self.assertTrue(hasattr(self.game, "game_data"))
+ self.assertTrue(hasattr(self.game, "live_data"))
+
+ def test_game_pythonic_field_names(self):
+ """Test that Pythonic field names are accessible."""
+ # Test top-level game attributes
+ self.assertIsNotNone(self.game.game_pk)
+ self.assertIsNotNone(self.game.metadata)
+ self.assertIsNotNone(self.game.game_data)
+ self.assertIsNotNone(self.game.live_data)
+
+ # Test game_data nested attributes
+ self.assertIsNotNone(self.game.game_data.game)
+ self.assertIsNotNone(self.game.game_data.datetime)
+ self.assertIsNotNone(self.game.game_data.status)
+ self.assertIsNotNone(self.game.game_data.teams)
+ self.assertIsNotNone(self.game.game_data.venue)
+ self.assertIsNotNone(self.game.game_data.official_venue)
+ self.assertIsNotNone(self.game.game_data.probable_pitchers)
+
+ # Test live_data nested attributes
+ self.assertIsNotNone(self.game.live_data.plays)
+ self.assertIsNotNone(self.game.live_data.boxscore)
+ self.assertIsNotNone(self.game.live_data.leaders)
diff --git a/tests/external_tests/gamepace/test_gamepace.py b/tests/external_tests/gamepace/test_gamepace.py
index 68d44fda..a230502d 100644
--- a/tests/external_tests/gamepace/test_gamepace.py
+++ b/tests/external_tests/gamepace/test_gamepace.py
@@ -1,5 +1,5 @@
import unittest
-from mlbstatsapi.models.gamepace import Gamepace, Gamepacedata
+from mlbstatsapi.models.gamepace import GamePace, GamePaceData
from mlbstatsapi import Mlb
@@ -18,19 +18,19 @@
# # set draft id
# season_id = 2021
-# # call get_gamepace return Gamepace object
+# # call get_gamepace return GamePace object
# gamepace = self.mlb.get_gamepace(season_id)
-# # Gamepace should not be None
+# # GamePace should not be None
# self.assertIsNotNone(gamepace)
-# self.assertIsInstance(gamepace, Gamepace)
+# self.assertIsInstance(gamepace, GamePace)
# # list should not be empty
# self.assertNotEqual(gamepace.sports, [])
# # items in list should be gamepace data
-# self.assertIsInstance(gamepace.sports[0], Gamepacedata)
+# self.assertIsInstance(gamepace.sports[0], GamePaceData)
# sportgamepace = gamepace.sports[0]
@@ -38,8 +38,8 @@
# self.assertIsNotNone(sportgamepace)
# # sportgamepace should have attrs set
-# self.assertTrue(sportgamepace.hitspergame)
-# self.assertTrue(sportgamepace.totalgames)
+# self.assertTrue(sportgamepace.hits_per_game)
+# self.assertTrue(sportgamepace.total_games)
# def test_get_gamepace_404(self):
# """This test should return a 200 and """
@@ -47,7 +47,7 @@
# # set gamepace season to invalid year
# season_id = '2040,21'
-# # call get_gamepace return Gamepace object
+# # call get_gamepace return GamePace object
# gamepace = self.mlb.get_gamepace(season_id)
# # gamepace should be None
@@ -64,4 +64,4 @@
# # gamepace should not be None
# self.assertIsNotNone(gamepace)
# # list should not be empty
-# self.assertNotEqual(gamepace.leagues, [])
\ No newline at end of file
+# self.assertNotEqual(gamepace.leagues, [])
diff --git a/tests/external_tests/homerunderby/test_homerunderby.py b/tests/external_tests/homerunderby/test_homerunderby.py
index a145f7e5..abbf2be9 100644
--- a/tests/external_tests/homerunderby/test_homerunderby.py
+++ b/tests/external_tests/homerunderby/test_homerunderby.py
@@ -1,5 +1,5 @@
import unittest
-from mlbstatsapi.models.homerunderby import Homerunderby, Round
+from mlbstatsapi.models.homerunderby import HomeRunDerby, Round
from mlbstatsapi import Mlb
@@ -12,34 +12,34 @@ def setUpClass(cls) -> None:
def tearDownClass(cls) -> None:
pass
- def test_get_gamepace(self):
+ def test_get_homerunderby(self):
"""This test should return a 200 and Round"""
- # set draft id
+ # set game id
game_id = 511101
- # call get_gamepace return Gamepace object
+ # call get_homerun_derby return HomeRunDerby object
derby = self.mlb.get_homerun_derby(game_id)
- # Gamepace should not be None
+ # HomeRunDerby should not be None
self.assertIsNotNone(derby)
- self.assertIsInstance(derby, Homerunderby)
+ self.assertIsInstance(derby, HomeRunDerby)
# list should not be empty
self.assertNotEqual(derby.rounds, [])
- # items in list should be gamepace data
+ # items in list should be Round
self.assertIsInstance(derby.rounds[0], Round)
def test_get_homerunderby_404(self):
- """This test should return a 200 and """
+ """This test should return None for invalid game id"""
# set gameid to invalid id
game_id = '100394810242'
- # call get_gamepace return Gamepace object
+ # call get_homerun_derby return HomeRunDerby object
derby = self.mlb.get_homerun_derby(game_id)
- # gamepace should be None
- self.assertIsNone(derby)
\ No newline at end of file
+ # derby should be None
+ self.assertIsNone(derby)
diff --git a/tests/external_tests/league/test_league.py b/tests/external_tests/league/test_league.py
index ced2d979..45be6ed8 100644
--- a/tests/external_tests/league/test_league.py
+++ b/tests/external_tests/league/test_league.py
@@ -1,4 +1,5 @@
import unittest
+from pydantic import ValidationError
from mlbstatsapi.models.leagues import League
from mlbstatsapi import Mlb
@@ -14,7 +15,8 @@ def tearDownClass(cls) -> None:
pass
def test_league_instance_type_error(self):
- with self.assertRaises(TypeError):
+ """Pydantic raises ValidationError when required fields are missing."""
+ with self.assertRaises(ValidationError):
league = League()
def test_league_instance_position_arguments(self):
@@ -28,19 +30,19 @@ def test_league_has_attributes(self):
self.assertTrue(hasattr(self.league, "name"))
self.assertTrue(hasattr(self.league, "link"))
self.assertTrue(hasattr(self.league, "abbreviation"))
- self.assertTrue(hasattr(self.league, "nameshort"))
- self.assertTrue(hasattr(self.league, "seasonstate"))
- self.assertTrue(hasattr(self.league, "haswildcard"))
- self.assertTrue(hasattr(self.league, "hassplitseason"))
- self.assertTrue(hasattr(self.league, "numgames"))
- self.assertTrue(hasattr(self.league, "hasplayoffpoints"))
- self.assertTrue(hasattr(self.league, "numteams"))
- self.assertTrue(hasattr(self.league, "numwildcardteams"))
- self.assertTrue(hasattr(self.league, "seasondateinfo"))
+ self.assertTrue(hasattr(self.league, "name_short"))
+ self.assertTrue(hasattr(self.league, "season_state"))
+ self.assertTrue(hasattr(self.league, "has_wildcard"))
+ self.assertTrue(hasattr(self.league, "has_split_season"))
+ self.assertTrue(hasattr(self.league, "num_games"))
+ self.assertTrue(hasattr(self.league, "has_playoff_points"))
+ self.assertTrue(hasattr(self.league, "num_teams"))
+ self.assertTrue(hasattr(self.league, "num_wildcard_teams"))
+ self.assertTrue(hasattr(self.league, "season_date_info"))
self.assertTrue(hasattr(self.league, "season"))
- self.assertTrue(hasattr(self.league, "orgcode"))
- self.assertTrue(hasattr(self.league, "conferencesinuse"))
- self.assertTrue(hasattr(self.league, "divisionsinuse"))
+ self.assertTrue(hasattr(self.league, "org_code"))
+ self.assertTrue(hasattr(self.league, "conferences_in_use"))
+ self.assertTrue(hasattr(self.league, "divisions_in_use"))
self.assertTrue(hasattr(self.league, "sport"))
- self.assertTrue(hasattr(self.league, "sortorder"))
+ self.assertTrue(hasattr(self.league, "sort_order"))
self.assertTrue(hasattr(self.league, "active"))
diff --git a/tests/external_tests/person/test_person.py b/tests/external_tests/person/test_person.py
index d2792172..b75f5b3a 100644
--- a/tests/external_tests/person/test_person.py
+++ b/tests/external_tests/person/test_person.py
@@ -1,4 +1,5 @@
-import unittest
+import unittest
+from pydantic import ValidationError
from mlbstatsapi.models.people import Person, Position
from mlbstatsapi import Mlb
@@ -14,13 +15,14 @@ def tearDownClass(cls) -> None:
pass
def test_player_instance_type_error(self):
- with self.assertRaises(TypeError):
+ """Pydantic raises ValidationError when required fields are missing."""
+ with self.assertRaises(ValidationError):
player = Person()
def test_player_instance_position_arguments(self):
self.assertEqual(self.player.id, 664034)
self.assertIsInstance(self.player, Person)
- self.assertEqual(self.player.fullname, "Ty France")
+ self.assertEqual(self.player.full_name, "Ty France")
self.assertEqual(self.player.link, "/api/v1/people/664034")
def test_get_persons(self):
@@ -44,6 +46,7 @@ def test_get_persons(self):
self.assertIsInstance(players_l[0], Person)
self.assertIsInstance(players_s[0], Person)
+
class TestPersonPrimaryPosition(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
@@ -55,5 +58,5 @@ def tearDownClass(cls) -> None:
pass
def test_player_position_player_position(self):
- self.assertIsInstance(self.position_player.primaryposition, Position)
- self.assertTrue(hasattr(self.position_player.primaryposition, "code"))
\ No newline at end of file
+ self.assertIsInstance(self.position_player.primary_position, Position)
+ self.assertTrue(hasattr(self.position_player.primary_position, "code"))
diff --git a/tests/external_tests/schedule/test_schedule.py b/tests/external_tests/schedule/test_schedule.py
index d5a80856..6cd03776 100644
--- a/tests/external_tests/schedule/test_schedule.py
+++ b/tests/external_tests/schedule/test_schedule.py
@@ -1,4 +1,5 @@
import unittest
+from pydantic import ValidationError
from mlbstatsapi.models.schedules import Schedule
from mlbstatsapi import Mlb
@@ -13,20 +14,32 @@ def setUpClass(cls) -> None:
def tearDownClass(cls) -> None:
pass
- def test_schedule_instance_type_error(self):
- with self.assertRaises(TypeError):
+ def test_schedule_instance_validation_error(self):
+ with self.assertRaises(ValidationError):
schedule = Schedule()
def test_schedule_instance_position_arguments(self):
- self.assertEqual(self.schedule.totalitems, 4)
- self.assertEqual(self.schedule.totalevents, 0)
- self.assertEqual(self.schedule.totalgames, 4)
+ self.assertEqual(self.schedule.total_items, 4)
+ self.assertEqual(self.schedule.total_events, 0)
+ self.assertEqual(self.schedule.total_games, 4)
def test_schedule_has_attributes(self):
self.assertIsInstance(self.schedule, Schedule)
- self.assertTrue(hasattr(self.schedule, "totalitems"))
- self.assertTrue(hasattr(self.schedule, "totalevents"))
- self.assertTrue(hasattr(self.schedule, "totalgames"))
- self.assertTrue(hasattr(self.schedule, "totalgamesinprogress"))
+ self.assertTrue(hasattr(self.schedule, "total_items"))
+ self.assertTrue(hasattr(self.schedule, "total_events"))
+ self.assertTrue(hasattr(self.schedule, "total_games"))
+ self.assertTrue(hasattr(self.schedule, "total_games_in_progress"))
self.assertTrue(hasattr(self.schedule, "dates"))
+ def test_schedule_pythonic_field_names(self):
+ """Test that Pythonic field names are accessible."""
+ self.assertIsNotNone(self.schedule.total_items)
+ self.assertIsNotNone(self.schedule.dates)
+ if self.schedule.dates:
+ date = self.schedule.dates[0]
+ self.assertIsNotNone(date.total_games)
+ if date.games:
+ game = date.games[0]
+ self.assertIsNotNone(game.game_pk)
+ self.assertIsNotNone(game.game_type)
+ self.assertIsNotNone(game.game_date)
diff --git a/tests/external_tests/sport/test_sport.py b/tests/external_tests/sport/test_sport.py
index 865f750e..18f2de1d 100644
--- a/tests/external_tests/sport/test_sport.py
+++ b/tests/external_tests/sport/test_sport.py
@@ -1,4 +1,5 @@
import unittest
+from pydantic import ValidationError
from mlbstatsapi.models.sports import Sport
from mlbstatsapi import Mlb
@@ -14,7 +15,8 @@ def tearDownClass(cls) -> None:
pass
def test_sport_instance_type_error(self):
- with self.assertRaises(TypeError):
+ """Pydantic raises ValidationError when required fields are missing."""
+ with self.assertRaises(ValidationError):
sport = Sport()
def test_sport_instance_position_arguments(self):
@@ -29,5 +31,5 @@ def test_sport_attributes(self):
self.assertTrue(hasattr(self.sport, "name"))
self.assertTrue(hasattr(self.sport, "code"))
self.assertTrue(hasattr(self.sport, "abbreviation"))
- self.assertTrue(hasattr(self.sport, "sortorder"))
- self.assertTrue(hasattr(self.sport, "activestatus"))
+ self.assertTrue(hasattr(self.sport, "sort_order"))
+ self.assertTrue(hasattr(self.sport, "active_status"))
diff --git a/tests/external_tests/standings/test_standings.py b/tests/external_tests/standings/test_standings.py
index daae205e..8ebb5c6d 100644
--- a/tests/external_tests/standings/test_standings.py
+++ b/tests/external_tests/standings/test_standings.py
@@ -34,12 +34,12 @@ def test_get_standings(self):
standing = standings[0]
- # sportgamepace should not be none
+ # standing should not be none
self.assertIsNotNone(standing)
- # sportgamepace should have attrs set
- self.assertTrue(standing.standingstype)
- self.assertTrue(standing.lastupdated)
+ # standing should have attrs set
+ self.assertTrue(standing.standings_type)
+ self.assertTrue(standing.last_updated)
def test_get_standings_404(self):
"""This test should return a 200 and """
@@ -72,4 +72,4 @@ def test_get_standings_with_params(self):
# standings should not be None
self.assertIsNotNone(standings)
# list should not be empty
- self.assertNotEqual(standings, [])
\ No newline at end of file
+ self.assertNotEqual(standings, [])
diff --git a/tests/external_tests/stats/test_catching.py b/tests/external_tests/stats/test_catching.py
index 21df3f68..7ef250b1 100644
--- a/tests/external_tests/stats/test_catching.py
+++ b/tests/external_tests/stats/test_catching.py
@@ -1,4 +1,4 @@
-import unittest
+import unittest
import time
from mlbstatsapi.mlb_api import Mlb
@@ -39,11 +39,11 @@ def test_catching_stat_attributes_player(self):
season = stats['catching']['season']
career = stats['catching']['career']
- self.assertEqual(season.totalsplits, len(season.splits))
+ self.assertEqual(season.total_splits, len(season.splits))
self.assertEqual(season.group, 'catching')
self.assertEqual(season.type, 'season')
- self.assertEqual(career.totalsplits, len(career.splits))
+ self.assertEqual(career.total_splits, len(career.splits))
self.assertEqual(career.group, 'catching')
self.assertEqual(career.type, 'career')
@@ -70,10 +70,10 @@ def test_catching_stat_attributes_team(self):
season = stats['catching']['season']
career = stats['catching']['career']
- self.assertEqual(season.totalsplits, len(season.splits))
+ self.assertEqual(season.total_splits, len(season.splits))
self.assertEqual(season.group, 'catching')
self.assertEqual(season.type, 'season')
- self.assertEqual(career.totalsplits, len(career.splits))
+ self.assertEqual(career.total_splits, len(career.splits))
self.assertEqual(career.group, 'catching')
self.assertEqual(career.type, 'career')
diff --git a/tests/external_tests/stats/test_fielding.py b/tests/external_tests/stats/test_fielding.py
index e56d311b..85b019b6 100644
--- a/tests/external_tests/stats/test_fielding.py
+++ b/tests/external_tests/stats/test_fielding.py
@@ -1,4 +1,4 @@
-import unittest
+import unittest
import time
from mlbstatsapi.mlb_api import Mlb
@@ -45,11 +45,11 @@ def test_fielding_stat_attributes_player(self):
season = stats['fielding']['season']
career = stats['fielding']['career']
- self.assertEqual(season.totalsplits, len(season.splits))
+ self.assertEqual(season.total_splits, len(season.splits))
self.assertEqual(season.group, 'fielding')
self.assertEqual(season.type, 'season')
- self.assertEqual(career.totalsplits, len(career.splits))
+ self.assertEqual(career.total_splits, len(career.splits))
self.assertEqual(career.group, 'fielding')
self.assertEqual(career.type, 'career')
@@ -79,18 +79,18 @@ def test_fielding_stat_attributes_team(self):
season_advanced = stats['fielding']['seasonadvanced']
career_advanced = stats['fielding']['careeradvanced']
- self.assertEqual(season.totalsplits, len(season.splits))
+ self.assertEqual(season.total_splits, len(season.splits))
self.assertEqual(season.group, 'fielding')
self.assertEqual(season.type, 'season')
- self.assertEqual(career.totalsplits, len(career.splits))
+ self.assertEqual(career.total_splits, len(career.splits))
self.assertEqual(career.group, 'fielding')
self.assertEqual(career.type, 'career')
- self.assertEqual(season_advanced.totalsplits, len(season_advanced.splits))
+ self.assertEqual(season_advanced.total_splits, len(season_advanced.splits))
self.assertEqual(season_advanced.group, 'fielding')
self.assertEqual(season_advanced.type, 'seasonAdvanced')
- self.assertEqual(career_advanced.totalsplits, len(career_advanced.splits))
+ self.assertEqual(career_advanced.total_splits, len(career_advanced.splits))
self.assertEqual(career_advanced.group, 'fielding')
self.assertEqual(career_advanced.type, 'careerAdvanced')
diff --git a/tests/external_tests/stats/test_hitting.py b/tests/external_tests/stats/test_hitting.py
index 55f74c24..a198423b 100644
--- a/tests/external_tests/stats/test_hitting.py
+++ b/tests/external_tests/stats/test_hitting.py
@@ -1,4 +1,4 @@
-import unittest
+import unittest
import time
from mlbstatsapi.mlb_api import Mlb
@@ -49,19 +49,19 @@ def test_hitting_stat_attributes_player(self):
career_advanced = stats['hitting']['careeradvanced']
# check that attrs exist and contain data
- self.assertEqual(season.totalsplits, len(season.splits))
+ self.assertEqual(season.total_splits, len(season.splits))
self.assertEqual(season.group, 'hitting')
self.assertEqual(season.type, 'season')
- self.assertEqual(career.totalsplits, len(career.splits))
+ self.assertEqual(career.total_splits, len(career.splits))
self.assertEqual(career.group, 'hitting')
self.assertEqual(career.type, 'career')
- self.assertEqual(season_advanced.totalsplits, len(season_advanced.splits))
+ self.assertEqual(season_advanced.total_splits, len(season_advanced.splits))
self.assertEqual(season_advanced.group, 'hitting')
self.assertEqual(season_advanced.type, 'seasonAdvanced')
- self.assertEqual(career_advanced.totalsplits, len(career_advanced.splits))
+ self.assertEqual(career_advanced.total_splits, len(career_advanced.splits))
self.assertEqual(career_advanced.group, 'hitting')
self.assertEqual(career_advanced.type, 'careerAdvanced')
@@ -94,19 +94,19 @@ def test_hitting_stat_attributes_team(self):
season_advanced = stats['hitting']['seasonadvanced']
career_advanced = stats['hitting']['careeradvanced']
- self.assertEqual(season.totalsplits, len(season.splits))
+ self.assertEqual(season.total_splits, len(season.splits))
self.assertEqual(season.group, 'hitting')
self.assertEqual(season.type, 'season')
- self.assertEqual(career.totalsplits, len(career.splits))
+ self.assertEqual(career.total_splits, len(career.splits))
self.assertEqual(career.group, 'hitting')
self.assertEqual(career.type, 'career')
- self.assertEqual(season_advanced.totalsplits, len(season_advanced.splits))
+ self.assertEqual(season_advanced.total_splits, len(season_advanced.splits))
self.assertEqual(season_advanced.group, 'hitting')
self.assertEqual(season_advanced.type, 'seasonAdvanced')
- self.assertEqual(career_advanced.totalsplits, len(career_advanced.splits))
+ self.assertEqual(career_advanced.total_splits, len(career_advanced.splits))
self.assertEqual(career_advanced.group, 'hitting')
self.assertEqual(career_advanced.type, 'careerAdvanced')
@@ -274,7 +274,7 @@ def test_hitting_pitchlog_stats_player(self):
pitchlog = stats['hitting']['pitchlog']
self.assertTrue(len(pitchlog.splits) > 1)
- self.assertEqual(pitchlog.totalsplits, len(pitchlog.splits))
+ self.assertEqual(pitchlog.total_splits, len(pitchlog.splits))
def test_hitting_pitchlog_stats_player(self):
@@ -298,7 +298,7 @@ def test_hitting_pitchlog_stats_player(self):
# playlogs should return multiple splits
playlogs = stats['hitting']['playlog']
self.assertTrue(len(playlogs.splits) > 1)
- self.assertEqual(playlogs.totalsplits, len(playlogs.splits))
+ self.assertEqual(playlogs.total_splits, len(playlogs.splits))
def test_hitting_pitchArsenal_stats_player(self):
@@ -321,7 +321,7 @@ def test_hitting_pitchArsenal_stats_player(self):
pitcharsenal = stats['stats']['pitcharsenal']
self.assertTrue(len(pitcharsenal.splits) > 1)
- self.assertEqual(pitcharsenal.totalsplits, len(pitcharsenal.splits))
+ self.assertEqual(pitcharsenal.total_splits, len(pitcharsenal.splits))
def test_hitting_hotcoldzones_stats_player(self):
"""mlb get stats should return hitting stats"""
@@ -344,4 +344,4 @@ def test_hitting_hotcoldzones_stats_player(self):
# hotcoldzone should return 5 splits
hotcoldzone = stats['stats']['hotcoldzones']
self.assertEqual(len(hotcoldzone.splits), 5)
- self.assertEqual(hotcoldzone.totalsplits, len(hotcoldzone.splits))
+ self.assertEqual(hotcoldzone.total_splits, len(hotcoldzone.splits))
diff --git a/tests/external_tests/stats/test_pitching.py b/tests/external_tests/stats/test_pitching.py
index 43bb74b5..768a5670 100644
--- a/tests/external_tests/stats/test_pitching.py
+++ b/tests/external_tests/stats/test_pitching.py
@@ -1,4 +1,4 @@
-import unittest
+import unittest
import time
from mlbstatsapi.mlb_api import Mlb
@@ -45,19 +45,19 @@ def test_pitching_stat_attributes_player(self):
season_advanced = stats['pitching']['seasonadvanced']
career_advanced = stats['pitching']['careeradvanced']
- self.assertEqual(season.totalsplits, len(season.splits))
+ self.assertEqual(season.total_splits, len(season.splits))
self.assertEqual(season.group, 'pitching')
self.assertEqual(season.type, 'season')
- self.assertEqual(career.totalsplits, len(career.splits))
+ self.assertEqual(career.total_splits, len(career.splits))
self.assertEqual(career.group, 'pitching')
self.assertEqual(career.type, 'career')
- self.assertEqual(season_advanced.totalsplits, len(season_advanced.splits))
+ self.assertEqual(season_advanced.total_splits, len(season_advanced.splits))
self.assertEqual(season_advanced.group, 'pitching')
self.assertEqual(season_advanced.type, 'seasonAdvanced')
- self.assertEqual(career_advanced.totalsplits, len(career_advanced.splits))
+ self.assertEqual(career_advanced.total_splits, len(career_advanced.splits))
self.assertEqual(career_advanced.group, 'pitching')
self.assertEqual(career_advanced.type, 'careerAdvanced')
@@ -89,19 +89,19 @@ def test_pitching_stat_attributes_team(self):
season_advanced = stats['pitching']['seasonadvanced']
career_advanced = stats['pitching']['careeradvanced']
- self.assertEqual(season.totalsplits, len(season.splits))
+ self.assertEqual(season.total_splits, len(season.splits))
self.assertEqual(season.group, 'pitching')
self.assertEqual(season.type, 'season')
- self.assertEqual(career.totalsplits, len(career.splits))
+ self.assertEqual(career.total_splits, len(career.splits))
self.assertEqual(career.group, 'pitching')
self.assertEqual(career.type, 'career')
- self.assertEqual(season_advanced.totalsplits, len(season_advanced.splits))
+ self.assertEqual(season_advanced.total_splits, len(season_advanced.splits))
self.assertEqual(season_advanced.group, 'pitching')
self.assertEqual(season_advanced.type, 'seasonAdvanced')
- self.assertEqual(career_advanced.totalsplits, len(career_advanced.splits))
+ self.assertEqual(career_advanced.total_splits, len(career_advanced.splits))
self.assertEqual(career_advanced.group, 'pitching')
self.assertEqual(career_advanced.type, 'careerAdvanced')
diff --git a/tests/external_tests/team/test_team.py b/tests/external_tests/team/test_team.py
index 4d7f547f..7de0a507 100644
--- a/tests/external_tests/team/test_team.py
+++ b/tests/external_tests/team/test_team.py
@@ -1,4 +1,5 @@
-import unittest
+import unittest
+from pydantic import ValidationError
from mlbstatsapi.models.teams import Team
from mlbstatsapi.models.venues import Venue
from mlbstatsapi.models.divisions import Division
@@ -17,7 +18,8 @@ def tearDownClass(cls) -> None:
pass
def test_team_instance_type_error(self):
- with self.assertRaises(TypeError):
+ """Pydantic raises ValidationError when required fields are missing."""
+ with self.assertRaises(ValidationError):
team = Team()
def test_team_instance_id_instance_success(self):
@@ -58,4 +60,4 @@ def test_get_teams_for_sport(self):
self.assertIsInstance(self.teams, list)
# teams should not be empty list
- self.assertNotEqual(self.teams, [])
\ No newline at end of file
+ self.assertNotEqual(self.teams, [])
diff --git a/tests/external_tests/venue/test_venue.py b/tests/external_tests/venue/test_venue.py
index 30ae8087..5ed98f14 100644
--- a/tests/external_tests/venue/test_venue.py
+++ b/tests/external_tests/venue/test_venue.py
@@ -1,4 +1,5 @@
import unittest
+from pydantic import ValidationError
from mlbstatsapi.models.venues import Venue
from mlbstatsapi import Mlb
@@ -14,7 +15,8 @@ def tearDownClass(cls) -> None:
pass
def test_venue_instance_type_error(self):
- with self.assertRaises(TypeError):
+ """Pydantic raises ValidationError when required fields are missing."""
+ with self.assertRaises(ValidationError):
venue = Venue()
def test_venue_instance_position_arguments(self):
@@ -30,5 +32,5 @@ def test_venue_attributes(self):
self.assertTrue(hasattr(self.venue, "name"))
self.assertTrue(hasattr(self.venue, "location"))
self.assertTrue(hasattr(self.venue, "timezone"))
- self.assertTrue(hasattr(self.venue, "fieldinfo"))
+ self.assertTrue(hasattr(self.venue, "field_info"))
self.assertTrue(hasattr(self.venue, "active"))
diff --git a/tests/mock_tests/drafts/test_draft_mock.py b/tests/mock_tests/drafts/test_draft_mock.py
index 6c7a48b3..d56065da 100644
--- a/tests/mock_tests/drafts/test_draft_mock.py
+++ b/tests/mock_tests/drafts/test_draft_mock.py
@@ -1,4 +1,4 @@
-from typing import Dict, List
+from typing import Dict, List
from unittest.mock import patch
import unittest
import requests_mock
@@ -57,5 +57,5 @@ def test_get_draft_by_year_id(self, m):
draftpick = draftpicks[0]
- # draft pick should have attrs set
- self.assertTrue(draftpick.pickround)
\ No newline at end of file
+ # draft pick should have attrs set (using Pythonic field name)
+ self.assertTrue(draftpick.pick_round)
\ No newline at end of file
diff --git a/tests/mock_tests/gamepace/test_gamepace_mock.py b/tests/mock_tests/gamepace/test_gamepace_mock.py
index e52500da..99e935b4 100644
--- a/tests/mock_tests/gamepace/test_gamepace_mock.py
+++ b/tests/mock_tests/gamepace/test_gamepace_mock.py
@@ -7,7 +7,7 @@
from mlbstatsapi import Mlb
-from mlbstatsapi.models.gamepace import Gamepace, Gamepacedata
+from mlbstatsapi.models.gamepace import GamePace, GamePaceData
path_to_current_file = os.path.realpath(__file__)
@@ -34,25 +34,25 @@ def test_get_gamepace(self, m):
# set draft id
season_id = 2021
- # call get_gamepace return Gamepace object
+ # call get_gamepace return GamePace object
gamepace = self.mlb.get_gamepace(season_id)
- # Gamepace should not be None
+ # GamePace should not be None
self.assertIsNotNone(gamepace)
- self.assertIsInstance(gamepace, Gamepace)
+ self.assertIsInstance(gamepace, GamePace)
# list should not be empty
self.assertNotEqual(gamepace.sports, [])
# items in list should be gamepace data
- self.assertIsInstance(gamepace.sports[0], Gamepacedata)
+ self.assertIsInstance(gamepace.sports[0], GamePaceData)
sportgamepace = gamepace.sports[0]
# sportgamepace should not be none
self.assertIsNotNone(sportgamepace)
- # sportgamepace should have attrs set
- self.assertTrue(sportgamepace.hitspergame)
- self.assertTrue(sportgamepace.totalgames)
\ No newline at end of file
+ # sportgamepace should have attrs set (using Pythonic names)
+ self.assertTrue(sportgamepace.hits_per_game)
+ self.assertTrue(sportgamepace.total_games)
diff --git a/tests/mock_tests/homerunderby/test_homerunderby_mock.py b/tests/mock_tests/homerunderby/test_homerunderby_mock.py
index c3eaeca7..a1fcf3dd 100644
--- a/tests/mock_tests/homerunderby/test_homerunderby_mock.py
+++ b/tests/mock_tests/homerunderby/test_homerunderby_mock.py
@@ -7,7 +7,7 @@
from mlbstatsapi import Mlb
-from mlbstatsapi.models.homerunderby import Homerunderby, Round
+from mlbstatsapi.models.homerunderby import HomeRunDerby, Round
path_to_current_file = os.path.realpath(__file__)
@@ -31,19 +31,19 @@ def test_get_homerunderby(self, m):
m.get('https://statsapi.mlb.com/api/v1/homeRunDerby/511101', json=self.homerunderby_mock,
status_code=200)
- # set draft id
+ # set game id
game_id = 511101
- # call get_gamepace return Gamepace object
+ # call get_homerun_derby return HomeRunDerby object
derby = self.mlb.get_homerun_derby(game_id)
- # Gamepace should not be None
+ # HomeRunDerby should not be None
self.assertIsNotNone(derby)
- self.assertIsInstance(derby, Homerunderby)
+ self.assertIsInstance(derby, HomeRunDerby)
# list should not be empty
self.assertNotEqual(derby.rounds, [])
- # items in list should be gamepace data
- self.assertIsInstance(derby.rounds[0], Round)
\ No newline at end of file
+ # items in list should be Round
+ self.assertIsInstance(derby.rounds[0], Round)
diff --git a/tests/mock_tests/standings/test_standings_mock.py b/tests/mock_tests/standings/test_standings_mock.py
index bef712fd..f546c98d 100644
--- a/tests/mock_tests/standings/test_standings_mock.py
+++ b/tests/mock_tests/standings/test_standings_mock.py
@@ -51,6 +51,6 @@ def test_get_standings(self, m):
# sportgamepace should not be none
self.assertIsNotNone(standing)
- # sportgamepace should have attrs set
- self.assertTrue(standing.standingstype)
- self.assertTrue(standing.lastupdated)
\ No newline at end of file
+ # standings should have attrs set
+ self.assertTrue(standing.standings_type)
+ self.assertTrue(standing.last_updated)
\ No newline at end of file
diff --git a/tests/mock_tests/stats/test_game_player_stats_for_game.py b/tests/mock_tests/stats/test_game_player_stats_for_game.py
index 54f45171..528dcdd7 100644
--- a/tests/mock_tests/stats/test_game_player_stats_for_game.py
+++ b/tests/mock_tests/stats/test_game_player_stats_for_game.py
@@ -1,4 +1,4 @@
-import unittest
+import unittest
import time
from mlbstatsapi.mlb_api import Mlb
@@ -156,7 +156,7 @@ def test_get_players_stats_for_archie(self, m):
gamelogs = game_stats['stats']['gamelog']
self.assertEqual(len(gamelogs.splits), 3)
- self.assertEqual(gamelogs.totalsplits, len(gamelogs.splits))
+ self.assertEqual(gamelogs.total_splits, len(gamelogs.splits))
vsplayer5y = game_stats['pitching']['vsplayer5y']
diff --git a/tests/mock_tests/stats/test_hitting_stats_mock.py b/tests/mock_tests/stats/test_hitting_stats_mock.py
index 5687e15d..f78d510f 100644
--- a/tests/mock_tests/stats/test_hitting_stats_mock.py
+++ b/tests/mock_tests/stats/test_hitting_stats_mock.py
@@ -1,4 +1,4 @@
-import unittest
+import unittest
import requests_mock
import json
import os
@@ -78,19 +78,19 @@ def test_hitting_stat_attributes_player(self, m):
career_advanced = stats['hitting']['careeradvanced']
# check that attrs exist and contain data
- self.assertEqual(season.totalsplits, len(season.splits))
+ self.assertEqual(season.total_splits, len(season.splits))
self.assertEqual(season.group, 'hitting')
self.assertEqual(season.type, 'season')
- self.assertEqual(career.totalsplits, len(career.splits))
+ self.assertEqual(career.total_splits, len(career.splits))
self.assertEqual(career.group, 'hitting')
self.assertEqual(career.type, 'career')
- self.assertEqual(season_advanced.totalsplits, len(season_advanced.splits))
+ self.assertEqual(season_advanced.total_splits, len(season_advanced.splits))
self.assertEqual(season_advanced.group, 'hitting')
self.assertEqual(season_advanced.type, 'seasonAdvanced')
- self.assertEqual(career_advanced.totalsplits, len(career_advanced.splits))
+ self.assertEqual(career_advanced.total_splits, len(career_advanced.splits))
self.assertEqual(career_advanced.group, 'hitting')
self.assertEqual(career_advanced.type, 'careerAdvanced')
@@ -124,19 +124,19 @@ def test_pitching_stat_attributes_team(self, m):
career_advanced = stats['hitting']['careeradvanced']
# check that attrs exist and contain data
- self.assertEqual(season.totalsplits, len(season.splits))
+ self.assertEqual(season.total_splits, len(season.splits))
self.assertEqual(season.group, 'hitting')
self.assertEqual(season.type, 'season')
- self.assertEqual(career.totalsplits, len(career.splits))
+ self.assertEqual(career.total_splits, len(career.splits))
self.assertEqual(career.group, 'hitting')
self.assertEqual(career.type, 'career')
- self.assertEqual(season_advanced.totalsplits, len(season_advanced.splits))
+ self.assertEqual(season_advanced.total_splits, len(season_advanced.splits))
self.assertEqual(season_advanced.group, 'hitting')
self.assertEqual(season_advanced.type, 'seasonAdvanced')
- self.assertEqual(career_advanced.totalsplits, len(career_advanced.splits))
+ self.assertEqual(career_advanced.total_splits, len(career_advanced.splits))
self.assertEqual(career_advanced.group, 'hitting')
self.assertEqual(career_advanced.type, 'careerAdvanced')
@@ -159,7 +159,7 @@ def test_hitting_hotcoldzones_for_player(self, m):
# hotcoldzone should return 5 splits
hotcoldzone = stats['stats']['hotcoldzones']
self.assertEqual(len(hotcoldzone.splits), 5)
- self.assertEqual(hotcoldzone.totalsplits, len(hotcoldzone.splits))
+ self.assertEqual(hotcoldzone.total_splits, len(hotcoldzone.splits))
# hot cold zone should have 13 zones for each zone type
for split in hotcoldzone.splits:
@@ -187,7 +187,7 @@ def test_hitting_pitchlog_for_player(self, m):
# pitchlog should have 2 splits from mock
pitchlogs = stats['hitting']['pitchlog']
self.assertEqual(len(pitchlogs.splits), 6)
- self.assertEqual(pitchlogs.totalsplits, len(pitchlogs.splits))
+ self.assertEqual(pitchlogs.total_splits, len(pitchlogs.splits))
for pitchlog in pitchlogs.splits:
self.assertTrue(pitchlog.stat.details)
@@ -215,7 +215,7 @@ def test_hitting_playlog_for_player(self, m):
# pitchlog items should have 2 splits
pitchlogs = stats['hitting']['playlog']
self.assertEqual(len(pitchlogs.splits), 2)
- self.assertEqual(pitchlogs.totalsplits, len(pitchlogs.splits))
+ self.assertEqual(pitchlogs.total_splits, len(pitchlogs.splits))
for pitchlog in pitchlogs.splits:
self.assertTrue(pitchlog.stat)
@@ -238,7 +238,7 @@ def test_hitting_spraychart_for_player(self, m):
spraychart = spraychart['stats']['spraychart']
self.assertEqual(len(spraychart.splits), 1)
- self.assertEqual(spraychart.totalsplits, len(spraychart.splits))
+ self.assertEqual(spraychart.total_splits, len(spraychart.splits))
for pitchlog in spraychart.splits:
self.assertTrue(pitchlog.stat)
\ No newline at end of file
diff --git a/tests/mock_tests/stats/test_pitching_stats_mock.py b/tests/mock_tests/stats/test_pitching_stats_mock.py
index fd17f5f0..0e66493d 100644
--- a/tests/mock_tests/stats/test_pitching_stats_mock.py
+++ b/tests/mock_tests/stats/test_pitching_stats_mock.py
@@ -1,4 +1,4 @@
-import unittest
+import unittest
import requests_mock
import json
import os
@@ -78,19 +78,19 @@ def test_pitching_stat_attributes_player(self, m):
season_advanced = stats['pitching']['seasonadvanced']
career_advanced = stats['pitching']['careeradvanced']
- self.assertEqual(season.totalsplits, len(season.splits))
+ self.assertEqual(season.total_splits, len(season.splits))
self.assertEqual(season.group, 'pitching')
self.assertEqual(season.type, 'season')
- self.assertEqual(career.totalsplits, len(career.splits))
+ self.assertEqual(career.total_splits, len(career.splits))
self.assertEqual(career.group, 'pitching')
self.assertEqual(career.type, 'career')
- self.assertEqual(season_advanced.totalsplits, len(season_advanced.splits))
+ self.assertEqual(season_advanced.total_splits, len(season_advanced.splits))
self.assertEqual(season_advanced.group, 'pitching')
self.assertEqual(season_advanced.type, 'seasonAdvanced')
- self.assertEqual(career_advanced.totalsplits, len(career_advanced.splits))
+ self.assertEqual(career_advanced.total_splits, len(career_advanced.splits))
self.assertEqual(career_advanced.group, 'pitching')
self.assertEqual(career_advanced.type, 'careerAdvanced')
@@ -122,19 +122,19 @@ def test_pitching_stat_attributes_team(self, m):
season_advanced = stats['pitching']['seasonadvanced']
career_advanced = stats['pitching']['careeradvanced']
- self.assertEqual(season.totalsplits, len(season.splits))
+ self.assertEqual(season.total_splits, len(season.splits))
self.assertEqual(season.group, 'pitching')
self.assertEqual(season.type, 'season')
- self.assertEqual(career.totalsplits, len(career.splits))
+ self.assertEqual(career.total_splits, len(career.splits))
self.assertEqual(career.group, 'pitching')
self.assertEqual(career.type, 'career')
- self.assertEqual(season_advanced.totalsplits, len(season_advanced.splits))
+ self.assertEqual(season_advanced.total_splits, len(season_advanced.splits))
self.assertEqual(season_advanced.group, 'pitching')
self.assertEqual(season_advanced.type, 'seasonAdvanced')
- self.assertEqual(career_advanced.totalsplits, len(career_advanced.splits))
+ self.assertEqual(career_advanced.total_splits, len(career_advanced.splits))
self.assertEqual(career_advanced.group, 'pitching')
self.assertEqual(career_advanced.type, 'careerAdvanced')
@@ -163,7 +163,7 @@ def test_pitching_play_log_for_player(self, m):
# hotcoldzone should return 5 splits
hotcoldzone = stats['stats']['hotcoldzones']
self.assertEqual(len(hotcoldzone.splits), 5)
- self.assertEqual(hotcoldzone.totalsplits, len(hotcoldzone.splits))
+ self.assertEqual(hotcoldzone.total_splits, len(hotcoldzone.splits))
# hot cold zone should have 13 zones for each zone type
for split in hotcoldzone.splits:
@@ -191,7 +191,7 @@ def test_pitching_pitchlog_for_pitcher(self, m):
# pitchlog should have 2 splits from mock
pitchlogs = stats['pitching']['pitchlog']
self.assertEqual(len(pitchlogs.splits), 2)
- self.assertEqual(pitchlogs.totalsplits, len(pitchlogs.splits))
+ self.assertEqual(pitchlogs.total_splits, len(pitchlogs.splits))
for pitchlog in pitchlogs.splits:
self.assertTrue(pitchlog.stat.details)
@@ -219,7 +219,7 @@ def test_pitching_playlog_for_pitcher(self, m):
# pitchlog items should have 2 splits
pitchlogs = stats['pitching']['playlog']
self.assertEqual(len(pitchlogs.splits), 2)
- self.assertEqual(pitchlogs.totalsplits, len(pitchlogs.splits))
+ self.assertEqual(pitchlogs.total_splits, len(pitchlogs.splits))
for pitchlog in pitchlogs.splits:
self.assertTrue(pitchlog.stat)
@@ -243,7 +243,7 @@ def test_pitching_play_log_for_player(self, m):
spraychart = spraychart['stats']['spraychart']
self.assertEqual(len(spraychart.splits), 1)
- self.assertEqual(spraychart.totalsplits, len(spraychart.splits))
+ self.assertEqual(spraychart.total_splits, len(spraychart.splits))
for pitchlog in spraychart.splits:
self.assertTrue(pitchlog.stat)
\ No newline at end of file
diff --git a/tests/test_base_model.py b/tests/test_base_model.py
new file mode 100644
index 00000000..138109d6
--- /dev/null
+++ b/tests/test_base_model.py
@@ -0,0 +1,22 @@
+from pydantic import Field
+
+from mlbstatsapi.models import MLBBaseModel
+
+
+class Sample(MLBBaseModel):
+ id: int
+ full_name: str = Field(alias="fullName")
+
+
+def test_ignore_extra_fields():
+ obj = Sample(id=1, full_name="Test", extra_field="ignored")
+ assert obj.id == 1
+ assert obj.full_name == "Test"
+ # Extra fields should be ignored and not set as attributes
+ assert not hasattr(obj, "extra_field")
+
+
+def test_populate_by_name_alias():
+ # populate_by_name allows alias population when present
+ obj = Sample(id=1, fullName="Alias Name") # type: ignore[arg-type]
+ assert obj.full_name == "Alias Name"