sportsball 0.3.109__tar.gz → 0.3.111__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 (220) hide show
  1. {sportsball-0.3.109/sportsball.egg-info → sportsball-0.3.111}/PKG-INFO +1 -1
  2. {sportsball-0.3.109 → sportsball-0.3.111}/setup.py +1 -1
  3. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/__init__.py +1 -1
  4. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/__main__.py +1 -1
  5. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/args.py +5 -0
  6. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/afl/afl_afl_league_model.py +10 -0
  7. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/afltables/afl_afltables_league_model.py +4 -0
  8. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/aussportsbetting/afl_aussportsbetting_league_model.py +4 -0
  9. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/combined/afl_combined_league_model.py +8 -1
  10. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/oddsportal/afl_oddsportal_league_model.py +4 -0
  11. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/aussportsbetting/aussportsbetting_league_model.py +4 -0
  12. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/combined/combined_address_model.py +6 -5
  13. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/combined/combined_game_model.py +15 -10
  14. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/combined/combined_league_model.py +5 -0
  15. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/combined/combined_player_model.py +33 -32
  16. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/combined/combined_team_model.py +4 -3
  17. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/combined/combined_venue_model.py +5 -4
  18. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/combined/combined_weather_model.py +3 -2
  19. sportsball-0.3.111/sportsball/data/combined/null_check.py +22 -0
  20. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/espn/espn_league_model.py +4 -0
  21. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/google/google_address_model.py +27 -0
  22. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/league_model.py +23 -6
  23. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nba/combined/nba_combined_league_model.py +8 -1
  24. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nba/nba/nba_nba_league_model.py +4 -0
  25. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nba/sportsreference/nba_sportsreference_league_model.py +4 -0
  26. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/ncaab/combined/ncaab_combined_league_model.py +8 -1
  27. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/ncaab/oddsportal/ncaab_oddsportal_league_model.py +4 -0
  28. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/ncaab/sportsreference/ncaab_sportsreference_league_model.py +4 -0
  29. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/ncaaf/combined/ncaaf_combined_league_model.py +8 -1
  30. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nfl/aussportsbetting/nfl_aussportsbetting_league_model.py +4 -0
  31. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nfl/combined/nfl_combined_league_model.py +8 -1
  32. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nfl/espn/nfl_espn_league_model.py +4 -0
  33. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nfl/oddsportal/nfl_oddsportal_league_model.py +4 -0
  34. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nfl/sportsdb/nfl_sportsdb_league_model.py +4 -0
  35. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/oddsportal/oddsportal_league_model.py +4 -0
  36. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/sportsdb/sportsdb_league_model.py +4 -0
  37. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/sportsreference/sportsreference_league_model.py +4 -0
  38. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/sportsball.py +6 -6
  39. {sportsball-0.3.109 → sportsball-0.3.111/sportsball.egg-info}/PKG-INFO +1 -1
  40. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball.egg-info/SOURCES.txt +1 -0
  41. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/afl/afltables/afl_afltables_game_model_test.py +2 -0
  42. {sportsball-0.3.109 → sportsball-0.3.111}/tests/sportsball_test.py +1 -1
  43. {sportsball-0.3.109 → sportsball-0.3.111}/LICENSE +0 -0
  44. {sportsball-0.3.109 → sportsball-0.3.111}/MANIFEST.in +0 -0
  45. {sportsball-0.3.109 → sportsball-0.3.111}/README.md +0 -0
  46. {sportsball-0.3.109 → sportsball-0.3.111}/requirements.txt +0 -0
  47. {sportsball-0.3.109 → sportsball-0.3.111}/setup.cfg +0 -0
  48. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/cache.py +0 -0
  49. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/__init__.py +0 -0
  50. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/address_model.py +0 -0
  51. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/__init__.py +0 -0
  52. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/afl/__init__.py +0 -0
  53. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/afl/afl_afl_game_model.py +0 -0
  54. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/afl/afl_afl_player_model.py +0 -0
  55. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/afl/afl_afl_team_model.py +0 -0
  56. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/afl/afl_afl_venue_model.py +0 -0
  57. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/afltables/__init__.py +0 -0
  58. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/afltables/afl_afltables_game_model.py +0 -0
  59. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/afltables/afl_afltables_player_model.py +0 -0
  60. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/afltables/afl_afltables_team_model.py +0 -0
  61. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/afltables/afl_afltables_venue_model.py +0 -0
  62. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/aussportsbetting/__init__.py +0 -0
  63. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/combined/__init__.py +0 -0
  64. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/espn/__init__.py +0 -0
  65. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/espn/afl_espn_league_model.py +0 -0
  66. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/afl/oddsportal/__init__.py +0 -0
  67. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/aussportsbetting/__init__.py +0 -0
  68. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/aussportsbetting/aussportsbetting_bookie_model.py +0 -0
  69. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/aussportsbetting/aussportsbetting_game_model.py +0 -0
  70. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/aussportsbetting/aussportsbetting_odds_model.py +0 -0
  71. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/aussportsbetting/aussportsbetting_team_model.py +0 -0
  72. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/aussportsbetting/aussportsbetting_venue_model.py +0 -0
  73. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/bookie_model.py +0 -0
  74. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/combined/__init__.py +0 -0
  75. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/espn/__init__.py +0 -0
  76. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/espn/espn_bookie_model.py +0 -0
  77. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/espn/espn_game_model.py +0 -0
  78. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/espn/espn_odds_model.py +0 -0
  79. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/espn/espn_player_model.py +0 -0
  80. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/espn/espn_team_model.py +0 -0
  81. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/espn/espn_venue_model.py +0 -0
  82. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/field_type.py +0 -0
  83. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/game_model.py +0 -0
  84. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/google/__init__.py +0 -0
  85. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/google/google_news_model.py +0 -0
  86. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/league.py +0 -0
  87. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/model.py +0 -0
  88. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nba/__init__.py +0 -0
  89. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nba/combined/__init__.py +0 -0
  90. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nba/espn/__init__.py +0 -0
  91. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nba/espn/nba_espn_league_model.py +0 -0
  92. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nba/nba/__init__.py +0 -0
  93. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nba/nba/nba_nba_game_model.py +0 -0
  94. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nba/nba/nba_nba_team_model.py +0 -0
  95. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nba/oddsportal/__init__.py +0 -0
  96. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nba/oddsportal/nba_oddsportal_league_model.py +0 -0
  97. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nba/sportsdb/__init__.py +0 -0
  98. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nba/sportsdb/nba_sportsdb_league_model.py +0 -0
  99. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nba/sportsreference/__init__.py +0 -0
  100. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/ncaab/__init__.py +0 -0
  101. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/ncaab/combined/__init__.py +0 -0
  102. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/ncaab/espn/__init__.py +0 -0
  103. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/ncaab/espn/ncaab_espn_league_model.py +0 -0
  104. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/ncaab/oddsportal/__init__.py +0 -0
  105. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/ncaab/sportsreference/__init__.py +0 -0
  106. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/ncaaf/__init__.py +0 -0
  107. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/ncaaf/combined/__init__.py +0 -0
  108. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/ncaaf/espn/__init__.py +0 -0
  109. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/ncaaf/espn/ncaaf_espn_league_model.py +0 -0
  110. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/ncaaf/oddsportal/__init__.py +0 -0
  111. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/ncaaf/oddsportal/ncaaf_oddsportal_league_model.py +0 -0
  112. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/news_model.py +0 -0
  113. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nfl/__init__.py +0 -0
  114. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nfl/aussportsbetting/__init__.py +0 -0
  115. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nfl/combined/__init__.py +0 -0
  116. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nfl/espn/__init__.py +0 -0
  117. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nfl/oddsportal/__init__.py +0 -0
  118. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/nfl/sportsdb/__init__.py +0 -0
  119. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/odds_model.py +0 -0
  120. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/oddsportal/__init__.py +0 -0
  121. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/oddsportal/decrypt.py +0 -0
  122. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/oddsportal/oddsportal_bookie_model.py +0 -0
  123. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/oddsportal/oddsportal_game_model.py +0 -0
  124. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/oddsportal/oddsportal_odds_model.py +0 -0
  125. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/oddsportal/oddsportal_team_model.py +0 -0
  126. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/oddsportal/oddsportal_venue_model.py +0 -0
  127. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/player_model.py +0 -0
  128. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/season_type.py +0 -0
  129. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/social_model.py +0 -0
  130. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/sportsdb/__init__.py +0 -0
  131. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/sportsdb/sportsdb_game_model.py +0 -0
  132. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/sportsdb/sportsdb_team_model.py +0 -0
  133. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/sportsdb/sportsdb_venue_model.py +0 -0
  134. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/sportsreference/__init__.py +0 -0
  135. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/sportsreference/sportsreference_game_model.py +0 -0
  136. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/sportsreference/sportsreference_player_model.py +0 -0
  137. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/sportsreference/sportsreference_team_model.py +0 -0
  138. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/sportsreference/sportsreference_venue_model.py +0 -0
  139. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/team_model.py +0 -0
  140. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/venue_model.py +0 -0
  141. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/weather/__init__.py +0 -0
  142. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/weather/gribstream/__init__.py +0 -0
  143. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/weather/gribstream/gribstream_weather_model.py +0 -0
  144. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/weather/multi_weather_model.py +0 -0
  145. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/weather/openmeteo/__init__.py +0 -0
  146. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/weather/openmeteo/openmeteo_weather_model.py +0 -0
  147. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/weather_model.py +0 -0
  148. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/wikipedia/__init__.py +0 -0
  149. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/wikipedia/wikipedia_venue_model.py +0 -0
  150. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/x/__init__.py +0 -0
  151. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/data/x/x_social_model.py +0 -0
  152. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/logger.py +0 -0
  153. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/loglevel.py +0 -0
  154. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/playwright.py +0 -0
  155. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/proxy_session.py +0 -0
  156. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/session.py +0 -0
  157. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/vendor/__init__.py +0 -0
  158. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball/vendor/pygooglenews/__init__.py +0 -0
  159. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball.egg-info/dependency_links.txt +0 -0
  160. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball.egg-info/entry_points.txt +0 -0
  161. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball.egg-info/not-zip-safe +0 -0
  162. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball.egg-info/requires.txt +0 -0
  163. {sportsball-0.3.109 → sportsball-0.3.111}/sportsball.egg-info/top_level.txt +0 -0
  164. {sportsball-0.3.109 → sportsball-0.3.111}/tests/__init__.py +0 -0
  165. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/__init__.py +0 -0
  166. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/afl/__init__.py +0 -0
  167. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/afl/afl/__init__.py +0 -0
  168. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/afl/afl/afl_afl_league_model_test.py +0 -0
  169. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/afl/afltables/__init__.py +0 -0
  170. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/afl/afltables/afl_afltables_league_model_test.py +0 -0
  171. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/afl/afltables/afl_afltables_player_model_test.py +0 -0
  172. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/aussportsbetting/__init__.py +0 -0
  173. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/aussportsbetting/aussportsbetting_game_model_test.py +0 -0
  174. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/combined/__init__.py +0 -0
  175. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/combined/combined_game_model_test.py +0 -0
  176. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/combined/combined_player_model_test.py +0 -0
  177. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/combined/combined_team_model_test.py +0 -0
  178. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/espn/__init__.py +0 -0
  179. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/espn/espn_game_model_test.py +0 -0
  180. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/espn/espn_player_model_test.py +0 -0
  181. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/game_model_test.py +0 -0
  182. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/google/__init__.py +0 -0
  183. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/google/google_address_model_test.py +0 -0
  184. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/google/google_news_model_test.py +0 -0
  185. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/nba/__init__.py +0 -0
  186. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/nba/nba/__init__.py +0 -0
  187. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/nba/nba/nba_nba_game_model_test.py +0 -0
  188. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/nba/nba/nba_nba_league_model_test.py +0 -0
  189. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/nba/nba/nba_nba_team_model_test.py +0 -0
  190. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/nba/sportsdb/__init__.py +0 -0
  191. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/nba/sportsdb/nba_sportsdb_league_model_test.py +0 -0
  192. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/nba/sportsreference/__init__.py +0 -0
  193. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/nba/sportsreference/nba_sportsreference_league_model_test.py +0 -0
  194. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/ncaab/__init__.py +0 -0
  195. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/ncaab/sportsreference/__init__.py +0 -0
  196. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/ncaab/sportsreference/ncaab_sportsreference_league_model_test.py +0 -0
  197. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/nfl/__init__.py +0 -0
  198. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/nfl/sportsdb/__init__.py +0 -0
  199. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/nfl/sportsdb/nfl_sportsdb_league_model_test.py +0 -0
  200. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/oddsportal/__init__.py +0 -0
  201. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/oddsportal/decrypt_test.py +0 -0
  202. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/oddsportal/oddsportal_game_model_test.py +0 -0
  203. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/oddsportal/oddsportal_league_model_test.py +0 -0
  204. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/player_model_test.py +0 -0
  205. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/social_model_test.py +0 -0
  206. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/sportsdb/__init__.py +0 -0
  207. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/sportsdb/sportsdb_game_model_test.py +0 -0
  208. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/sportsdb/sportsdb_league_model_test.py +0 -0
  209. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/sportsdb/sportsdb_team_model_test.py +0 -0
  210. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/sportsdb/sportsdb_venue_model_test.py +0 -0
  211. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/sportsreference/__init__.py +0 -0
  212. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/sportsreference/sportsreference_game_model_test.py +0 -0
  213. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/sportsreference/sportsreference_league_model_test.py +0 -0
  214. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/sportsreference/sportsreference_player_model_test.py +0 -0
  215. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/sportsreference/sportsreference_team_model_test.py +0 -0
  216. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/sportsreference/sportsreference_venue_model_test.py +0 -0
  217. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/team_model_test.py +0 -0
  218. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/x/__init__.py +0 -0
  219. {sportsball-0.3.109 → sportsball-0.3.111}/tests/data/x/x_social_model_test.py +0 -0
  220. {sportsball-0.3.109 → sportsball-0.3.111}/tests/proxy_session_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: sportsball
