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 +3 -0
- ceblpy/ceblpy.py +485 -0
- ceblpy/helpers.py +29 -0
- ceblpy-0.1.0.dist-info/LICENSE +22 -0
- ceblpy-0.1.0.dist-info/METADATA +71 -0
- ceblpy-0.1.0.dist-info/RECORD +7 -0
- ceblpy-0.1.0.dist-info/WHEEL +4 -0
ceblpy/__init__.py
ADDED
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,,
|