polars-baseball 0.1.0__tar.gz

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.
Files changed (98) hide show
  1. polars_baseball-0.1.0/LICENSE +21 -0
  2. polars_baseball-0.1.0/MANIFEST.in +4 -0
  3. polars_baseball-0.1.0/PKG-INFO +255 -0
  4. polars_baseball-0.1.0/README.md +210 -0
  5. polars_baseball-0.1.0/polars_baseball/__init__.py +108 -0
  6. polars_baseball-0.1.0/polars_baseball/_cache.py +442 -0
  7. polars_baseball-0.1.0/polars_baseball/_client.py +216 -0
  8. polars_baseball-0.1.0/polars_baseball/_config.py +58 -0
  9. polars_baseball-0.1.0/polars_baseball/_encoding.py +11 -0
  10. polars_baseball-0.1.0/polars_baseball/_json_types.py +3 -0
  11. polars_baseball-0.1.0/polars_baseball/_json_utils.py +20 -0
  12. polars_baseball-0.1.0/polars_baseball/_schema_utils.py +27 -0
  13. polars_baseball-0.1.0/polars_baseball/_schemas/__init__.py +1 -0
  14. polars_baseball-0.1.0/polars_baseball/_schemas/mlb.py +331 -0
  15. polars_baseball-0.1.0/polars_baseball/_schemas/retrosheet.py +202 -0
  16. polars_baseball-0.1.0/polars_baseball/_season.py +112 -0
  17. polars_baseball-0.1.0/polars_baseball/_validation.py +35 -0
  18. polars_baseball-0.1.0/polars_baseball/apis/_leaderboard_registry.py +179 -0
  19. polars_baseball-0.1.0/polars_baseball/apis/bref.py +82 -0
  20. polars_baseball-0.1.0/polars_baseball/apis/fangraphs.py +250 -0
  21. polars_baseball-0.1.0/polars_baseball/apis/lahman.py +210 -0
  22. polars_baseball-0.1.0/polars_baseball/apis/mlb/__init__.py +42 -0
  23. polars_baseball-0.1.0/polars_baseball/apis/mlb/_contracts.py +294 -0
  24. polars_baseball-0.1.0/polars_baseball/apis/mlb/draft.py +80 -0
  25. polars_baseball-0.1.0/polars_baseball/apis/mlb/game.py +323 -0
  26. polars_baseball-0.1.0/polars_baseball/apis/mlb/people.py +124 -0
  27. polars_baseball-0.1.0/polars_baseball/apis/mlb/roster.py +81 -0
  28. polars_baseball-0.1.0/polars_baseball/apis/mlb/schedule.py +144 -0
  29. polars_baseball-0.1.0/polars_baseball/apis/mlb/stats.py +310 -0
  30. polars_baseball-0.1.0/polars_baseball/apis/mlb/taxonomy.py +176 -0
  31. polars_baseball-0.1.0/polars_baseball/apis/mlb/team_lookup.py +37 -0
  32. polars_baseball-0.1.0/polars_baseball/apis/mlb/transactions.py +92 -0
  33. polars_baseball-0.1.0/polars_baseball/apis/mlb/venues.py +80 -0
  34. polars_baseball-0.1.0/polars_baseball/apis/playerid.py +281 -0
  35. polars_baseball-0.1.0/polars_baseball/apis/retrosheet.py +260 -0
  36. polars_baseball-0.1.0/polars_baseball/apis/savant_fielding_running.py +205 -0
  37. polars_baseball-0.1.0/polars_baseball/apis/savant_gamefeed.py +87 -0
  38. polars_baseball-0.1.0/polars_baseball/apis/savant_leaderboards.py +382 -0
  39. polars_baseball-0.1.0/polars_baseball/apis/standings.py +121 -0
  40. polars_baseball-0.1.0/polars_baseball/apis/statcast.py +250 -0
  41. polars_baseball-0.1.0/polars_baseball/apis/teamid.py +43 -0
  42. polars_baseball-0.1.0/polars_baseball/apis/top_prospects.py +161 -0
  43. polars_baseball-0.1.0/polars_baseball/context.py +85 -0
  44. polars_baseball-0.1.0/polars_baseball/data/fangraphs_teams.csv +2936 -0
  45. polars_baseball-0.1.0/polars_baseball/data/statcast_valid_dates.json +21 -0
  46. polars_baseball-0.1.0/polars_baseball/enums/__init__.py +13 -0
  47. polars_baseball-0.1.0/polars_baseball/enums/enum_base.py +45 -0
  48. polars_baseball-0.1.0/polars_baseball/enums/fangraphs/__init__.py +58 -0
  49. polars_baseball-0.1.0/polars_baseball/enums/fangraphs/batting_data_enum.py +394 -0
  50. polars_baseball-0.1.0/polars_baseball/enums/fangraphs/fangraphs_stats_base.py +55 -0
  51. polars_baseball-0.1.0/polars_baseball/enums/fangraphs/fangraphs_stats_category.py +12 -0
  52. polars_baseball-0.1.0/polars_baseball/enums/fangraphs/fielding_data_enum.py +100 -0
  53. polars_baseball-0.1.0/polars_baseball/enums/fangraphs/league.py +19 -0
  54. polars_baseball-0.1.0/polars_baseball/enums/fangraphs/month.py +15 -0
  55. polars_baseball-0.1.0/polars_baseball/enums/fangraphs/pitching_data_enum.py +463 -0
  56. polars_baseball-0.1.0/polars_baseball/enums/fangraphs/positions.py +20 -0
  57. polars_baseball-0.1.0/polars_baseball/enums/pitch.py +44 -0
  58. polars_baseball-0.1.0/polars_baseball/enums/player.py +15 -0
  59. polars_baseball-0.1.0/polars_baseball/enums/position.py +72 -0
  60. polars_baseball-0.1.0/polars_baseball/enums/savant.py +14 -0
  61. polars_baseball-0.1.0/polars_baseball/exceptions.py +54 -0
  62. polars_baseball-0.1.0/polars_baseball/gateways/__init__.py +13 -0
  63. polars_baseball-0.1.0/polars_baseball/gateways/bref.py +130 -0
  64. polars_baseball-0.1.0/polars_baseball/gateways/compiled.py +202 -0
  65. polars_baseball-0.1.0/polars_baseball/gateways/mlb.py +43 -0
  66. polars_baseball-0.1.0/polars_baseball/gateways/savant.py +160 -0
  67. polars_baseball-0.1.0/polars_baseball/parsers/__init__.py +46 -0
  68. polars_baseball-0.1.0/polars_baseball/parsers/_strategy.py +136 -0
  69. polars_baseball-0.1.0/polars_baseball/parsers/base.py +10 -0
  70. polars_baseball-0.1.0/polars_baseball/parsers/bref.py +348 -0
  71. polars_baseball-0.1.0/polars_baseball/parsers/bref_schema.py +190 -0
  72. polars_baseball-0.1.0/polars_baseball/parsers/bref_standard_strategy.py +134 -0
  73. polars_baseball-0.1.0/polars_baseball/parsers/fangraphs.py +79 -0
  74. polars_baseball-0.1.0/polars_baseball/parsers/fangraphs_next_data_strategy.py +43 -0
  75. polars_baseball-0.1.0/polars_baseball/parsers/mlb/__init__.py +84 -0
  76. polars_baseball-0.1.0/polars_baseball/parsers/mlb/draft.py +32 -0
  77. polars_baseball-0.1.0/polars_baseball/parsers/mlb/game.py +147 -0
  78. polars_baseball-0.1.0/polars_baseball/parsers/mlb/html.py +84 -0
  79. polars_baseball-0.1.0/polars_baseball/parsers/mlb/people.py +58 -0
  80. polars_baseball-0.1.0/polars_baseball/parsers/mlb/roster.py +21 -0
  81. polars_baseball-0.1.0/polars_baseball/parsers/mlb/schedule.py +68 -0
  82. polars_baseball-0.1.0/polars_baseball/parsers/mlb/stats.py +107 -0
  83. polars_baseball-0.1.0/polars_baseball/parsers/mlb/taxonomy.py +67 -0
  84. polars_baseball-0.1.0/polars_baseball/parsers/mlb/transactions.py +36 -0
  85. polars_baseball-0.1.0/polars_baseball/parsers/mlb/types.py +300 -0
  86. polars_baseball-0.1.0/polars_baseball/parsers/mlb/venues.py +13 -0
  87. polars_baseball-0.1.0/polars_baseball/parsers/pipeline.py +135 -0
  88. polars_baseball-0.1.0/polars_baseball/parsers/savant.py +35 -0
  89. polars_baseball-0.1.0/polars_baseball/parsers/savant_gamefeed.py +222 -0
  90. polars_baseball-0.1.0/polars_baseball/parsers/savant_leaderboard_strategy.py +111 -0
  91. polars_baseball-0.1.0/polars_baseball/parsers/savant_schema.py +20 -0
  92. polars_baseball-0.1.0/polars_baseball.egg-info/PKG-INFO +255 -0
  93. polars_baseball-0.1.0/polars_baseball.egg-info/SOURCES.txt +96 -0
  94. polars_baseball-0.1.0/polars_baseball.egg-info/dependency_links.txt +1 -0
  95. polars_baseball-0.1.0/polars_baseball.egg-info/requires.txt +23 -0
  96. polars_baseball-0.1.0/polars_baseball.egg-info/top_level.txt +1 -0
  97. polars_baseball-0.1.0/pyproject.toml +80 -0
  98. polars_baseball-0.1.0/setup.cfg +4 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nick
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,4 @@
1
+ include LICENSE
2
+ include polars_baseball/data/*.csv
3
+ include polars_baseball/data/*.json
4
+ prune scratch
@@ -0,0 +1,255 @@
1
+ Metadata-Version: 2.4
2
+ Name: polars-baseball
3
+ Version: 0.1.0
4
+ Summary: Retrieve baseball data in Python
5
+ Author: Nick
6
+ Maintainer: Nick
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/nicko4o/polars-baseball
9
+ Project-URL: Repository, https://github.com/nicko4o/polars-baseball
10
+ Project-URL: Issues, https://github.com/nicko4o/polars-baseball/issues
11
+ Project-URL: Changelog, https://github.com/nicko4o/polars-baseball/blob/main/CHANGELOG.md
12
+ Keywords: baseball,sabermetrics,data,statistics,statcast,web scraping
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Topic :: Software Development :: Libraries
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: lxml>=4.2.1
24
+ Requires-Dist: pyarrow>=1.0.1
25
+ Requires-Dist: tqdm>=4.50.0
26
+ Requires-Dist: curl_cffi>=0.10.0
27
+ Requires-Dist: polars>=1.0.0
28
+ Requires-Dist: httpx
29
+ Requires-Dist: typing_extensions>=4.0.0
30
+ Provides-Extra: plot
31
+ Requires-Dist: hvplot>=0.9.0; extra == "plot"
32
+ Requires-Dist: altair>=5.0.0; extra == "plot"
33
+ Provides-Extra: test
34
+ Requires-Dist: pytest<8.4,>=7.4; extra == "test"
35
+ Requires-Dist: mypy<1.15,>=1.8; extra == "test"
36
+ Requires-Dist: pytest-cov>=2.10.1; extra == "test"
37
+ Requires-Dist: pytest-xdist>=2.1.0; extra == "test"
38
+ Requires-Dist: types-requests>=2.18.1; extra == "test"
39
+ Requires-Dist: ruff>=0.1.0; extra == "test"
40
+ Requires-Dist: types-tqdm; extra == "test"
41
+ Requires-Dist: lxml-stubs; extra == "test"
42
+ Requires-Dist: types-setuptools; extra == "test"
43
+ Requires-Dist: pytest-asyncio; extra == "test"
44
+ Dynamic: license-file
45
+
46
+ # polars-baseball
47
+
48
+ Languages: [English](README.md) | [Traditional Chinese](README.zh-TW.md)
49
+
50
+ `polars-baseball` is a modern asynchronous Python library for retrieving baseball data. It is built around
51
+ Polars, where most public data APIs return `polars.DataFrame` objects (with documented exceptions such as `standings()`
52
+ returning other shapes), and supports Statcast, Baseball Reference, FanGraphs, Lahman,
53
+ Retrosheet, MLB Stats API, and player ID workflows.
54
+
55
+ ---
56
+
57
+ ## Key Features
58
+
59
+ - **Polars Core**: Most public APIs return native `polars.DataFrame` objects (with `standings()` returning `list[polars.DataFrame]`) for filtering, aggregation, and export.
60
+ - **Async-First Engine**: Data-fetching APIs are asynchronous and should be called with `await` or `asyncio.run()`.
61
+ - **Flexible Concurrency**: Support for custom context configuration to isolate resources in multi-threaded/loop environments.
62
+ - **Automatic Cache**: Built-in file caching reduces repeated network requests for large workflows.
63
+
64
+ ---
65
+
66
+ ## Installation
67
+
68
+ ```bash
69
+ pip install polars-baseball
70
+ ```
71
+
72
+ For local development:
73
+
74
+ ```bash
75
+ git clone https://github.com/nicko4o/polars-baseball
76
+ cd polars-baseball
77
+ uv sync --all-extras
78
+ ```
79
+
80
+ To run the visualization examples, install the optional example dependencies:
81
+
82
+ ```bash
83
+ pip install "polars-baseball[plot]"
84
+ ```
85
+
86
+ ---
87
+
88
+ ## Quick Start
89
+
90
+ ### 1. Statcast Queries
91
+
92
+ ```python
93
+ import asyncio
94
+
95
+ import polars_baseball as pb
96
+
97
+
98
+ async def main() -> None:
99
+ df = await pb.statcast(start_dt="2024-05-06", end_dt="2024-05-06")
100
+ print(df.head(5))
101
+
102
+ darvish_df = await pb.statcast_pitcher(
103
+ start_dt="2024-05-06",
104
+ end_dt="2024-05-06",
105
+ player_id=450314,
106
+ )
107
+ print(darvish_df.head(5))
108
+
109
+
110
+ if __name__ == "__main__":
111
+ asyncio.run(main())
112
+ ```
113
+
114
+ ### 2. Aggregate with Polars
115
+
116
+ ```python
117
+ import asyncio
118
+
119
+ import polars as pl
120
+ import polars_baseball as pb
121
+
122
+
123
+ async def main() -> None:
124
+ darvish_df = await pb.statcast_pitcher(
125
+ start_dt="2024-05-06",
126
+ end_dt="2024-05-06",
127
+ player_id=450314,
128
+ )
129
+ summary = (
130
+ darvish_df
131
+ .group_by("pitch_type")
132
+ .agg(pl.col("release_speed").mean().alias("mean_speed"))
133
+ )
134
+ print(summary)
135
+
136
+
137
+ if __name__ == "__main__":
138
+ asyncio.run(main())
139
+ ```
140
+
141
+ ### 3. Top Prospects
142
+
143
+ ```python
144
+ import asyncio
145
+
146
+ import polars_baseball as pb
147
+
148
+
149
+ async def main() -> None:
150
+ prospects = await pb.top_prospects(team_name="mets")
151
+ print(prospects.head(5))
152
+
153
+
154
+ if __name__ == "__main__":
155
+ asyncio.run(main())
156
+ ```
157
+
158
+ ### 4. Interactive Data Visualization
159
+
160
+ `polars-baseball` does not provide a plotting API. This example passes the returned `polars.DataFrame` to hvPlot.
161
+
162
+ ```python
163
+ import asyncio
164
+
165
+ import hvplot.polars # noqa: F401
166
+ import polars_baseball as pb
167
+
168
+
169
+ async def main() -> None:
170
+ df = await pb.statcast(start_dt="2024-05-06", end_dt="2024-05-06")
171
+ chart = (
172
+ df
173
+ .filter(df["hc_x"].is_not_null() & df["hc_y"].is_not_null())
174
+ .plot.scatter(
175
+ x="hc_x",
176
+ y="hc_y",
177
+ by="events",
178
+ invert_y=True,
179
+ )
180
+ )
181
+ print(chart)
182
+
183
+
184
+ if __name__ == "__main__":
185
+ asyncio.run(main())
186
+ ```
187
+
188
+ ## Web Services & Concurrency (FastAPI, Gunicorn, Celery)
189
+
190
+ By default, calling package functions without a `context` parameter will fallback to an implicit package-level global singleton `BaseballContext`. **This global default context is not guaranteed to be thread-safe or loop-safe in long-running concurrent environments.**
191
+
192
+ When deploying `polars-baseball` inside concurrent web services (such as FastAPI, Gunicorn, or Celery workers), you **must** explicitly manage the lifespan of `BaseballContext` and pass it to all API calls.
193
+
194
+ ### FastAPI lifespan Example
195
+
196
+ ```python
197
+ from contextlib import asynccontextmanager
198
+ from fastapi import FastAPI
199
+ import polars_baseball as pb
200
+
201
+ @asynccontextmanager
202
+ async def lifespan(app: FastAPI):
203
+ # Initialize a dedicated context bound to the app's event loop
204
+ app.state.pb_context = pb.BaseballContext()
205
+ try:
206
+ yield
207
+ finally:
208
+ # Properly clean up HTTP connections
209
+ await app.state.pb_context.http.close()
210
+
211
+ app = FastAPI(lifespan=lifespan)
212
+
213
+ @app.get("/statcast")
214
+ async def get_statcast():
215
+ df = await pb.statcast(
216
+ start_dt="2026-06-01",
217
+ end_dt="2026-06-02",
218
+ context=app.state.pb_context,
219
+ )
220
+ return df.to_dicts()
221
+ ```
222
+
223
+ ---
224
+
225
+ ## API Namespace Policy
226
+
227
+ The package root (`import polars_baseball as pb`) exposes only the stable, commonly used public API. Provider-specific and advanced functions remain available from `polars_baseball.apis.*`.
228
+
229
+ Modules prefixed with `_`, including `_schemas`, are internal implementation details and are not part of the compatibility contract.
230
+
231
+ ---
232
+
233
+ ## Documentation
234
+
235
+ - [English documentation](docs/)
236
+ - [Traditional Chinese documentation](docs/zh-tw/)
237
+ - [Caching Guide](docs/caching.md)
238
+ - [Data Visualization Guide](docs/plotting.md)
239
+ - [Statcast API](docs/statcast.md)
240
+ - [Player ID Lookup](docs/playerid_lookup.md)
241
+ - [MLB Stats API](docs/mlb_api.md)
242
+ - [Savant Gamefeed API](docs/savant_gamefeed.md)
243
+ - [Prospect Rankings](docs/prospect_rankings.md)
244
+
245
+ ---
246
+
247
+ ## Contributing
248
+
249
+ See [CONTRIBUTING.md](.github/CONTRIBUTING.md) for the development workflow and architecture notes.
250
+
251
+ ---
252
+
253
+ ## Author
254
+
255
+ Created and maintained by Nick.
@@ -0,0 +1,210 @@
1
+ # polars-baseball
2
+
3
+ Languages: [English](README.md) | [Traditional Chinese](README.zh-TW.md)
4
+
5
+ `polars-baseball` is a modern asynchronous Python library for retrieving baseball data. It is built around
6
+ Polars, where most public data APIs return `polars.DataFrame` objects (with documented exceptions such as `standings()`
7
+ returning other shapes), and supports Statcast, Baseball Reference, FanGraphs, Lahman,
8
+ Retrosheet, MLB Stats API, and player ID workflows.
9
+
10
+ ---
11
+
12
+ ## Key Features
13
+
14
+ - **Polars Core**: Most public APIs return native `polars.DataFrame` objects (with `standings()` returning `list[polars.DataFrame]`) for filtering, aggregation, and export.
15
+ - **Async-First Engine**: Data-fetching APIs are asynchronous and should be called with `await` or `asyncio.run()`.
16
+ - **Flexible Concurrency**: Support for custom context configuration to isolate resources in multi-threaded/loop environments.
17
+ - **Automatic Cache**: Built-in file caching reduces repeated network requests for large workflows.
18
+
19
+ ---
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ pip install polars-baseball
25
+ ```
26
+
27
+ For local development:
28
+
29
+ ```bash
30
+ git clone https://github.com/nicko4o/polars-baseball
31
+ cd polars-baseball
32
+ uv sync --all-extras
33
+ ```
34
+
35
+ To run the visualization examples, install the optional example dependencies:
36
+
37
+ ```bash
38
+ pip install "polars-baseball[plot]"
39
+ ```
40
+
41
+ ---
42
+
43
+ ## Quick Start
44
+
45
+ ### 1. Statcast Queries
46
+
47
+ ```python
48
+ import asyncio
49
+
50
+ import polars_baseball as pb
51
+
52
+
53
+ async def main() -> None:
54
+ df = await pb.statcast(start_dt="2024-05-06", end_dt="2024-05-06")
55
+ print(df.head(5))
56
+
57
+ darvish_df = await pb.statcast_pitcher(
58
+ start_dt="2024-05-06",
59
+ end_dt="2024-05-06",
60
+ player_id=450314,
61
+ )
62
+ print(darvish_df.head(5))
63
+
64
+
65
+ if __name__ == "__main__":
66
+ asyncio.run(main())
67
+ ```
68
+
69
+ ### 2. Aggregate with Polars
70
+
71
+ ```python
72
+ import asyncio
73
+
74
+ import polars as pl
75
+ import polars_baseball as pb
76
+
77
+
78
+ async def main() -> None:
79
+ darvish_df = await pb.statcast_pitcher(
80
+ start_dt="2024-05-06",
81
+ end_dt="2024-05-06",
82
+ player_id=450314,
83
+ )
84
+ summary = (
85
+ darvish_df
86
+ .group_by("pitch_type")
87
+ .agg(pl.col("release_speed").mean().alias("mean_speed"))
88
+ )
89
+ print(summary)
90
+
91
+
92
+ if __name__ == "__main__":
93
+ asyncio.run(main())
94
+ ```
95
+
96
+ ### 3. Top Prospects
97
+
98
+ ```python
99
+ import asyncio
100
+
101
+ import polars_baseball as pb
102
+
103
+
104
+ async def main() -> None:
105
+ prospects = await pb.top_prospects(team_name="mets")
106
+ print(prospects.head(5))
107
+
108
+
109
+ if __name__ == "__main__":
110
+ asyncio.run(main())
111
+ ```
112
+
113
+ ### 4. Interactive Data Visualization
114
+
115
+ `polars-baseball` does not provide a plotting API. This example passes the returned `polars.DataFrame` to hvPlot.
116
+
117
+ ```python
118
+ import asyncio
119
+
120
+ import hvplot.polars # noqa: F401
121
+ import polars_baseball as pb
122
+
123
+
124
+ async def main() -> None:
125
+ df = await pb.statcast(start_dt="2024-05-06", end_dt="2024-05-06")
126
+ chart = (
127
+ df
128
+ .filter(df["hc_x"].is_not_null() & df["hc_y"].is_not_null())
129
+ .plot.scatter(
130
+ x="hc_x",
131
+ y="hc_y",
132
+ by="events",
133
+ invert_y=True,
134
+ )
135
+ )
136
+ print(chart)
137
+
138
+
139
+ if __name__ == "__main__":
140
+ asyncio.run(main())
141
+ ```
142
+
143
+ ## Web Services & Concurrency (FastAPI, Gunicorn, Celery)
144
+
145
+ By default, calling package functions without a `context` parameter will fallback to an implicit package-level global singleton `BaseballContext`. **This global default context is not guaranteed to be thread-safe or loop-safe in long-running concurrent environments.**
146
+
147
+ When deploying `polars-baseball` inside concurrent web services (such as FastAPI, Gunicorn, or Celery workers), you **must** explicitly manage the lifespan of `BaseballContext` and pass it to all API calls.
148
+
149
+ ### FastAPI lifespan Example
150
+
151
+ ```python
152
+ from contextlib import asynccontextmanager
153
+ from fastapi import FastAPI
154
+ import polars_baseball as pb
155
+
156
+ @asynccontextmanager
157
+ async def lifespan(app: FastAPI):
158
+ # Initialize a dedicated context bound to the app's event loop
159
+ app.state.pb_context = pb.BaseballContext()
160
+ try:
161
+ yield
162
+ finally:
163
+ # Properly clean up HTTP connections
164
+ await app.state.pb_context.http.close()
165
+
166
+ app = FastAPI(lifespan=lifespan)
167
+
168
+ @app.get("/statcast")
169
+ async def get_statcast():
170
+ df = await pb.statcast(
171
+ start_dt="2026-06-01",
172
+ end_dt="2026-06-02",
173
+ context=app.state.pb_context,
174
+ )
175
+ return df.to_dicts()
176
+ ```
177
+
178
+ ---
179
+
180
+ ## API Namespace Policy
181
+
182
+ The package root (`import polars_baseball as pb`) exposes only the stable, commonly used public API. Provider-specific and advanced functions remain available from `polars_baseball.apis.*`.
183
+
184
+ Modules prefixed with `_`, including `_schemas`, are internal implementation details and are not part of the compatibility contract.
185
+
186
+ ---
187
+
188
+ ## Documentation
189
+
190
+ - [English documentation](docs/)
191
+ - [Traditional Chinese documentation](docs/zh-tw/)
192
+ - [Caching Guide](docs/caching.md)
193
+ - [Data Visualization Guide](docs/plotting.md)
194
+ - [Statcast API](docs/statcast.md)
195
+ - [Player ID Lookup](docs/playerid_lookup.md)
196
+ - [MLB Stats API](docs/mlb_api.md)
197
+ - [Savant Gamefeed API](docs/savant_gamefeed.md)
198
+ - [Prospect Rankings](docs/prospect_rankings.md)
199
+
200
+ ---
201
+
202
+ ## Contributing
203
+
204
+ See [CONTRIBUTING.md](.github/CONTRIBUTING.md) for the development workflow and architecture notes.
205
+
206
+ ---
207
+
208
+ ## Author
209
+
210
+ Created and maintained by Nick.
@@ -0,0 +1,108 @@
1
+ import logging as _logging
2
+
3
+ from polars_baseball._cache import configure_cache
4
+ from polars_baseball.apis.fangraphs import FanGraphsRequest, fg_data
5
+ from polars_baseball.apis.mlb import (
6
+ mlb_divisions,
7
+ mlb_draft,
8
+ mlb_game_boxscore,
9
+ mlb_game_boxscore_stats,
10
+ mlb_game_feed_live,
11
+ mlb_game_linescore,
12
+ mlb_game_play_by_play,
13
+ mlb_game_win_probability,
14
+ mlb_leagues,
15
+ mlb_people,
16
+ mlb_people_awards,
17
+ mlb_pitch_arsenal,
18
+ mlb_player_stats,
19
+ mlb_postseason_schedule,
20
+ mlb_roster,
21
+ mlb_schedule,
22
+ mlb_stat_leaders,
23
+ mlb_team_stats,
24
+ mlb_teams,
25
+ mlb_transactions,
26
+ mlb_venues,
27
+ )
28
+ from polars_baseball.apis.playerid import playerid_lookup
29
+ from polars_baseball.apis.savant_fielding_running import (
30
+ statcast_arm_strength,
31
+ statcast_baserunning_run_value,
32
+ statcast_catcher_stance,
33
+ statcast_catcher_throwing,
34
+ )
35
+ from polars_baseball.apis.savant_gamefeed import (
36
+ savant_gamefeed_exit_velocity,
37
+ savant_gamefeed_exit_velocity_many,
38
+ savant_gamefeed_pitch_data,
39
+ savant_gamefeed_pitch_data_many,
40
+ )
41
+ from polars_baseball.apis.standings import standings
42
+ from polars_baseball.apis.statcast import statcast, statcast_batter, statcast_pitcher, statcast_single_game
43
+ from polars_baseball.apis.top_prospects import prospect_rankings, top_prospects
44
+ from polars_baseball.context import BaseballContext
45
+ from polars_baseball.context import cleanup as _cleanup
46
+ from polars_baseball.enums import ArsenalType, KeyType
47
+
48
+ __version__ = "0.1.0"
49
+
50
+ _logging.getLogger("polars_baseball").addHandler(_logging.NullHandler())
51
+
52
+
53
+ async def cleanup() -> None:
54
+ """Close default HTTP resources held by the package-level context."""
55
+ await _cleanup()
56
+
57
+
58
+ __all__ = [
59
+ "ArsenalType",
60
+ "BaseballContext",
61
+ "FanGraphsRequest",
62
+ "KeyType",
63
+ "cleanup",
64
+ "configure_cache",
65
+ "fg_data",
66
+ "mlb_divisions",
67
+ "mlb_draft",
68
+ "mlb_game_boxscore",
69
+ "mlb_game_boxscore_stats",
70
+ "mlb_game_feed_live",
71
+ "mlb_game_linescore",
72
+ "mlb_game_play_by_play",
73
+ "mlb_game_win_probability",
74
+ "mlb_leagues",
75
+ "mlb_people",
76
+ "mlb_people_awards",
77
+ "mlb_pitch_arsenal",
78
+ "mlb_player_stats",
79
+ "mlb_postseason_schedule",
80
+ "mlb_roster",
81
+ "mlb_schedule",
82
+ "mlb_stat_leaders",
83
+ "mlb_team_stats",
84
+ "mlb_teams",
85
+ "mlb_transactions",
86
+ "mlb_venues",
87
+ "playerid_lookup",
88
+ "savant_gamefeed_exit_velocity",
89
+ "savant_gamefeed_exit_velocity_many",
90
+ "savant_gamefeed_pitch_data",
91
+ "savant_gamefeed_pitch_data_many",
92
+ "statcast_arm_strength",
93
+ "statcast_baserunning_run_value",
94
+ "statcast_catcher_stance",
95
+ "statcast_catcher_throwing",
96
+ "standings",
97
+ "statcast",
98
+ "statcast_batter",
99
+ "statcast_pitcher",
100
+ "statcast_single_game",
101
+ "top_prospects",
102
+ "prospect_rankings",
103
+ ]
104
+
105
+ for _implementation_namespace in ("apis", "context", "enums", "exceptions", "gateways", "parsers"):
106
+ globals().pop(_implementation_namespace, None)
107
+
108
+ del _implementation_namespace