3
- Version: 0.3.109
3
+ Version: 0.3.111
4
4
  Summary: A library for pulling in and normalising sports stats.
5
5
  Home-page: https://github.com/8W9aG/sportsball
6
6
  Author: Will Sackfield
@@ -26,7 +26,7 @@ def install_requires() -> typing.List[str]:
26
26
 
27
27
  setup(
28
28
  name='sportsball',
29
- version='0.3.109',
29
+ version='0.3.111',
30
30
  description='A library for pulling in and normalising sports stats.',
31
31
  long_description=long_description,
32
32
  long_description_content_type='text/markdown',
@@ -4,4 +4,4 @@
4
4
  import cchardet # type: ignore
5
5
  import lxml # noqa: ignore
6
6
 
7
- __VERSION__ = "0.3.109"
7
+ __VERSION__ = "0.3.111"
@@ -21,7 +21,7 @@ def main() -> None:
21
21
  logging.info("--- sportsball %s ---", __VERSION__)
22
22
 
23
23
  ball = SportsBall()
24
- league = ball.league(league_from_str(args.league))
24
+ league = ball.league(league_from_str(args.league), args.leaguemodel)
25
25
  df = league.to_frame()
26
26
  handle = io.BytesIO()
27
27
  df.to_parquet(handle, compression="gzip")
@@ -23,6 +23,11 @@ def parse_args() -> argparse.Namespace:
23
23
  help="The loglevel to display logs at..",
24
24
  required=False,
25
25
  )
