ceblpy 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.
ceblpy/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ # read version from installed package
2
+ from importlib.metadata import version
3
+ __version__ = version("ceblpy")
ceblpy/ceblpy.py ADDED
@@ -0,0 +1,485 @@
1
+ import pandas as pd
2
+ from . import helpers as h
3
+ from datetime import datetime
4
+
5
+
6
+ def load_cebl_schedule(seasons=None):
7
+ """
8
+ Load cleaned CEBL schedule data from the cebl data repository.
9
+
10
+ Parameters
11
+ ----------
12
+ seasons : int, list of int, or None, optional
13
+ Season(s) to load. By default, None loads all available seasons.
14
+ - int : Single season year (e.g., 2020)
15
+ - list of int : Multiple seasons (e.g., [2019, 2020, 2021])
16
+ - None : Load all available seasons
17
+
18
+ All years must be 2019 or later.
19
+
20
+ Returns
21
+ -------
22
+ pandas.DataFrame
23
+ A DataFrame containing the schedule with the following columns:
24
+
25
+ ================================ ===========
26
+ Column Name Type
27
+ ================================ ===========
28
+ fiba_id int
29
+ season int
30
+ start_time_utc datetime
31
+ status str
32
+ competition str
33
+ venue_name str
34
+ period float
35
+ home_team_id int
36
+ home_team_name str
37
+ home_team_score float
38
+ home_team_logo_url str
39
+ home_team_url_stats_en str
40
+ home_team_url_stats_fr str
41
+ away_team_id int
42
+ away_team_name str
43
+ away_team_score float
44
+ away_team_logo_url str
45
+ away_team_url_stats_en str
46
+ away_team_url_stats_fr str
47
+ stats_url_en str
48
+ stats_url_fr str
49
+ cebl_stats_url_en str
50
+ cebl_stats_url_fr str
51
+ tickets_url_en str
52
+ tickets_url_fr str
53
+ id int
54
+ fiba_json_url str
55
+ ================================ ===========
56
+
57
+
58
+ Examples
59
+ --------
60
+ >>> load_cebl_schedule(2020)
61
+ >>> load_cebl_schedule([2019, 2020, 2021])
62
+ >>> load_cebl_schedule()
63
+ """
64
+ if isinstance(seasons, int):
65
+ seasons = [seasons]
66
+ if isinstance(seasons, list):
67
+ h.validate_seasons(seasons)
68
+ elif seasons is None:
69
+ seasons = list(range(2019, datetime.now().year + 1))
70
+ else:
71
+ raise TypeError(f"Expected seasons to be an int, list of ints, or None, got {type(seasons).__name__}")
72
+
73
+ schedule = pd.read_csv("https://github.com/ryanndu/cebl-data/releases/download/schedule/cebl_schedule.csv")
74
+ schedule = schedule[schedule['season'].isin(seasons)]
75
+ return schedule
76
+
77
+
78
+ def load_cebl_team_boxscore(seasons=None):
79
+ """
80
+ Load cleaned CEBL team boxscore data from the cebl data repository.
81
+
82
+ Parameters
83
+ ----------
84
+ seasons : int, list of int, or None, optional
85
+ Season(s) to load. By default, None loads all available seasons.
86
+ - int : Single season year (e.g., 2020)
87
+ - list of int : Multiple seasons (e.g., [2019, 2020, 2021])
88
+ - None : Load all available seasons
89
+
90
+ All years must be 2019 or later.
91
+
92
+ Returns
93
+ -------
94
+ pandas.DataFrame
95
+ A DataFrame containing the team boxscore with the following columns:
96
+
97
+ ============================================== ===========
98
+ Column Name Type
99
+ ============================================== ===========
100
+ game_id int
101
+ season int
102
+ team_name str
103
+ short_name str
104
+ code str
105
+ team_score int
106
+ minutes str
107
+ field_goals_made int
108
+ field_goals_attempted int
109
+ field_goal_percentage int
110
+ two_point_field_goals_made int
111
+ two_point_field_goals_attempted int
112
+ two_point__percentage int
113
+ three_point_field_goals_made int
114
+ three_point_field_goals_attempted int
115
+ three_point_percentage int
116
+ free_throws_made int
117
+ free_throws_attempted int
118
+ free_throw_percentage int
119
+ offensive_rebounds int
120
+ defensive_rebounds int
121
+ rebounds int
122
+ assists int
123
+ steals int
124
+ turnovers int
125
+ blocks int
126
+ blocks_received int
127
+ personal_fouls int
128
+ fouls_drawn int
129
+ total_fouls int
130
+ bonus_fouls int
131
+ points_in_the_paint int
132
+ second_chance_points int
133
+ points_from_turnovers int
134
+ bench_points int
135
+ fast_break_points int
136
+ team_index_rating int
137
+ team_index_rating_2 int
138
+ team_index_rating_3 float
139
+ team_index_rating_4 float
140
+ team_index_rating_5 int
141
+ team_index_rating_6 int
142
+ team_index_rating_7 int
143
+ team_fouls int
144
+ team_turnovers int
145
+ team_rebounds int
146
+ team_defensive_rebounds int
147
+ team_offensive_rebounds int
148
+ period_1_score int
149
+ period_2_score float
150
+ period_3_score float
151
+ period_4_score float
152
+ biggest_lead float
153
+ biggest_scoring_run float
154
+ time_leading float
155
+ lead_changes int
156
+ times_scores_level int
157
+ timeouts_left int
158
+ head_coach str
159
+ assistant_coach_1 str
160
+ assistant_coach_2 str
161
+ international_team_name str
162
+ international_short_name str
163
+ international_code str
164
+ logo str
165
+ logo_t_url str
166
+ logo_t_size str
167
+ logo_t_height int
168
+ logo_t_width int
169
+ logo_t_bytes int
170
+ logo_s_url str
171
+ logo_s_size str
172
+ logo_s_height int
173
+ logo_s_width int
174
+ logo_s_bytes int
175
+ ============================================== ===========
176
+
177
+ Examples
178
+ --------
179
+ >>> load_cebl_team_boxscore(2020)
180
+ >>> load_cebl_team_boxscore([2019, 2020, 2021])
181
+ >>> load_cebl_team_boxscore()
182
+ """
183
+ if isinstance(seasons, int):
184
+ seasons = [seasons]
185
+ if isinstance(seasons, list):
186
+ h.validate_seasons(seasons)
187
+ elif seasons is None:
188
+ seasons = list(range(2019, datetime.now().year + 1))
189
+ else:
190
+ raise TypeError(f"Expected seasons to be an int, list of ints, or None, got {type(seasons).__name__}")
191
+
192
+ team_boxscore = pd.read_csv("https://github.com/ryanndu/cebl-data/releases/download/team-boxscore/cebl_teams.csv")
193
+ team_boxscore = team_boxscore[team_boxscore['season'].isin(seasons)]
194
+ return team_boxscore
195
+
196
+
197
+ def load_cebl_player_boxscore(seasons=None):
198
+ """
199
+ Load cleaned CEBL player boxscore data from the cebl data repository.
200
+
201
+ Parameters
202
+ ----------
203
+ seasons : int, list of int, or None, optional
204
+ Season(s) to load. By default, None loads all available seasons.
205
+ - int : Single season year (e.g., 2020)
206
+ - list of int : Multiple seasons (e.g., [2019, 2020, 2021])
207
+ - None : Load all available seasons
208
+
209
+ All years must be 2019 or later.
210
+
211
+ Returns
212
+ -------
213
+ pandas.DataFrame
214
+ A DataFrame containing the player boxscore with the following columns:
215
+
216
+ ====================================== ===========
217
+ Column Name Type
218
+ ====================================== ===========
219
+ game_id int
220
+ season int
221
+ team_name str
222
+ player_number int
223
+ player_name str
224
+ player_position str
225
+ minutes str
226
+ points int
227
+ field_goals_made int
228
+ field_goals_attempted int
229
+ field_goal_percentage int
230
+ two_point_field_goals_made int
231
+ two_point_field_goals_attempted int
232
+ two_point__percentage int
233
+ three_point_field_goals_made int
234
+ three_point_field_goals_attempted int
235
+ three_point_percentage int
236
+ free_throws_made int
237
+ free_throws_attempted int
238
+ free_throw_percentage int
239
+ offensive_rebounds int
240
+ defensive_rebounds int
241
+ rebounds int
242
+ assists int
243
+ turnovers int
244
+ steals int
245
+ blocks int
246
+ blocks_received int
247
+ personal_fouls int
248
+ fouls_drawn int
249
+ plus_minus int
250
+ index_rating int
251
+ index_rating_2 int
252
+ index_rating_3 float
253
+ index_rating_4 float
254
+ index_rating_5 int
255
+ index_rating_6 int
256
+ index_rating_7 int
257
+ second_chance_points int
258
+ fast_break_points int
259
+ points_in_the_paint int
260
+ first_name str
261
+ first_name_initial str
262
+ last_name str
263
+ last_name_initial str
264
+ international_first_name str
265
+ international_first_name_initial str
266
+ international_last_name str
267
+ international_last_name_initial str
268
+ scoreboard_name str
269
+ active bool
270
+ starter bool
271
+ captain bool
272
+ photo_t str
273
+ photo_s str
274
+ ====================================== ===========
275
+
276
+ Examples
277
+ --------
278
+ >>> load_cebl_player_boxscore(2020)
279
+ >>> load_cebl_player_boxscore([2019, 2020, 2021])
280
+ >>> load_cebl_player_boxscore()
281
+ """
282
+ if isinstance(seasons, int):
283
+ seasons = [seasons]
284
+ if isinstance(seasons, list):
285
+ h.validate_seasons(seasons)
286
+ elif seasons is None:
287
+ seasons = list(range(2019, datetime.now().year + 1))
288
+ else:
289
+ raise TypeError(f"Expected seasons to be an int, list of ints, or None, got {type(seasons).__name__}")
290
+
291
+ player_boxscore = pd.read_csv("https://github.com/ryanndu/cebl-data/releases/download/player-boxscore/cebl_players.csv")
292
+ player_boxscore = player_boxscore[player_boxscore['season'].isin(seasons)]
293
+ return player_boxscore
294
+
295
+
296
+ def load_cebl_officials(seasons=None):
297
+ """
298
+ Load cleaned CEBL officials data from the cebl data repository.
299
+
300
+ Parameters
301
+ ----------
302
+ seasons : int, list of int, or None, optional
303
+ Season(s) to load. By default, None loads all available seasons.
304
+ - int : Single season year (e.g., 2020)
305
+ - list of int : Multiple seasons (e.g., [2019, 2020, 2021])
306
+ - None : Load all available seasons
307
+
308
+ All years must be 2019 or later.
309
+
310
+ Returns
311
+ -------
312
+ pandas.DataFrame
313
+ A DataFrame containing the officials with the following columns:
314
+
315
+ ================================ ===========
316
+ Column Name Type
317
+ ================================ ===========
318
+ game_id int
319
+ season int
320
+ officials_type str
321
+ officials_name str
322
+ first_name str
323
+ last_name str
324
+ scoreboard_name str
325
+ first_name_initial str
326
+ last_name_initial str
327
+ international_first_name str
328
+ international_first_name_initial str
329
+ international_last_name str
330
+ international_last_name_initial str
331
+ scoreboard_name str
332
+ ================================ ===========
333
+
334
+ Examples
335
+ --------
336
+ >>> load_cebl_officials(2020)
337
+ >>> load_cebl_officials([2019, 2020, 2021])
338
+ >>> load_cebl_officials_boxscore()
339
+ """
340
+ if isinstance(seasons, int):
341
+ seasons = [seasons]
342
+ if isinstance(seasons, list):
343
+ h.validate_seasons(seasons)
344
+ elif seasons is None:
345
+ seasons = list(range(2019, datetime.now().year + 1))
346
+ else:
347
+ raise TypeError(f"Expected seasons to be an int, list of ints, or None, got {type(seasons).__name__}")
348
+
349
+ officials = pd.read_csv("https://github.com/ryanndu/cebl-data/releases/download/officials/cebl_officials.csv")
350
+ officials = officials[officials['season'].isin(seasons)]
351
+ return officials
352
+
353
+
354
+ def load_cebl_coaches(seasons=None):
355
+ """
356
+ Load cleaned CEBL coaches data from the cebl data repository.
357
+
358
+ Parameters
359
+ ----------
360
+ seasons : int, list of int, or None, optional
361
+ Season(s) to load. By default, None loads all available seasons.
362
+ - int : Single season year (e.g., 2020)
363
+ - list of int : Multiple seasons (e.g., [2019, 2020, 2021])
364
+ - None : Load all available seasons
365
+
366
+ All years must be 2019 or later.
367
+
368
+ Returns
369
+ -------
370
+ pandas.DataFrame
371
+ A DataFrame containing the coaches with the following columns:
372
+
373
+ ================================ ===========
374
+ Column Name Type
375
+ ================================ ===========
376
+ game_id int
377
+ season int
378
+ team_name str
379
+ coach_name str
380
+ coach_type str
381
+ first_name str
382
+ first_name_initial str
383
+ last_name str
384
+ last_name_initial str
385
+ international_first_name str
386
+ international_first_name_initial str
387
+ international_last_name str
388
+ international_last_name_initial str
389
+ scoreboard_name str
390
+ ================================ ===========
391
+
392
+ Examples
393
+ --------
394
+ >>> load_cebl_coaches(2020)
395
+ >>> load_cebl_coaches([2019, 2020, 2021])
396
+ >>> load_cebl_coaches()
397
+ """
398
+ if isinstance(seasons, int):
399
+ seasons = [seasons]
400
+ if isinstance(seasons, list):
401
+ h.validate_seasons(seasons)
402
+ elif seasons is None:
403
+ seasons = list(range(2019, datetime.now().year + 1))
404
+ else:
405
+ raise TypeError(f"Expected seasons to be an int, list of ints, or None, got {type(seasons).__name__}")
406
+
407
+ coaches = pd.read_csv("https://github.com/ryanndu/cebl-data/releases/download/coaches/cebl_coaches.csv")
408
+ coaches = coaches[coaches['season'].isin(seasons)]
409
+ return coaches
410
+
411
+
412
+ def load_cebl_pbp(seasons=None):
413
+ """
414
+ Load cleaned CEBL pbp data from the cebl data repository.
415
+
416
+ Parameters
417
+ ----------
418
+ seasons : int, list of int, or None, optional
419
+ Season(s) to load. By default, None loads all available seasons.
420
+ - int : Single season year (e.g., 2020)
421
+ - list of int : Multiple seasons (e.g., [2019, 2020, 2021])
422
+ - None : Load all available seasons
423
+
424
+ All years must be 2019 or later.
425
+
426
+ Returns
427
+ -------
428
+ pandas.DataFrame
429
+ A DataFrame containing the pbp with the following columns:
430
+
431
+ ================================ ===========
432
+ Column Name Type
433
+ ================================ ===========
434
+ game_id int
435
+ season int
436
+ game_time str
437
+ home_score int
438
+ away_score int
439
+ home_lead int
440
+ team_id int
441
+ period int
442
+ period_type str
443
+ player_id int
444
+ scoreboard_name str
445
+ success int
446
+ action_type str
447
+ action_number float
448
+ previous_action float
449
+ sub_type str
450
+ scoring int
451
+ shirt_number float
452
+ player_name str
453
+ first_name str
454
+ last_name str
455
+ x float
456
+ y float
457
+ qualifier_0 str
458
+ qualifier_1 str
459
+ qualifier_2 str
460
+ qualifier_3 str
461
+ international_first_name str
462
+ international_last_name str
463
+ international_first_name_initial str
464
+ international_last_name_initial str
465
+ ================================ ===========
466
+
467
+ Examples
468
+ --------
469
+ >>> load_cebl_pbp(2020)
470
+ >>> load_cebl_pbp([2019, 2020, 2021])
471
+ >>> load_cebl_pbp()
472
+ """
473
+ if isinstance(seasons, int):
474
+ seasons = [seasons]
475
+ if isinstance(seasons, list):
476
+ h.validate_seasons(seasons)
477
+ elif seasons is None:
478
+ seasons = list(range(2019, datetime.now().year + 1))
479
+ else:
480
+ raise TypeError(f"Expected seasons to be an int, list of ints, or None, got {type(seasons).__name__}")
481
+
482
+ pbp = pd.DataFrame()
483
+ for season in seasons:
484
+ pbp = pd.concat([pbp, pd.read_csv(f"https://github.com/ryanndu/cebl-data/releases/download/pbp/cebl_pbp_{season}.csv")])
485
+ return pbp
ceblpy/helpers.py ADDED
@@ -0,0 +1,29 @@
1
+ import pandas as pd
2
+ from datetime import datetime
3
+
4
+ def validate_seasons(seasons):
5
+ """
6
+ Checks whether all the provided seasons are valid years and raises an error if not.
7
+
8
+ Parameters
9
+ ----------
10
+ seasons: list of int
11
+ A list of years representing seasons to validate.
12
+
13
+ Returns
14
+ -------
15
+ None
16
+
17
+ Examples
18
+ --------
19
+ >>> validate_seasons([2019, 2020, 2021])
20
+ >>> validate_seasons([2018, "2020"]) # Raises TypeError
21
+ >>> validate_seasons([2022, 2023, 2030]) # Raises ValueError
22
+ """
23
+ if not isinstance(seasons, list):
24
+ raise TypeError("Expected a list of years")
25
+ for year in seasons:
26
+ if not isinstance(year, int):
27
+ raise TypeError(f"Expected an integer for year, got {type(year).__name__}")
28
+ if year < 2019 or year > datetime.now().year:
29
+ raise ValueError(f"Year {year} out of valid range (2019-{datetime.now().year})")
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025, Ryan Du
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.
22
+
@@ -0,0 +1,71 @@
1
+ Metadata-Version: 2.3
2
+ Name: ceblpy
3
+ Version: 0.1.0
4
+ Summary: Extract and analyze data form the Canadian Elite Basketball league (CEBL).
5
+ License: MIT
6
+ Author: Ryan Du
7
+ Requires-Python: >=3.12,<4.0
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Requires-Dist: pandas (>=2.3.0,<3.0.0)
13
+ Description-Content-Type: text/markdown
14
+
15
+ # ceblpy <img src="https://github.com/ryanndu/ceblpy/raw/main/assets/images/cebl-logo.png" align="right" width="100" height="100"/>
16
+
17
+ ---
18
+
19
+ ## Overview
20
+
21
+ **[ceblpy](https://github.com/ryanndu/ceblpy)** is a Python package designed for working with the Canadian Elite Basketball League (CEBL) data.
22
+
23
+ The package has functions to retrieve team and player box scores, game schedules, coach and officials information, and full play-by-play data.
24
+
25
+ ---
26
+
27
+ ## Installation
28
+
29
+ You can install the **[ceblpy](https://github.com/ryanndu/ceblpy)** package with:
30
+
31
+ ```bash
32
+ $ pip install ceblpy
33
+ ```
34
+
35
+ ---
36
+
37
+ ## Usage
38
+
39
+ To retrieve the CEBL schedule for a given season (e.g., 2024), use the `load_cebl_schedule()` function:
40
+
41
+ ```python
42
+ from ceblpy.ceblpy import load_cebl_schedule
43
+
44
+ # Load the 2024 CEBL season schedule
45
+ schedule = load_cebl_schedule(2024)
46
+
47
+ # Preview the data
48
+ print(schedule.head())
49
+ ```
50
+
51
+ ---
52
+
53
+ ## Contributing
54
+
55
+ Found a bug? Have an idea to make ceblpy better? We'd love to hear from you!
56
+ - **Open an issue** on our **[GitHub Issues](https://github.com/ryanndu/ceblpy/issues)** page
57
+ - **Email Me** directly at **[ryandu343@gmail.com](mailto:ryandu343@gmail.com)**
58
+
59
+ All suggestions and contributions are welcome!
60
+
61
+ ---
62
+
63
+ ## License
64
+
65
+ `ceblpy` was created by Ryan Du and David Awosoga. It is licensed under the terms of the MIT license.
66
+
67
+ ---
68
+
69
+ ## Credits
70
+
71
+ `ceblpy` was created with [`cookiecutter`](https://cookiecutter.readthedocs.io/en/latest/) and the `py-pkgs-cookiecutter` [template](https://github.com/py-pkgs/py-pkgs-cookiecutter).
@@ -0,0 +1,7 @@
1
+ ceblpy/__init__.py,sha256=BEMXUVUjrxmZr2QkWknXKXSkSCYqurdFIitKUBigsvM,110
2
+ ceblpy/ceblpy.py,sha256=xref64dSEcDNX6Zsog74KWIDK7kZc7VNkFoHNyrMOuc,21234
3
+ ceblpy/helpers.py,sha256=lCCpS1DBPcO4cJWDHbu8NE_Dw8n6v9wpG0s0yeUtgYs,948
4
+ ceblpy-0.1.0.dist-info/LICENSE,sha256=KCoyVd7Op-r5Ray0mGmDgKiF6z1PCeJ7Rwxplau4Qhs,1088
5
+ ceblpy-0.1.0.dist-info/METADATA,sha256=hr7R90cPQDmmj61137kl5Fts6EYV1DSy94A4MWZtLOY,1992
6
+ ceblpy-0.1.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
7
+ ceblpy-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.1.3
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any