Skip to content

Commit 0a20b33

Browse files
committed
convert floating point stats from string
1 parent bf81078 commit 0a20b33

7 files changed

Lines changed: 164 additions & 157 deletions

File tree

mlbstatsapi/models/base.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,28 @@
1-
from pydantic import BaseModel, ConfigDict
2-
3-
1+
from pydantic import BaseModel, ConfigDict, BeforeValidator
2+
from typing import Annotated
43
def to_camel_case(value: str) -> str:
54
parts = value.split("_")
65
if not parts:
76
return value
87
return parts[0] + "".join(part[:1].upper() + part[1:] for part in parts[1:])
98

109

10+
def float_or_none(v)-> float | None:
11+
try:
12+
f = float(v)
13+
return f
14+
except (TypeError, ValueError):
15+
return None
16+
17+
OptionalFloat = Annotated[float | None, BeforeValidator(float_or_none)]
18+
1119
class MLBBaseModel(BaseModel):
1220
"""Common base for all MLB Stats API models.
1321
1422
- Pydantic v2
1523
- Ignores unknown fields to remain resilient to API changes
1624
- populate_by_name allows alias-based population when needed
1725
"""
18-
1926
model_config = ConfigDict(
2027
extra="ignore",
2128
alias_generator=to_camel_case,

mlbstatsapi/models/stats/catching.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from typing import Optional, List, ClassVar
22
from pydantic import Field
3-
from mlbstatsapi.models.base import MLBBaseModel
3+
from mlbstatsapi.models.base import MLBBaseModel, OptionalFloat
44
from mlbstatsapi.models.teams import Team
55
from mlbstatsapi.models.game import Game
66
from .stats import Split
@@ -30,23 +30,23 @@ class SimpleCatchingSplit(MLBBaseModel):
3030
The number of hits while catching.
3131
hit_by_pitch : int
3232
The number of batters hit by a pitch while catching.
33-
avg : str
33+
avg : float
3434
The batting average while catching.
3535
at_bats : int
3636
The number of at bats while catching.
37-
obp : str
37+
obp : float
3838
The on base percentage while catching.
39-
slg : str
39+
slg : float
4040
The slugging percentage while catching.
41-
ops : str
41+
ops : float
4242
The on-base slugging while catching.
4343
caught_stealing : int
4444
The number of runners caught stealing by the catcher.
45-
caught_stealing_percentage : str
45+
caught_stealing_percentage : float
4646
Percentage of runners caught stealing by the catcher.
4747
stolen_bases : int
4848
The number of stolen bases while catching.
49-
stolen_base_percentage : str
49+
stolen_base_percentage : float
5050
The stolen base percentage against the catcher.
5151
earned_runs : int
5252
The earned run amount against the catcher.
@@ -62,7 +62,7 @@ class SimpleCatchingSplit(MLBBaseModel):
6262
The number of pick offs while catching.
6363
total_bases : int
6464
The total number of bases.
65-
strikeout_walk_ratio : str
65+
strikeout_walk_ratio : float
6666
The strike out to walk ratio while catching.
6767
catchers_interference : int
6868
The number of times catcher interference committed.
@@ -84,23 +84,23 @@ class SimpleCatchingSplit(MLBBaseModel):
8484
intentional_walks: Optional[int] = Field(default=None, alias="intentionalWalks")
8585
hits: Optional[int] = None
8686
hit_by_pitch: Optional[int] = Field(default=None, alias="hitByPitch")
87-
avg: Optional[str] = None
87+
avg: OptionalFloat = None
8888
at_bats: Optional[int] = Field(default=None, alias="atBats")
89-
obp: Optional[str] = None
90-
slg: Optional[str] = None
91-
ops: Optional[str] = None
89+
obp: OptionalFloat = None
90+
slg: OptionalFloat = None
91+
ops: OptionalFloat = None
9292
caught_stealing: Optional[int] = Field(default=None, alias="caughtStealing")
93-
caught_stealing_percentage: Optional[str] = Field(default=None, alias="caughtStealingPercentage")
93+
caught_stealing_percentage: OptionalFloat = Field(default=None, alias="caughtStealingPercentage")
9494
stolen_bases: Optional[int] = Field(default=None, alias="stolenBases")
95-
stolen_base_percentage: Optional[str] = Field(default=None, alias="stolenBasePercentage")
95+
stolen_base_percentage: OptionalFloat = Field(default=None, alias="stolenBasePercentage")
9696
earned_runs: Optional[int] = Field(default=None, alias="earnedRuns")
9797
batters_faced: Optional[int] = Field(default=None, alias="battersFaced")
9898
games_pitched: Optional[int] = Field(default=None, alias="gamesPitched")
9999
hit_batsmen: Optional[int] = Field(default=None, alias="hitBatsmen")
100100
wild_pitches: Optional[int] = Field(default=None, alias="wildPitches")
101101
pickoffs: Optional[int] = None
102102
total_bases: Optional[int] = Field(default=None, alias="totalBases")
103-
strikeout_walk_ratio: Optional[str] = Field(default=None, alias="strikeoutWalkRatio")
103+
strikeout_walk_ratio: OptionalFloat = Field(default=None, alias="strikeoutWalkRatio")
104104
catchers_interference: Optional[int] = Field(default=None, alias="catchersInterference")
105105
sac_bunts: Optional[int] = Field(default=None, alias="sacBunts")
106106
sac_flies: Optional[int] = Field(default=None, alias="sacFlies")

mlbstatsapi/models/stats/fielding.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from typing import Optional, Any, List, ClassVar
22
from pydantic import Field, field_validator
3-
from mlbstatsapi.models.base import MLBBaseModel
3+
from mlbstatsapi.models.base import MLBBaseModel, OptionalFloat
44
from mlbstatsapi.models.people import Position
55
from mlbstatsapi.models.teams import Team
66
from mlbstatsapi.models.game import Game
@@ -21,11 +21,11 @@ class SimpleFieldingSplit(MLBBaseModel):
2121
The number of games started.
2222
caught_stealing : int
2323
The number of runners caught stealing.
24-
caught_stealing_percentage : str
24+
caught_stealing_percentage : float
2525
The percentage of runners caught stealing.
2626
stolen_bases : int
2727
The number of stolen bases.
28-
stolen_base_percentage : str
28+
stolen_base_percentage : float
2929
The stolen base percentage.
3030
assists : int
3131
The number of assists.
@@ -35,13 +35,13 @@ class SimpleFieldingSplit(MLBBaseModel):
3535
The number of errors committed.
3636
chances : int
3737
The number of chances.
38-
fielding : str
38+
fielding : float
3939
The fielding percentage.
40-
range_factor_per_game : str
40+
range_factor_per_game : float
4141
Range rating per game.
42-
range_factor_per_9_inn : str
42+
range_factor_per_9_inn : float
4343
Range factor per 9 innings.
44-
innings : str
44+
innings : float
4545
The number of innings played.
4646
games : int
4747
The number of games played.
@@ -51,7 +51,7 @@ class SimpleFieldingSplit(MLBBaseModel):
5151
The number of double plays.
5252
triple_plays : int
5353
The number of triple plays.
54-
catcher_era : str
54+
catcher_era : float
5555
The catcher ERA of the fielding stat.
5656
catchers_interference : int
5757
The number of times catchers interference was committed.
@@ -67,22 +67,22 @@ class SimpleFieldingSplit(MLBBaseModel):
6767
games_played: Optional[int] = Field(default=None, alias="gamesPlayed")
6868
games_started: Optional[int] = Field(default=None, alias="gamesStarted")
6969
caught_stealing: Optional[int] = Field(default=None, alias="caughtStealing")
70-
caught_stealing_percentage: Optional[str] = Field(default=None, alias="caughtStealingPercentage")
70+
caught_stealing_percentage: OptionalFloat = Field(default=None, alias="caughtStealingPercentage")
7171
stolen_bases: Optional[int] = Field(default=None, alias="stolenBases")
72-
stolen_base_percentage: Optional[str] = Field(default=None, alias="stolenBasePercentage")
72+
stolen_base_percentage: OptionalFloat = Field(default=None, alias="stolenBasePercentage")
7373
assists: Optional[int] = None
7474
putouts: Optional[int] = None
7575
errors: Optional[int] = None
7676
chances: Optional[int] = None
77-
fielding: Optional[str] = None
78-
range_factor_per_game: Optional[str] = Field(default=None, alias="rangeFactorPerGame")
79-
range_factor_per_9_inn: Optional[str] = Field(default=None, alias="rangeFactorPer9Inn")
80-
innings: Optional[str] = None
77+
fielding: OptionalFloat = None
78+
range_factor_per_game: OptionalFloat = Field(default=None, alias="rangeFactorPerGame")
79+
range_factor_per_9_inn: OptionalFloat = Field(default=None, alias="rangeFactorPer9Inn")
80+
innings: OptionalFloat = None
8181
games: Optional[int] = None
8282
passed_ball: Optional[int] = Field(default=None, alias="passedBall")
8383
double_plays: Optional[int] = Field(default=None, alias="doublePlays")
8484
triple_plays: Optional[int] = Field(default=None, alias="triplePlays")
85-
catcher_era: Optional[str] = Field(default=None, alias="catcherEra")
85+
catcher_era: OptionalFloat = Field(default=None, alias="catcherEra")
8686
catchers_interference: Optional[int] = Field(default=None, alias="catchersInterference")
8787
wild_pitches: Optional[int] = Field(default=None, alias="wildPitches")
8888
throwing_errors: Optional[int] = Field(default=None, alias="throwingErrors")

mlbstatsapi/models/stats/hitting.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from typing import Optional, List, Any, ClassVar
22
from pydantic import Field, field_validator
3-
from mlbstatsapi.models.base import MLBBaseModel
3+
from mlbstatsapi.models.base import MLBBaseModel, OptionalFloat
44
from mlbstatsapi.models.people import Person, Position, Batter, Pitcher
55
from mlbstatsapi.models.teams import Team
66
from mlbstatsapi.models.game import Game
@@ -83,18 +83,18 @@ class AdvancedHittingSplit(MLBBaseModel):
8383
left_on_base: Optional[int] = Field(default=None, alias="leftOnBase")
8484
sac_bunts: Optional[int] = Field(default=None, alias="sacBunts")
8585
sac_flies: Optional[int] = Field(default=None, alias="sacFlies")
86-
babip: Optional[str] = None
86+
babip: OptionalFloat = None
8787
extra_base_hits: Optional[int] = Field(default=None, alias="extraBaseHits")
8888
hit_by_pitch: Optional[int] = Field(default=None, alias="hitByPitch")
8989
gidp: Optional[int] = None
9090
gidp_opp: Optional[int] = Field(default=None, alias="gidpOpp")
9191
number_of_pitches: Optional[int] = Field(default=None, alias="numberOfPitches")
92-
pitches_per_plate_appearance: Optional[str] = Field(default=None, alias="pitchesPerPlateAppearance")
93-
walks_per_plate_appearance: Optional[str] = Field(default=None, alias="walksPerPlateAppearance")
94-
strikeouts_per_plate_appearance: Optional[str] = Field(default=None, alias="strikeoutsPerPlateAppearance")
95-
home_runs_per_plate_appearance: Optional[str] = Field(default=None, alias="homeRunsPerPlateAppearance")
96-
walks_per_strikeout: Optional[str] = Field(default=None, alias="walksPerStrikeout")
97-
iso: Optional[str] = None
92+
pitches_per_plate_appearance: OptionalFloat = Field(default=None, alias="pitchesPerPlateAppearance")
93+
walks_per_plate_appearance: OptionalFloat = Field(default=None, alias="walksPerPlateAppearance")
94+
strikeouts_per_plate_appearance: OptionalFloat = Field(default=None, alias="strikeoutsPerPlateAppearance")
95+
home_runs_per_plate_appearance: OptionalFloat = Field(default=None, alias="homeRunsPerPlateAppearance")
96+
walks_per_strikeout: OptionalFloat = Field(default=None, alias="walksPerStrikeout")
97+
iso: OptionalFloat = None
9898
reached_on_error: Optional[int] = Field(default=None, alias="reachedOnError")
9999
walkoffs: Optional[int] = None
100100
flyouts: Optional[int] = None
@@ -203,15 +203,15 @@ class SimpleHittingSplit(MLBBaseModel):
203203
intentional_walks: Optional[int] = Field(default=None, alias="intentionalWalks")
204204
hits: Optional[int] = None
205205
hit_by_pitch: Optional[int] = Field(default=None, alias="hitByPitch")
206-
avg: Optional[str] = None
206+
avg: OptionalFloat = None
207207
at_bats: Optional[int] = Field(default=None, alias="atBats")
208-
obp: Optional[str] = None
209-
slg: Optional[str] = None
210-
ops: Optional[str] = None
208+
obp: OptionalFloat = None
209+
slg: OptionalFloat = None
210+
ops: OptionalFloat = None
211211
caught_stealing: Optional[int] = Field(default=None, alias="caughtStealing")
212-
caught_stealing_percentage: Optional[str] = Field(default=None, alias="caughtStealingPercentage")
212+
caught_stealing_percentage: OptionalFloat = Field(default=None, alias="caughtStealingPercentage")
213213
stolen_bases: Optional[int] = Field(default=None, alias="stolenBases")
214-
stolen_base_percentage: Optional[str] = Field(default=None, alias="stolenBasePercentage")
214+
stolen_base_percentage: OptionalFloat = Field(default=None, alias="stolenBasePercentage")
215215
ground_into_double_play: Optional[int] = Field(default=None, alias="groundIntoDoublePlay")
216216
ground_into_triple_play: Optional[int] = Field(default=None, alias="groundIntoTriplePlay")
217217
number_of_pitches: Optional[int] = Field(default=None, alias="numberOfPitches")
@@ -221,10 +221,10 @@ class SimpleHittingSplit(MLBBaseModel):
221221
left_on_base: Optional[int] = Field(default=None, alias="leftOnBase")
222222
sac_bunts: Optional[int] = Field(default=None, alias="sacBunts")
223223
sac_flies: Optional[int] = Field(default=None, alias="sacFlies")
224-
babip: Optional[str] = None
225-
groundouts_to_airouts: Optional[str] = Field(default=None, alias="groundoutsToAirouts")
224+
babip: OptionalFloat = None
225+
groundouts_to_airouts: OptionalFloat = Field(default=None, alias="groundoutsToAirouts")
226226
catchers_interference: Optional[int] = Field(default=None, alias="catchersInterference")
227-
at_bats_per_home_run: Optional[str] = Field(default=None, alias="atBatsPerHomeRun")
227+
at_bats_per_home_run: OptionalFloat = Field(default=None, alias="atBatsPerHomeRun")
228228

229229

230230
class HittingWinLoss(Split):

0 commit comments

Comments
 (0)