26
+ parser.add_argument(
27
+ "--leaguemodel",
28
+ required=False,
29
+ help="The league model to use.",
30
+ )
26
31
  parser.add_argument(
27
32
  "file",
28
33
  default=STDOUT_FILE,
@@ -8,6 +8,7 @@ from typing import Iterator
8
8
 
9
9
  import requests_cache
10
10
  from bs4 import BeautifulSoup
11
+ from dateutil.parser import parse
11
12
  from playwright.sync_api import sync_playwright
12
13
 
13
14
  from ....playwright import ensure_install
@@ -73,6 +74,11 @@ def _parse_game_info(
73
74
  "time", {"class": re.compile(".*match-list-alt__header-time.*")}
74
75
  ):
75
76
  dt = datetime.datetime.fromtimestamp(float(time.get("data-date")) / 1000.0)
77
+ for span_tz in div.find_all(
78
+ "span", {"class": re.compile(".*match-list-alt__header-timezone.*")}
79
+ ):
80
+ tz_text = span_tz.get_text().strip().replace("(", "").replace(")", "")
81
+ dt = parse(" ".join([str(dt), tz_text]))
76
82
  venue_name: str | None = None
77
83
  for span in div.find_all(
78
84
  "span", {"class": re.compile(".*match-list-alt__header-venue.*")}
@@ -95,6 +101,10 @@ class AFLAFLLeagueModel(LeagueModel):
95
101
  ) -> None:
96
102
  super().__init__(League.AFL, session)
97
103
 
104
+ @classmethod
105
+ def name(cls) -> str:
106
+ return "afl-afl-league-model"
107
+
98
108
  @property
99
109
  def _ladder(self) -> list[str]:
100
110
  ladder = []
@@ -47,6 +47,10 @@ class AFLAFLTablesLeagueModel(LeagueModel):
47
47
  ) -> None:
