baseball-api-wrapper 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,32 @@
1
+ """
2
+ baseball_api_wrapper
3
+ ====================
4
+ A Python wrapper for the official MLB Stats API (https://statsapi.mlb.com).
5
+
6
+ Quick start::
7
+
8
+ from baseball_api_wrapper import get_teams
9
+
10
+ teams = get_teams(2024)
11
+ for team in teams:
12
+ print(team["id"], team["name"])
13
+ """
14
+
15
+ from .client import MLBStatsAPIError, MLBStatsClient
16
+ from .modules.teams import get_teams
17
+ from .modules.roster import get_roster
18
+ from .modules.players import get_player_info, get_player_stats, get_player_career_splits
19
+ from .modules.games import get_schedule, get_boxscore, get_game_by_pk
20
+
21
+ __all__ = [
22
+ "MLBStatsClient",
23
+ "MLBStatsAPIError",
24
+ "get_teams",
25
+ "get_roster",
26
+ "get_player_info",
27
+ "get_player_stats",
28
+ "get_player_career_splits",
29
+ "get_schedule",
30
+ "get_boxscore",
31
+ "get_game_by_pk",
32
+ ]
@@ -0,0 +1,86 @@
1
+ """
2
+ MLB Stats API Client
3
+ ====================
4
+ A Python wrapper for the official MLB Stats API (https://statsapi.mlb.com).
5
+
6
+ This module provides a low-level HTTP client that handles request construction,
7
+ error handling, and response parsing for the MLB Stats API.
8
+ """
9
+
10
+ import requests
11
+ from typing import Any, Dict, Optional
12
+
13
+
14
+ class MLBStatsAPIError(Exception):
15
+ """Raised when the MLB Stats API returns an error response."""
16
+
17
+ def __init__(self, status_code: int, message: str):
18
+ self.status_code = status_code
19
+ self.message = message
20
+ super().__init__(f"MLB Stats API error {status_code}: {message}")
21
+
22
+
23
+ class MLBStatsClient:
24
+ """
25
+ Low-level HTTP client for the MLB Stats API.
26
+
27
+ Handles base URL configuration, session management, and common
28
+ request/response logic. Higher-level endpoint wrappers build on
29
+ top of this class.
30
+
31
+ Args:
32
+ base_url: The root URL of the Stats API. Defaults to the
33
+ official production endpoint.
34
+ timeout: Request timeout in seconds. Defaults to 10.
35
+
36
+ Example::
37
+
38
+ client = MLBStatsClient()
39
+ data = client.get("/api/v1/teams", params={"season": "2024", "sportId": 1})
40
+ """
41
+
42
+ DEFAULT_BASE_URL = "https://statsapi.mlb.com"
43
+
44
+ def __init__(
45
+ self,
46
+ base_url: str = DEFAULT_BASE_URL,
47
+ timeout: int = 10,
48
+ ):
49
+ self.base_url = base_url.rstrip("/")
50
+ self.timeout = timeout
51
+ self._session = requests.Session()
52
+ self._session.headers.update({"Accept": "application/json"})
53
+
54
+ def get(self, path: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
55
+ """
56
+ Perform a GET request against the Stats API.
57
+
58
+ Args:
59
+ path: API path, e.g. ``"/api/v1/teams"``.
60
+ params: Optional dictionary of query-string parameters.
61
+
62
+ Returns:
63
+ Parsed JSON response as a Python dictionary.
64
+
65
+ Raises:
66
+ MLBStatsAPIError: If the server returns a non-2xx status code.
67
+ requests.RequestException: On network-level failures.
68
+ """
69
+ url = f"{self.base_url}{path}"
70
+ response = self._session.get(url, params=params, timeout=self.timeout)
71
+
72
+ if not response.ok:
73
+ raise MLBStatsAPIError(response.status_code, response.text)
74
+
75
+ return response.json()
76
+
77
+ def close(self):
78
+ """Close the underlying HTTP session, freeing connection-pool resources."""
79
+ self._session.close()
80
+
81
+ # Support use as a context manager
82
+ def __enter__(self):
83
+ return self
84
+
85
+ def __exit__(self, *_):
86
+ self.close()
File without changes
@@ -0,0 +1,147 @@
1
+ """
2
+ Games
3
+ =====
4
+ Functions for retrieving MLB game schedule and score data from the Stats API.
5
+
6
+ The primary entry point is :func:`get_schedule`, which returns games for a
7
+ given date. By default it fetches regular-season MLB games only.
8
+ """
9
+
10
+ from typing import Any, Dict, List, Optional
11
+
12
+ from ..client import MLBStatsClient
13
+
14
+ _SCHEDULE_PATH = "/api/v1/schedule"
15
+ _BOXSCORE_PATH = "/api/v1/game/{game_pk}/boxscore"
16
+
17
+ MLB_SPORT_ID = 1
18
+
19
+
20
+ def get_schedule(
21
+ date: str,
22
+ sport_id: int = MLB_SPORT_ID,
23
+ game_type: str = "R",
24
+ client: Optional[MLBStatsClient] = None,
25
+ ) -> List[Dict[str, Any]]:
26
+ """
27
+ Return all games scheduled for the given date.
28
+
29
+ Args:
30
+ date:
31
+ The date to query in ``YYYY-MM-DD`` format, e.g. ``"2024-04-01"``.
32
+ sport_id:
33
+ Top-level sport identifier. Use ``1`` (default) for MLB.
34
+ game_type:
35
+ Game type filter. ``"R"`` (default) returns regular-season games.
36
+ Pass ``"S"`` for spring training, ``"P"`` for playoffs, or ``"A"``
37
+ for the All-Star game.
38
+ client:
39
+ Optional pre-configured :class:`~baseball_api_wrapper.client.MLBStatsClient`.
40
+ If omitted, a default client is created for this single call.
41
+
42
+ Returns:
43
+ A list of game dictionaries as returned by the MLB Stats API
44
+ ``/api/v1/schedule`` endpoint. Returns an empty list when no games
45
+ are scheduled for the requested date.
46
+
47
+ Raises:
48
+ baseball_api_wrapper.client.MLBStatsAPIError:
49
+ If the API returns a non-2xx HTTP status code.
50
+ requests.RequestException:
51
+ On network-level failures.
52
+ """
53
+ params: Dict[str, Any] = {
54
+ "sportId": sport_id,
55
+ "date": date,
56
+ "gameType": game_type,
57
+ }
58
+
59
+ _owns_client = client is None
60
+ if _owns_client:
61
+ client = MLBStatsClient()
62
+
63
+ try:
64
+ data = client.get(_SCHEDULE_PATH, params=params)
65
+ finally:
66
+ if _owns_client:
67
+ client.close()
68
+
69
+ dates = data.get("dates", [])
70
+ if not dates:
71
+ return []
72
+ return dates[0].get("games", [])
73
+
74
+
75
+ def get_game_by_pk(
76
+ game_pk: int,
77
+ client: Optional[MLBStatsClient] = None,
78
+ ) -> Dict[str, Any]:
79
+ """
80
+ Return the schedule entry for a single game by its ``gamePk``.
81
+
82
+ Useful for fetching lightweight metadata (status, date, teams) without
83
+ the full boxscore payload.
84
+
85
+ Args:
86
+ game_pk: The unique game identifier.
87
+ client: Optional pre-configured :class:`~baseball_api_wrapper.client.MLBStatsClient`.
88
+
89
+ Returns:
90
+ The game dictionary for the requested ``gamePk``, or an empty dict
91
+ if the game is not found.
92
+ """
93
+ params: Dict[str, Any] = {"gamePks": game_pk, "sportId": MLB_SPORT_ID}
94
+
95
+ _owns_client = client is None
96
+ if _owns_client:
97
+ client = MLBStatsClient()
98
+
99
+ try:
100
+ data = client.get(_SCHEDULE_PATH, params=params)
101
+ finally:
102
+ if _owns_client:
103
+ client.close()
104
+
105
+ dates = data.get("dates", [])
106
+ if not dates:
107
+ return {}
108
+ games = dates[0].get("games", [])
109
+ return games[0] if games else {}
110
+
111
+
112
+ def get_boxscore(
113
+ game_pk: int,
114
+ client: Optional[MLBStatsClient] = None,
115
+ ) -> Dict[str, Any]:
116
+ """
117
+ Return the box score for a single game.
118
+
119
+ Args:
120
+ game_pk:
121
+ The unique game identifier (``gamePk``) returned by
122
+ :func:`get_schedule`.
123
+ client:
124
+ Optional pre-configured :class:`~baseball_api_wrapper.client.MLBStatsClient`.
125
+ If omitted, a default client is created for this single call.
126
+
127
+ Returns:
128
+ The raw box score dictionary as returned by the MLB Stats API
129
+ ``/api/v1/game/{gamePk}/boxscore`` endpoint.
130
+
131
+ Raises:
132
+ baseball_api_wrapper.client.MLBStatsAPIError:
133
+ If the API returns a non-2xx HTTP status code.
134
+ requests.RequestException:
135
+ On network-level failures.
136
+ """
137
+ path = _BOXSCORE_PATH.format(game_pk=game_pk)
138
+
139
+ _owns_client = client is None
140
+ if _owns_client:
141
+ client = MLBStatsClient()
142
+
143
+ try:
144
+ return client.get(path)
145
+ finally:
146
+ if _owns_client:
147
+ client.close()
@@ -0,0 +1,178 @@
1
+ """
2
+ Players
3
+ =======
4
+ Functions for retrieving player information and statistics from the MLB Stats API.
5
+
6
+ The two primary entry points are:
7
+
8
+ * :func:`get_player_info` – Basic biographical data for a player.
9
+ * :func:`get_player_stats` – Season statistics for a player, split by group
10
+ (``"hitting"`` or ``"pitching"``).
11
+ """
12
+
13
+ from typing import Any, Dict, List, Optional
14
+
15
+ from ..client import MLBStatsClient
16
+
17
+ _PLAYER_INFO_PATH = "/api/v1/people/{player_id}"
18
+ _PLAYER_STATS_PATH = "/api/v1/people/{player_id}/stats"
19
+
20
+
21
+ def get_player_career_splits(
22
+ player_id: int,
23
+ group: str = "hitting",
24
+ client: Optional[MLBStatsClient] = None,
25
+ ) -> List[Dict[str, Any]]:
26
+ """
27
+ Return year-by-year career splits for a player.
28
+
29
+ Each element in the returned list is a split dict with at minimum:
30
+ * ``season`` – The season year as a string, e.g. ``"2024"``.
31
+ * ``stat`` – Dict of raw stat fields for that season.
32
+
33
+ Args:
34
+ player_id: The player's unique MLB identifier.
35
+ group: ``"hitting"`` or ``"pitching"``. Defaults to ``"hitting"``.
36
+ client: Optional pre-configured MLBStatsClient.
37
+
38
+ Returns:
39
+ A list of split dicts, one per season, or an empty list if none found.
40
+ """
41
+ path = _PLAYER_STATS_PATH.format(player_id=player_id)
42
+ params: Dict[str, Any] = {"stats": "yearByYear", "group": group, "hydrate": "team"}
43
+
44
+ _owns_client = client is None
45
+ if _owns_client:
46
+ client = MLBStatsClient()
47
+
48
+ try:
49
+ data = client.get(path, params=params)
50
+ finally:
51
+ if _owns_client:
52
+ client.close()
53
+
54
+ for stat_block in data.get("stats", []):
55
+ splits = stat_block.get("splits", [])
56
+ if splits:
57
+ return splits
58
+
59
+ return []
60
+
61
+
62
+ def get_player_info(
63
+ player_id: int,
64
+ client: Optional[MLBStatsClient] = None,
65
+ ) -> Dict[str, Any]:
66
+ """
67
+ Return biographical information for a single player.
68
+
69
+ The returned dict contains at minimum:
70
+
71
+ * ``id`` – Player's unique MLB identifier.
72
+ * ``fullName`` – Full display name.
73
+ * ``primaryPosition`` – Nested dict with ``code``, ``name``, ``type``,
74
+ ``abbreviation``.
75
+ * ``active`` – Boolean indicating whether the player is active.
76
+
77
+ Args:
78
+ player_id:
79
+ The player's unique MLB identifier, e.g. ``660271`` for Juan Soto.
80
+ client:
81
+ Optional pre-configured :class:`~baseball_api_wrapper.client.MLBStatsClient`.
82
+ If omitted, a default client is created for the single call.
83
+
84
+ Returns:
85
+ A dict of player attributes as returned by the MLB Stats API.
86
+
87
+ Raises:
88
+ mlb_statsapi.client.MLBStatsAPIError:
89
+ If the API returns a non-2xx HTTP status code.
90
+ requests.RequestException:
91
+ On network-level failures.
92
+ KeyError:
93
+ If the response contains no ``people`` entry for the given ID.
94
+ """
95
+ path = _PLAYER_INFO_PATH.format(player_id=player_id)
96
+
97
+ _owns_client = client is None
98
+ if _owns_client:
99
+ client = MLBStatsClient()
100
+
101
+ try:
102
+ data = client.get(path)
103
+ finally:
104
+ if _owns_client:
105
+ client.close()
106
+
107
+ people: List[Dict[str, Any]] = data.get("people", [])
108
+ if not people:
109
+ raise KeyError(f"No player found with id {player_id}")
110
+
111
+ return people[0]
112
+
113
+
114
+ def get_player_stats(
115
+ player_id: int,
116
+ season: int | str,
117
+ group: str = "hitting",
118
+ client: Optional[MLBStatsClient] = None,
119
+ ) -> Optional[Dict[str, Any]]:
120
+ """
121
+ Return season statistics for a player for a specific stat group.
122
+
123
+ Args:
124
+ player_id:
125
+ The player's unique MLB identifier.
126
+ season:
127
+ The MLB season year, e.g. ``2024`` or ``"2024"``.
128
+ group:
129
+ The stat group to retrieve: ``"hitting"`` or ``"pitching"``.
130
+ Defaults to ``"hitting"``.
131
+ client:
132
+ Optional pre-configured :class:`~baseball_api_wrapper.client.MLBStatsClient`.
133
+ If omitted, a default client is created for the single call.
134
+
135
+ Returns:
136
+ A dict of raw stat fields as returned by the MLB Stats API (the
137
+ ``stat`` object from the first split), or ``None`` if no stats are
138
+ available for this player/season/group combination.
139
+
140
+ Raises:
141
+ mlb_statsapi.client.MLBStatsAPIError:
142
+ If the API returns a non-2xx HTTP status code.
143
+ requests.RequestException:
144
+ On network-level failures.
145
+
146
+ Example::
147
+
148
+ from baseball_api_wrapper.modules.players import get_player_stats
149
+
150
+ # Juan Soto's 2024 hitting stats
151
+ stats = get_player_stats(660271, 2024, group="hitting")
152
+ if stats:
153
+ print(stats["avg"], stats["homeRuns"], stats["rbi"])
154
+ """
155
+ path = _PLAYER_STATS_PATH.format(player_id=player_id)
156
+
157
+ params: Dict[str, Any] = {
158
+ "stats": "season",
159
+ "season": str(season),
160
+ "group": group,
161
+ }
162
+
163
+ _owns_client = client is None
164
+ if _owns_client:
165
+ client = MLBStatsClient()
166
+
167
+ try:
168
+ data = client.get(path, params=params)
169
+ finally:
170
+ if _owns_client:
171
+ client.close()
172
+
173
+ for stat_block in data.get("stats", []):
174
+ splits = stat_block.get("splits", [])
175
+ if splits:
176
+ return splits[0].get("stat")
177
+
178
+ return None
@@ -0,0 +1,164 @@
1
+ """
2
+ Roster
3
+ ======
4
+ Functions for retrieving team roster data from the MLB Stats API.
5
+
6
+ The primary entry point is :func:`get_roster`, which returns the list of
7
+ players (or coaches) on a team's roster for a given season.
8
+
9
+ Roster Types
10
+ ------------
11
+ The API supports several roster types, all exposed via the :class:`RosterType`
12
+ enum. The most commonly used types are:
13
+
14
+ * ``ACTIVE`` – The 26-man active roster (in-season).
15
+ * ``FORTY_MAN`` – The full 40-man roster.
16
+ * ``FULL_SEASON`` – Everyone who appeared on the roster at any point
17
+ during the season.
18
+ * ``FULL_ROSTER`` – Alias similar to FULL_SEASON.
19
+ * ``NON_ROSTER_INVITEES`` – Spring training non-roster invitees.
20
+ * ``DEPTH_CHART`` – Organizational depth chart.
21
+ * ``GAMEDAY`` – Roster for a specific game day.
22
+ * ``ALL_TIME`` – All-time historical roster.
23
+ * ``COACH`` – Coaching staff.
24
+ """
25
+
26
+ from enum import Enum
27
+ from typing import Any, Dict, List, Optional
28
+
29
+ from ..client import MLBStatsClient
30
+
31
+ # API path template for the roster endpoint. teamId is a required path param.
32
+ _ROSTER_PATH = "/api/v1/teams/{team_id}/roster"
33
+
34
+
35
+ class RosterType(str, Enum):
36
+ """
37
+ Valid roster type identifiers accepted by the MLB Stats API.
38
+
39
+ Inherits from ``str`` so values can be passed directly wherever a
40
+ string is expected (e.g. as a query parameter).
41
+ """
42
+
43
+ ACTIVE = "active"
44
+ FORTY_MAN = "40Man"
45
+ FULL_SEASON = "fullSeason"
46
+ FULL_ROSTER = "fullRoster"
47
+ NON_ROSTER_INVITEES = "nonRosterInvitees"
48
+ DEPTH_CHART = "depthChart"
49
+ GAMEDAY = "gameday"
50
+ ALL_TIME = "allTime"
51
+ COACH = "coach"
52
+
53
+
54
+ def get_roster(
55
+ team_id: int,
56
+ season: int | str,
57
+ roster_type: RosterType | str = RosterType.ACTIVE,
58
+ date: Optional[str] = None,
59
+ client: Optional[MLBStatsClient] = None,
60
+ ) -> List[Dict[str, Any]]:
61
+ """
62
+ Return the roster for a team in a given MLB season.
63
+
64
+ Each entry in the returned list represents a single player (or coach,
65
+ depending on *roster_type*) and contains at minimum:
66
+
67
+ * ``person`` – dict with ``id``, ``fullName``, ``link``
68
+ * ``jerseyNumber`` – string jersey number
69
+ * ``position`` – dict with ``code``, ``name``, ``type``,
70
+ ``abbreviation``
71
+ * ``status`` – dict describing roster transaction status
72
+ * ``parentTeamId`` – ID of the parent MLB club
73
+
74
+ Args:
75
+ team_id:
76
+ Unique team identifier, e.g. ``147`` for the New York Yankees.
77
+ Team IDs can be retrieved via :func:`~mlb_statsapi.teams.get_teams`.
78
+ season:
79
+ The MLB season year, e.g. ``2024`` or ``"2024"``.
80
+ roster_type:
81
+ The type of roster to retrieve. Accepts a :class:`RosterType`
82
+ member or the equivalent raw string value. Defaults to
83
+ :attr:`RosterType.ACTIVE` (the 26-man active roster).
84
+ date:
85
+ Optional date string in ``"YYYY-MM-DD"`` format. When provided,
86
+ the roster is returned as it stood on that date. Useful with
87
+ ``roster_type=RosterType.GAMEDAY``.
88
+ client:
89
+ Optional pre-configured :class:`~mlb_statsapi.client.MLBStatsClient`
90
+ instance. If omitted, a default client pointing at the official
91
+ production endpoint is created and used for the single call.
92
+
93
+ Returns:
94
+ A list of roster-entry dictionaries as returned by the MLB Stats API.
95
+ Returns an empty list if the API response contains no roster entries.
96
+
97
+ Raises:
98
+ mlb_statsapi.client.MLBStatsAPIError:
99
+ If the API returns a non-2xx HTTP status code (e.g. 404 for an
100
+ unknown team ID).
101
+ requests.RequestException:
102
+ On network-level failures (timeouts, DNS errors, etc.).
103
+ ValueError:
104
+ If *date* is provided but does not match the ``YYYY-MM-DD`` format.
105
+
106
+ Example::
107
+
108
+ from mlb_statsapi.roster import get_roster, RosterType
109
+
110
+ # Active 26-man roster for the 2024 Yankees
111
+ roster = get_roster(147, 2024)
112
+ for entry in roster:
113
+ print(entry["jerseyNumber"], entry["person"]["fullName"])
114
+
115
+ # Full 40-man roster
116
+ roster_40 = get_roster(147, 2024, roster_type=RosterType.FORTY_MAN)
117
+
118
+ # Roster as of a specific date
119
+ roster_date = get_roster(147, 2024, date="2024-07-04")
120
+ """
121
+ if date is not None:
122
+ _validate_date(date)
123
+
124
+ path = _ROSTER_PATH.format(team_id=team_id)
125
+
126
+ params: Dict[str, Any] = {
127
+ "season": str(season),
128
+ "rosterType": roster_type.value if isinstance(roster_type, RosterType) else roster_type,
129
+ }
130
+
131
+ if date is not None:
132
+ params["date"] = date
133
+
134
+ _owns_client = client is None
135
+ if _owns_client:
136
+ client = MLBStatsClient()
137
+
138
+ try:
139
+ data = client.get(path, params=params)
140
+ finally:
141
+ if _owns_client:
142
+ client.close()
143
+
144
+ return data.get("roster", [])
145
+
146
+
147
+ def _validate_date(date: str) -> None:
148
+ """
149
+ Ensure *date* matches the ``YYYY-MM-DD`` format expected by the API.
150
+
151
+ Args:
152
+ date: Date string to validate.
153
+
154
+ Raises:
155
+ ValueError: If the string is not a valid ``YYYY-MM-DD`` date.
156
+ """
157
+ import datetime
158
+
159
+ try:
160
+ datetime.date.fromisoformat(date)
161
+ except ValueError:
162
+ raise ValueError(
163
+ f"date must be in YYYY-MM-DD format, got {date!r}"
164
+ )
@@ -0,0 +1,142 @@
1
+ """
2
+ Teams
3
+ =====
4
+ Functions for retrieving MLB team data from the Stats API.
5
+
6
+ The primary entry point is :func:`get_teams`, which returns a list of teams
7
+ for a given MLB season. Optional filters let callers narrow results by
8
+ league, division, or active status.
9
+
10
+ MLB Sport IDs
11
+ -------------
12
+ The Stats API serves data for multiple sports / levels. When fetching
13
+ official MLB teams you almost always want ``sport_id=1`` (the default).
14
+
15
+ Common sport IDs:
16
+ * 1 – MLB (majors)
17
+ * 11 – Triple-A
18
+ * 12 – Double-A
19
+ * 13 – High-A
20
+ * 14 – Single-A
21
+
22
+ Common league IDs:
23
+ * 103 – American League
24
+ * 104 – National League
25
+ """
26
+
27
+ from typing import Any, Dict, List, Optional
28
+
29
+ from ..client import MLBStatsClient
30
+
31
+ # The Stats API path for the teams collection resource.
32
+ _TEAMS_PATH = "/api/v1/teams"
33
+
34
+ # Sport ID for MLB (major leagues).
35
+ MLB_SPORT_ID = 1
36
+
37
+
38
+ def get_teams(
39
+ season: int | str,
40
+ sport_id: int = MLB_SPORT_ID,
41
+ league_ids: Optional[List[int]] = None,
42
+ division_id: Optional[int] = None,
43
+ active_status: Optional[str] = None,
44
+ client: Optional[MLBStatsClient] = None,
45
+ ) -> List[Dict[str, Any]]:
46
+ """
47
+ Return a list of MLB teams for the specified season.
48
+
49
+ Each team is represented as a dictionary containing at minimum:
50
+ ``id``, ``name``, ``teamCode``, ``abbreviation``, ``teamName``,
51
+ ``locationName``, ``league``, ``division``, and ``venue``.
52
+
53
+ Args:
54
+ season:
55
+ The MLB season year to query, e.g. ``2024`` or ``"2024"``.
56
+ sport_id:
57
+ Top-level sport identifier. Use ``1`` (default) for MLB
58
+ major-league teams. Pass a different value to retrieve teams
59
+ from the minors or other affiliated leagues.
60
+ league_ids:
61
+ Optional list of league IDs to filter results. For example,
62
+ ``[103]`` returns only American League teams and ``[104]``
63
+ returns only National League teams.
64
+ division_id:
65
+ Optional single division ID to restrict results to one division
66
+ (e.g. ``200`` for AL West).
67
+ active_status:
68
+ Controls which teams are included based on their franchise
69
+ status. Accepted values:
70
+
71
+ * ``"Y"`` – active franchises only (default API behaviour)
72
+ * ``"N"`` – inactive / historical franchises only
73
+ * ``"P"`` – pending franchises
74
+ * ``"B"`` – all franchises regardless of status
75
+
76
+ client:
77
+ Optional pre-configured :class:`~mlb_statsapi.client.MLBStatsClient`
78
+ instance. If omitted, a default client pointing at the official
79
+ production endpoint is created and used for the single call.
80
+
81
+ Returns:
82
+ A list of team dictionaries as returned by the MLB Stats API.
83
+ Returns an empty list if the API response contains no teams.
84
+
85
+ Raises:
86
+ mlb_statsapi.client.MLBStatsAPIError:
87
+ If the API returns a non-2xx HTTP status code.
88
+ requests.RequestException:
89
+ On network-level failures (timeouts, DNS errors, etc.).
90
+ ValueError:
91
+ If *active_status* is not one of the accepted values.
92
+
93
+ Example::
94
+
95
+ from mlb_statsapi.teams import get_teams
96
+
97
+ # All 30 MLB teams for the 2024 season
98
+ teams = get_teams(2024)
99
+ for team in teams:
100
+ print(team["id"], team["name"])
101
+
102
+ # Only American League teams
103
+ al_teams = get_teams(2024, league_ids=[103])
104
+
105
+ # All historical franchises (active + inactive)
106
+ all_franchises = get_teams(2024, active_status="B")
107
+ """
108
+ valid_statuses = {"Y", "N", "P", "B"}
109
+ if active_status is not None and active_status not in valid_statuses:
110
+ raise ValueError(
111
+ f"active_status must be one of {sorted(valid_statuses)}, "
112
+ f"got {active_status!r}"
113
+ )
114
+
115
+ params: Dict[str, Any] = {
116
+ "season": str(season),
117
+ "sportId": sport_id,
118
+ }
119
+
120
+ if league_ids is not None:
121
+ # The API accepts a comma-separated list for leagueIds.
122
+ params["leagueIds"] = ",".join(str(lid) for lid in league_ids)
123
+
124
+ if division_id is not None:
125
+ params["divisionId"] = division_id
126
+
127
+ if active_status is not None:
128
+ params["activeStatus"] = active_status
129
+
130
+ # Allow callers to inject a client (useful for testing / custom config).
131
+ # If none is provided, create a throw-away default client.
132
+ _owns_client = client is None
133
+ if _owns_client:
134
+ client = MLBStatsClient()
135
+
136
+ try:
137
+ data = client.get(_TEAMS_PATH, params=params)
138
+ finally:
139
+ if _owns_client:
140
+ client.close()
141
+
142
+ return data.get("teams", [])
@@ -0,0 +1,102 @@
1
+ Metadata-Version: 2.4
2
+ Name: baseball-api-wrapper
3
+ Version: 0.1.0
4
+ Summary: A Python wrapper for the official MLB Stats API (https://statsapi.mlb.com)
5
+ License-Expression: MIT
6
+ Requires-Python: >=3.9
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Requires-Dist: requests>=2.28
10
+ Provides-Extra: dev
11
+ Requires-Dist: pytest>=7.0; extra == "dev"
12
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
13
+ Requires-Dist: responses>=0.23; extra == "dev"
14
+ Dynamic: license-file
15
+
16
+ # baseball-api-wrapper
17
+
18
+ A Python wrapper for the official [MLB Stats API](https://statsapi.mlb.com).
19
+
20
+ ## Installation
21
+
22
+ Clone the repo and install in editable mode so changes to the source are reflected immediately:
23
+
24
+ ```bash
25
+ git clone <your-repo-url>
26
+ cd baseball-api-wrapper
27
+ pip install -e ".[dev]" # includes pytest and test dependencies
28
+ ```
29
+
30
+ For use in another project without dev tools:
31
+
32
+ ```bash
33
+ pip install -e /path/to/baseball-api-wrapper
34
+ ```
35
+
36
+ ## Quick Start
37
+
38
+ ```python
39
+ from baseball_api_wrapper import get_teams, get_roster
40
+
41
+ # List all MLB teams for the 2024 season
42
+ teams = get_teams(2024)
43
+ for team in teams:
44
+ print(team["id"], team["name"])
45
+
46
+ # Get the active roster for the New York Yankees (teamId=147)
47
+ roster = get_roster(147, season=2024)
48
+ for player in roster:
49
+ print(player["person"]["fullName"], player["position"]["name"])
50
+ ```
51
+
52
+ ## Using the Low-Level Client
53
+
54
+ For endpoints not yet covered by a module, use `MLBStatsClient` directly:
55
+
56
+ ```python
57
+ from baseball_api_wrapper import MLBStatsClient
58
+
59
+ with MLBStatsClient() as client:
60
+ data = client.get("/api/v1/standings", params={"leagueId": 103, "season": 2024})
61
+ print(data)
62
+ ```
63
+
64
+ ## Project Structure
65
+
66
+ ```
67
+ baseball_api_wrapper/ # Installable package
68
+ __init__.py # Public API surface
69
+ client.py # Low-level HTTP client (MLBStatsClient, MLBStatsAPIError)
70
+ modules/
71
+ teams.py # get_teams()
72
+ roster.py # get_roster()
73
+ tests/ # pytest test suite
74
+ test_teams.py
75
+ test_roster.py
76
+ pyproject.toml # Build & dependency config
77
+ ```
78
+
79
+ ## Running Tests
80
+
81
+ ```bash
82
+ pytest # Run all tests
83
+ pytest --cov=baseball_api_wrapper # Run with coverage report
84
+ ```
85
+
86
+ ## Error Handling
87
+
88
+ Network or API errors raise `MLBStatsAPIError`:
89
+
90
+ ```python
91
+ from baseball_api_wrapper import MLBStatsClient, MLBStatsAPIError
92
+
93
+ try:
94
+ with MLBStatsClient() as client:
95
+ data = client.get("/api/v1/teams/99999") # Non-existent team
96
+ except MLBStatsAPIError as e:
97
+ print(f"API error {e.status_code}: {e.message}")
98
+ ```
99
+
100
+ ## License
101
+
102
+ MIT — see [LICENSE](LICENSE) for details.
@@ -0,0 +1,12 @@
1
+ baseball_api_wrapper/__init__.py,sha256=CXwPig_Ts_GRRsGpxOr6gr_vqP7HBqhKIT-9oGqr9pE,807
2
+ baseball_api_wrapper/client.py,sha256=fp0_fV8O0Lv-SL6eBoopINeLddn133Yiv7JQeDdh7jU,2605
3
+ baseball_api_wrapper/modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ baseball_api_wrapper/modules/games.py,sha256=4QGc77PJsuuPFEQREgF54VqeVdNCA62s467WNSP3QBU,4167
5
+ baseball_api_wrapper/modules/players.py,sha256=8zg1xMO81u21brAb1eBrBGL1encRNQBq62D2tW7kX-c,5359
6
+ baseball_api_wrapper/modules/roster.py,sha256=yHsZJ5_aikR4_b2kfl3SAh4MyntRgB75qsseZGoINIw,5422
7
+ baseball_api_wrapper/modules/teams.py,sha256=HyuNS-IVTVddZY3bfOFA5PDsvwylHlXxZiffki789M0,4649
8
+ baseball_api_wrapper-0.1.0.dist-info/licenses/LICENSE,sha256=ESYyLizI0WWtxMeS7rGVcX3ivMezm-HOd5WdeOh-9oU,1056
9
+ baseball_api_wrapper-0.1.0.dist-info/METADATA,sha256=9US0YflCIZVMWreIhtOdy0WQ86agK894tYQj6ltG3Dc,2591
10
+ baseball_api_wrapper-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
11
+ baseball_api_wrapper-0.1.0.dist-info/top_level.txt,sha256=Xywgv0rkNorrhzYPkSVaq1QJ7dvwrmSK3srpp1F5Xr8,21
12
+ baseball_api_wrapper-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ baseball_api_wrapper