48
48
  super().__init__(League.AFL, session)
49
49
 
50
+ @classmethod
51
+ def name(cls) -> str:
52
+ return "afl-afltables-league-model"
53
+
50
54
  def _produce_games(
51
55
  self, season_url: str, season_type: SeasonType, pbar: tqdm.tqdm
52
56
  ) -> Iterator[GameModel]:
@@ -14,3 +14,7 @@ class AFLAusSportsBettingLeagueModel(AusSportsBettingLeagueModel):
14
14
  self, session: requests_cache.CachedSession, position: int | None = None
15
15
  ) -> None:
16
16
  super().__init__(League.AFL, session, position=position)
17
+
18
+ @classmethod
19
+ def name(cls) -> str:
20
+ return "afl-aussportsbetting-league-model"
@@ -251,7 +251,9 @@ AFL_VENUE_IDENTITY_MAP = {
251
251
  class AFLCombinedLeagueModel(CombinedLeagueModel):
252
252
  """AFL combined implementation of the league model."""
253
253
 
254
- def __init__(self, session: requests_cache.CachedSession) -> None:
254
+ def __init__(
255
+ self, session: requests_cache.CachedSession, league_filter: str | None
256
+ ) -> None:
255
257
  super().__init__(
256
258
  session,
257
259
  League.AFL,
@@ -262,6 +264,7 @@ class AFLCombinedLeagueModel(CombinedLeagueModel):
262
264
  AFLOddsPortalLeagueModel(session, position=3),
263
265
  AFLAFLLeagueModel(session, position=4),
264
266
  ],
267
+ league_filter,
265
268
  )
266
269
 
267
270
  @classmethod
@@ -271,3 +274,7 @@ class AFLCombinedLeagueModel(CombinedLeagueModel):
271
274
  @classmethod
272
275
  def venue_identity_map(cls) -> dict[str, str]:
273
276
  return AFL_VENUE_IDENTITY_MAP
277
+
278
+ @classmethod
279
+ def name(cls) -> str:
280
+ return "afl-combined-league-model"
@@ -15,3 +15,7 @@ class AFLOddsPortalLeagueModel(OddsPortalLeagueModel):
15
15
  self, session: requests_cache.CachedSession, position: int | None = None
16
16
  ) -> None:
17
17
  super().__init__(League.AFL, session, position=position)
18
+
19
+ @classmethod
20
+ def name(cls) -> str:
21
+ return "afl-oddsportal-league-model"
@@ -39,6 +39,10 @@ class AusSportsBettingLeagueModel(LeagueModel):
39
39
  f"League {league} not supported by aus sports betting."
40
40
  )
41
41
 
42
+ @classmethod
43
+ def name(cls) -> str:
44
+ return "aussportsbetting-league-model"
45
+
42
46
  def _row_to_game(self, row: Any) -> GameModel | None:
43
47
  current_cell_idx = 0
44
48
  date_cell = str(row[0].value)
@@ -2,6 +2,7 @@
2
2
 
3
3
  from ..address_model import AddressModel
4
4
  from .combined_weather_model import create_combined_weather_model
5
+ from .null_check import is_null
5
6
 
6
7
 
7
8
  def create_combined_address_model(
@@ -16,16 +17,16 @@ def create_combined_address_model(
16
17
  weather_models = []
17
18
  for address_model in address_models:
18
19
  address_model_latitude = address_model.latitude
19
- if address_model_latitude is not None:
20
+ if not is_null(address_model_latitude):
20
21
  latitude = address_model_latitude
21
22
  address_model_longitude = address_model.longitude
22
- if address_model_longitude is not None:
23
+ if not is_null(address_model_longitude):
23
24
  longitude = address_model_longitude
24
25
  address_model_housenumber = address_model.housenumber
25
- if address_model_housenumber is not None:
26
+ if not is_null(address_model_housenumber):
26
27
  housenumber = address_model_housenumber
27
28
  address_model_weather = address_model.weather
28
- if address_model_weather is not None:
29
+ if not is_null(address_model_weather):
29
30
  weather_models.append(address_model_weather)
30
31
  return AddressModel(
31
32
  city=address_models[0].city,
@@ -34,7 +35,7 @@ def create_combined_address_model(
34
35
  latitude=latitude,
35
36
  longitude=longitude,
36
37
  housenumber=housenumber,
37
- weather=create_combined_weather_model(weather_models), # pyright: ignore
38
+ weather=create_combined_weather_model(weather_models), # type: ignore
38
39
  timezone=address_models[0].timezone,
39
40
  country=address_models[0].country,
40
41
  )
@@ -1,6 +1,6 @@
1
1
  """Combined game model."""
2
2
 
3
- # pylint: disable=too-many-locals,line-too-long,too-many-arguments
3
+ # pylint: disable=too-many-locals,line-too-long,too-many-arguments,too-many-branches
4
4
  import logging
5
5
 
6
6
  import requests
@@ -10,6 +10,7 @@ from ..team_model import TeamModel
10
10
  from ..venue_model import VenueModel
11
11
  from .combined_team_model import create_combined_team_model
12
12
  from .combined_venue_model import create_combined_venue_model
13
+ from .null_check import is_null
13
14
 
14
15
 
15
16
  def _venue_models(
@@ -78,30 +79,34 @@ def create_combined_game_model(
78
79
  game_number = None
79
80
  postponed = None
80
81
  play_off = None
82
+ dt = game_models[0].dt
81
83
  for game_model in game_models:
84
+ game_model_dt = game_model.dt
85
+ if game_model_dt.tzinfo is not None and dt.tzinfo is None:
86
+ dt = game_model_dt
82
87
  game_model_attendance = game_model.attendance
83
- if game_model_attendance is not None:
88
+ if not is_null(game_model_attendance):
84
89
  attendance = game_model_attendance
85
90
  game_model_end_dt = game_model.end_dt
86
- if game_model_end_dt is not None:
91
+ if not is_null(game_model_end_dt):
87
92
  end_dt = game_model_end_dt
88
93
  game_model_year = game_model.year
89
- if game_model_year is not None:
94
+ if not is_null(game_model_year):
90
95
  year = game_model_year
91
96
  game_model_season_type = game_model.season_type
92
- if game_model_season_type is not None:
97
+ if not is_null(game_model_season_type):
93
98
  season_type = game_model_season_type
94
99
  game_model_week = game_model.week
95
- if game_model_week is not None:
100
+ if not is_null(game_model_week):
96
101
  week = game_model_week
97
102
  game_model_game_number = game_model.game_number
98
- if game_model_game_number is not None:
103
+ if not is_null(game_model_game_number):
99
104
  game_number = game_model_game_number
100
105
  game_model_postponed = game_model.postponed
101
- if game_model_postponed is not None:
106
+ if not is_null(game_model_postponed):
102
107
  postponed = game_model_postponed
103
108
  game_model_play_off = game_model.play_off
104
- if game_model_play_off is not None:
109
+ if not is_null(game_model_play_off):
105
110
  play_off = game_model_play_off
106
111
 
107
112
  if full_venue_identity is None and venue_models:
@@ -111,7 +116,7 @@ def create_combined_game_model(
111
116
  full_venue_identity = venue_model_identifier
112
117
 
113
118
  return GameModel(
114
- dt=game_models[0].dt,
119
+ dt=dt,
115
120
  week=week,
116
121
  game_number=game_number,
117
122
  venue=create_combined_venue_model(venue_models, full_venue_identity, session), # pyright: ignore
@@ -26,8 +26,13 @@ class CombinedLeagueModel(LeagueModel):
26
26
  session: requests_cache.CachedSession,
27
27
  league: League,
28
28
  league_models: list[LeagueModel],
29
+ league_filter: str | None,
29
30
  ) -> None:
30
31
  super().__init__(league, session)
32
+ if league_filter is not None:
33
+ league_models = [x for x in league_models if x.name() == league_filter]
34
+ if not league_models:
35
+ raise ValueError("No league models to run")
31
36
  self._league_models = league_models
32
37
 
33
38
  @classmethod
@@ -2,6 +2,7 @@
2
2
 
3
3
  # pylint: disable=too-many-locals,too-many-branches,too-many-statements,duplicate-code
4
4
  from ..player_model import PlayerModel
5
+ from .null_check import is_null
5
6
 
6
7
 
7
8
  def create_combined_player_model(
@@ -42,100 +43,100 @@ def create_combined_player_model(
42
43
  percentage_played = None
43
44
  for player_model in player_models:
44
45
  player_model_jersey = player_model.jersey
45
- if player_model_jersey is not None:
46
+ if not is_null(player_model_jersey):
46
47
  jersey = player_model_jersey
47
48
  player_model_kicks = player_model.kicks
48
- if player_model_kicks is not None:
49
+ if not is_null(player_model_kicks):
49
50
  kicks = player_model_kicks
50
51
  player_model_fumbles = player_model.fumbles
51
- if player_model_fumbles is not None:
52
+ if not is_null(player_model_fumbles):
52
53
  fumbles = player_model_fumbles
53
54
  player_model_fumbles_lost = player_model.fumbles_lost
54
- if player_model_fumbles_lost is not None:
55
+ if not is_null(player_model_fumbles_lost):
55
56
  fumbles_lost = player_model_fumbles_lost
56
57
  player_model_field_goals = player_model.field_goals
57
- if player_model_field_goals is not None:
58
+ if not is_null(player_model_field_goals):
58
59
  field_goals = player_model_field_goals
59
60
  player_model_field_goals_attempted = player_model.field_goals_attempted
60
- if player_model_field_goals_attempted is not None:
61
+ if not is_null(player_model_field_goals_attempted):
61
62
  field_goals_attempted = player_model_field_goals_attempted
62
63
  player_model_offensive_rebounds = player_model.offensive_rebounds
63
- if player_model_offensive_rebounds is not None:
64
+ if not is_null(player_model_offensive_rebounds):
64
65
  offensive_rebounds = player_model_offensive_rebounds
65
66
  player_model_assists = player_model.assists
66
- if player_model_assists is not None:
67
+ if not is_null(player_model_assists):
67
68
  assists = player_model_assists
68
69
  player_model_turnovers = player_model.turnovers
69
- if player_model_turnovers is not None:
70
+ if not is_null(player_model_turnovers):
70
71
  turnovers = player_model_turnovers
71
72
  player_model_name = player_model.name
72
- if player_model_name is not None:
73
+ if not is_null(player_model_name):
73
74
  name = player_model_name
74
75
  player_model_marks = player_model.marks
75
- if player_model_marks is not None:
76
+ if not is_null(player_model_marks):
76
77
  marks = player_model_marks
77
78
  player_model_handballs = player_model.handballs
78
- if player_model_handballs is not None:
79
+ if not is_null(player_model_handballs):
79
80
  handballs = player_model_handballs
80
81
  player_model_disposals = player_model.disposals
81
- if player_model_disposals is not None:
82
+ if not is_null(player_model_disposals):
82
83
  disposals = player_model_disposals
83
84
  player_model_goals = player_model.goals
84
- if player_model_goals is not None:
85
+ if not is_null(player_model_goals):
85
86
  goals = player_model_goals
86
87
  player_model_behinds = player_model.behinds
87
- if player_model_behinds is not None:
88
+ if not is_null(player_model_behinds):
88
89
  behinds = player_model_behinds
89
90
  player_model_hit_outs = player_model.hit_outs
90
- if player_model_hit_outs is not None:
91
+ if not is_null(player_model_hit_outs):
91
92
  hit_outs = player_model_hit_outs
92
93
  player_model_tackles = player_model.tackles
93
- if player_model_tackles is not None:
94
+ if not is_null(player_model_tackles):
94
95
  tackles = player_model_tackles
95
96
  player_model_rebounds = player_model.rebounds
96
- if player_model_rebounds is not None:
97
+ if not is_null(player_model_rebounds):
97
98
  rebounds = player_model_rebounds
98
99
  player_model_insides = player_model.insides
99
- if player_model_insides is not None:
100
+ if not is_null(player_model_insides):
100
101
  insides = player_model_insides
101
102
  player_model_clearances = player_model.clearances
102
- if player_model_clearances is not None:
103
+ if not is_null(player_model_clearances):
103
104
  clearances = player_model_clearances
104
105
  player_model_clangers = player_model.clangers
105
- if player_model_clangers is not None:
106
+ if not is_null(player_model_clangers):
106
107
  clangers = player_model_clangers
107
108
  player_model_free_kicks_for = player_model.free_kicks_for
108
- if player_model_free_kicks_for is not None:
109
+ if not is_null(player_model_free_kicks_for):
109
110
  free_kicks_for = player_model_free_kicks_for
110
111
  player_model_free_kicks_against = player_model.free_kicks_against
111
- if player_model_free_kicks_against is not None:
112
+ if not is_null(player_model_free_kicks_against):
112
113
  free_kicks_against = player_model_free_kicks_against
113
114
  player_model_brownlow_votes = player_model.brownlow_votes
114
- if player_model_brownlow_votes is not None:
115
+ if not is_null(player_model_brownlow_votes):
115
116
  brownlow_votes = player_model_brownlow_votes
116
117
  player_model_contested_possessions = player_model.contested_possessions
117
- if player_model_contested_possessions is not None:
118
+ if not is_null(player_model_contested_possessions):
118
119
  contested_possessions = player_model_contested_possessions
119
120
  player_model_uncontested_possessions = player_model.uncontested_possessions
120
- if player_model_uncontested_possessions is not None:
121
+ if not is_null(player_model_uncontested_possessions):
121
122
  uncontested_possessions = player_model_uncontested_possessions
122
123
  player_model_contested_marks = player_model.contested_marks
123
- if player_model_contested_marks is not None:
124
+ if not is_null(player_model_contested_marks):
124
125
  contested_marks = player_model_contested_marks
125
126
  player_model_marks_inside = player_model.marks_inside
126
- if player_model_marks_inside is not None:
127
+ if not is_null(player_model_marks_inside):
127
128
  marks_inside = player_model_marks_inside
128
129
  player_model_one_percenters = player_model.one_percenters
129
- if player_model_one_percenters is not None:
130
+ if not is_null(player_model_one_percenters):
130
131
  one_percenters = player_model_one_percenters
131
132
  player_model_bounces = player_model.bounces
132
- if player_model_bounces is not None:
133
+ if not is_null(player_model_bounces):
133
134
  bounces = player_model_bounces
134
135
  player_model_goal_assists = player_model.goal_assists
135
- if player_model_goal_assists is not None:
136
+ if not is_null(player_model_goal_assists):
136
137
  goal_assists = player_model_goal_assists
137
138
  player_model_percentage_played = player_model.percentage_played
138
- if player_model_percentage_played is not None:
139
+ if not is_null(player_model_percentage_played):
139
140
  percentage_played = player_model_percentage_played
140
141
  if name is None:
141
142
  raise ValueError("name is null.")
@@ -10,6 +10,7 @@ from ..player_model import PlayerModel
10
10
  from ..social_model import SocialModel
11
11
  from ..team_model import TeamModel
12
12
  from .combined_player_model import create_combined_player_model
13
+ from .null_check import is_null
13
14
 
14
15
  REGEX = re.compile("[^a-zA-Z]")
15
16
 
@@ -54,10 +55,10 @@ def create_combined_team_model(
54
55
  key = f"{odds_model.bookie.identifier}-{odds_model.odds}"
55
56
  odds[key] = odds.get(key, []) + [odds_model]
56
57
  team_model_points = team_model.points
57
- if team_model_points is not None:
58
+ if not is_null(team_model_points):
58
59
  points = team_model_points
59
60
  team_model_ladder_rank = team_model.ladder_rank
60
- if team_model_ladder_rank is not None:
61
+ if not is_null(team_model_ladder_rank):
61
62
  ladder_rank = team_model_ladder_rank
62
63
  for news_model in team_model.news:
63
64
  news_key = "-".join(
@@ -75,7 +76,7 @@ def create_combined_team_model(
75
76
  )
76
77
  social[social_key] = social_model
77
78
  team_model_field_goals = team_model.field_goals
78
- if team_model_field_goals is not None:
79
+ if not is_null(team_model_field_goals):
79
80
  field_goals = team_model_field_goals
80
81
 
81
82
  return TeamModel(
@@ -5,6 +5,7 @@ import requests
5
5
  from ..venue_model import VenueModel
6
6
  from ..wikipedia.wikipedia_venue_model import create_wikipedia_venue_model
7
7
  from .combined_address_model import create_combined_address_model
8
+ from .null_check import is_null
8
9
 
9
10
 
10
11
  def create_combined_venue_model(
@@ -24,18 +25,18 @@ def create_combined_venue_model(
24
25
  is_indoor = None
25
26
  for venue_model in venue_models:
26
27
  venue_model_address = venue_model.address
27
- if venue_model_address is not None:
28
+ if not is_null(venue_model_address):
28
29
  address_models.append(venue_model_address)
29
30
  venue_model_is_grass = venue_model.is_grass
30
- if venue_model_is_grass is not None:
31
+ if not is_null(venue_model_is_grass):
31
32
  is_grass = venue_model_is_grass
32
33
  venue_model_is_indoor = venue_model.is_indoor
33
- if venue_model_is_indoor is not None:
34
+ if not is_null(venue_model_is_indoor):
34
35
  is_indoor = venue_model_is_indoor
35
36
  return VenueModel(
36
37
  identifier=identifier,
37
38
  name=venue_models[0].name,
38
- address=create_combined_address_model(address_models), # pyright: ignore
39
+ address=create_combined_address_model(address_models), # type: ignore
39
40
  is_grass=is_grass,
40
41
  is_indoor=is_indoor,
41
42
  )
@@ -1,6 +1,7 @@
1
1
  """Combined weather model."""
2
2
 
3
3
  from ..weather_model import WeatherModel
4
+ from .null_check import is_null
4
5
 
5
6
 
6
7
  def create_combined_weather_model(
@@ -13,9 +14,9 @@ def create_combined_weather_model(
13
14
  relative_humidity = None
14
15
  for weather_model in weather_models:
15
16
  weather_model_temperature = weather_model.temperature
16
- if weather_model_temperature is not None:
17
+ if not is_null(weather_model_temperature):
17
18
  temperature = weather_model_temperature
18
19
  weather_model_relative_humidity = weather_model.relative_humidity
19
- if weather_model_relative_humidity is not None:
20
+ if not is_null(weather_model_relative_humidity):
20
21
  relative_humidity = weather_model_relative_humidity
21
22
  return WeatherModel(temperature=temperature, relative_humidity=relative_humidity)
@@ -0,0 +1,22 @@
1
+ """A function for checking whether an object is null."""
2
+
3
+ from typing import Any
4
+
5
+ import numpy as np
6
+
7
+
8
+ def is_null(obj: Any) -> bool:
9
+ """Whether the object is a null type object."""
10
+ if obj is None:
11
+ return True
12
+ try:
13
+ if np.isnan(obj):
14
+ return True
15
+ except TypeError:
16
+ pass
17
+ try:
18
+ if np.isnat(obj):
19
+ return True
20
+ except TypeError:
21
+ pass
22
+ return False
@@ -38,6 +38,10 @@ class ESPNLeagueModel(LeagueModel):
38
38
  super().__init__(league, session, position=position)
39
39
  self._start_url = start_url
40
40
 
41
+ @classmethod
42
+ def name(cls) -> str:
43
+ return "espn-league-model"
44
+
41
45
  def _produce_games(
42
46
  self,
43
47
  week: dict[str, Any],
@@ -13722,6 +13722,33 @@ _CACHED_GEOCODES: dict[str, Any] = {
13722
13722
  country="USA",
13723
13723
  ),
13724
13724
  "Ninja Stadium": BLUNDSTONE_ARENA,
13725
+ "Summit Arena, Rapid City, South Dakota": SportsballGeocodeTuple(
13726
+ city="Rapid City",
13727
+ state="SD",
13728
+ postal="",
13729
+ lat=44.08854,
13730
+ lng=-103.225816,
13731
+ housenumber="444",
13732
+ country="USA",
13733
+ ),
13734
+ "Charleston, West Virginia": SportsballGeocodeTuple(
13735
+ city="Charleston",
13736
+ state="WV",
13737
+ postal="",
13738
+ lat=38.349819,
13739
+ lng=-81.632622,
13740
+ housenumber="",
13741
+ country="USA",
13742
+ ),
13743
+ "Shreveport, Louisiana": SportsballGeocodeTuple(
13744
+ city="Shreveport",
13745
+ state="LA",
13746
+ postal="",
13747
+ lat=32.463889,
13748
+ lng=-93.794444,
13749
+ housenumber="",
13750
+ country="USA",
13751
+ ),
13725
13752
  }
13726
13753
 
13727
13754
 
@@ -1,6 +1,7 @@
1
1
  """The prototype class defining how to interface to the league."""
2
2
 
3
3
  # pylint: disable=line-too-long
4
+ import datetime
4
5
  from typing import Iterator, get_args, get_origin
5
6
 
6
7
  import pandas as pd
@@ -35,6 +36,7 @@ def _normalize_tz(df: pd.DataFrame) -> pd.DataFrame:
35
36
  )
36
37
  if tz_column not in df.columns.values.tolist():
37
38
  return df
39
+ df = df.dropna(subset=tz_column)
38
40
 
39
41
  tqdm.tqdm.pandas(desc="Timezone Conversions")
40
42
 
@@ -46,18 +48,24 @@ def _normalize_tz(df: pd.DataFrame) -> pd.DataFrame:
46
48
  if pd.isnull(tz):
47
49
  return row
48
50
 
49
- datetimes = {
50
- col: val for col, val in row.items() if isinstance(val, pd.Timestamp)
51
+ datetime_cols = {
52
+ col for col, val in row.items() if isinstance(val, pd.Timestamp)
51
53
  }
52
- for col, dt in datetimes.items():
54
+ datetime_cols.add(GAME_DT_COLUMN)
55
+ for col in datetime_cols:
56
+ dt = row[col] # type: ignore
57
+ if isinstance(dt, datetime.datetime):
58
+ dt = pd.to_datetime(dt)
53
59
  if dt.tz is None:
54
- row[col] = dt.tz_localize(tz, ambiguous=True)
60
+ row[col] = dt.tz_localize(
61
+ tz, ambiguous=True, nonexistent="shift_forward"
62
+ )
55
63
  elif str(dt.tz) != str(tz):
56
64
  row[col] = dt.tz_convert(tz)
57
65
 
58
66
  return row
59
67
 
60
- return df.apply(apply_tz, axis=1)
68
+ return df.progress_apply(apply_tz, axis=1) # type: ignore
61
69
 
62
70
 
63
71
  class LeagueModel(Model):
@@ -76,6 +84,11 @@ class LeagueModel(Model):
76
84
  self._df = None
77
85
  self.position = position
78
86
 
87
+ @classmethod
88
+ def name(cls) -> str:
89
+ """The name of the league model."""
90
+ raise NotImplementedError("name is not implemented by parent class.")
91
+
79
92
  @property
80
93
  def games(self) -> Iterator[GameModel]:
81
94
  """Find all the games in this league."""
@@ -180,12 +193,16 @@ class LeagueModel(Model):
180
193
  df = _normalize_tz(df)
181
194
 
182
195
  if GAME_DT_COLUMN in df.columns.values:
183
- df[GAME_DT_COLUMN] = pd.to_datetime(df[GAME_DT_COLUMN], utc=True)
196
+ # df[GAME_DT_COLUMN] = pd.to_datetime(df[GAME_DT_COLUMN])
197
+ # naive_times = df[df[GAME_DT_COLUMN].dt.tz.isna()]
198
+ # print("naive_times:")
199
+ # print(naive_times)
184
200
  df = df.sort_values(
185
201
  by=GAME_DT_COLUMN,
186
202
  ascending=True,
187
203
  )
188
204
  df = _clear_column_list(df)
205
+ df = df.reset_index()
189
206
 
190
207
  df = df[sorted(df.columns.values.tolist())]
191
208