sportsball 0.3.31__tar.gz → 0.3.33__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 (209) hide show
  1. {sportsball-0.3.31/sportsball.egg-info → sportsball-0.3.33}/PKG-INFO +1 -1
  2. {sportsball-0.3.31 → sportsball-0.3.33}/setup.py +1 -1
  3. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/__init__.py +1 -1
  4. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/address_model.py +3 -1
  5. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/google/google_address_model.py +136 -0
  6. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/oddsportal/decrypt.py +14 -2
  7. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/oddsportal/oddsportal_game_model.py +14 -7
  8. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/oddsportal/oddsportal_league_model.py +26 -12
  9. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/oddsportal/oddsportal_team_model.py +27 -21
  10. {sportsball-0.3.31 → sportsball-0.3.33/sportsball.egg-info}/PKG-INFO +1 -1
  11. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball.egg-info/SOURCES.txt +1 -0
  12. sportsball-0.3.33/tests/data/oddsportal/oddsportal_league_model_test.py +19 -0
  13. {sportsball-0.3.31 → sportsball-0.3.33}/LICENSE +0 -0
  14. {sportsball-0.3.31 → sportsball-0.3.33}/MANIFEST.in +0 -0
  15. {sportsball-0.3.31 → sportsball-0.3.33}/README.md +0 -0
  16. {sportsball-0.3.31 → sportsball-0.3.33}/requirements.txt +0 -0
  17. {sportsball-0.3.31 → sportsball-0.3.33}/setup.cfg +0 -0
  18. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/__main__.py +0 -0
  19. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/args.py +0 -0
  20. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/cache.py +0 -0
  21. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/__init__.py +0 -0
  22. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/afl/__init__.py +0 -0
  23. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/afl/afltables/__init__.py +0 -0
  24. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/afl/afltables/afl_afltables_game_model.py +0 -0
  25. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/afl/afltables/afl_afltables_league_model.py +0 -0
  26. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/afl/afltables/afl_afltables_player_model.py +0 -0
  27. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/afl/afltables/afl_afltables_team_model.py +0 -0
  28. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/afl/afltables/afl_afltables_venue_model.py +0 -0
  29. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/afl/aussportsbetting/__init__.py +0 -0
  30. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/afl/aussportsbetting/afl_aussportsbetting_league_model.py +0 -0
  31. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/afl/combined/__init__.py +0 -0
  32. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/afl/combined/afl_combined_league_model.py +0 -0
  33. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/afl/espn/__init__.py +0 -0
  34. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/afl/espn/afl_espn_league_model.py +0 -0
  35. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/afl/oddsportal/__init__.py +0 -0
  36. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/afl/oddsportal/afl_oddsportal_league_model.py +0 -0
  37. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/aussportsbetting/__init__.py +0 -0
  38. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/aussportsbetting/aussportsbetting_bookie_model.py +0 -0
  39. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/aussportsbetting/aussportsbetting_game_model.py +0 -0
  40. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/aussportsbetting/aussportsbetting_league_model.py +0 -0
  41. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/aussportsbetting/aussportsbetting_odds_model.py +0 -0
  42. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/aussportsbetting/aussportsbetting_team_model.py +0 -0
  43. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/aussportsbetting/aussportsbetting_venue_model.py +0 -0
  44. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/bookie_model.py +0 -0
  45. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/combined/__init__.py +0 -0
  46. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/combined/combined_address_model.py +0 -0
  47. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/combined/combined_game_model.py +0 -0
  48. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/combined/combined_league_model.py +0 -0
  49. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/combined/combined_player_model.py +0 -0
  50. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/combined/combined_team_model.py +0 -0
  51. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/combined/combined_venue_model.py +0 -0
  52. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/combined/combined_weather_model.py +0 -0
  53. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/espn/__init__.py +0 -0
  54. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/espn/espn_bookie_model.py +0 -0
  55. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/espn/espn_game_model.py +0 -0
  56. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/espn/espn_league_model.py +0 -0
  57. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/espn/espn_odds_model.py +0 -0
  58. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/espn/espn_player_model.py +0 -0
  59. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/espn/espn_team_model.py +0 -0
  60. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/espn/espn_venue_model.py +0 -0
  61. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/field_type.py +0 -0
  62. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/game_model.py +0 -0
  63. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/google/__init__.py +0 -0
  64. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/google/google_news_model.py +0 -0
  65. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/league.py +0 -0
  66. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/league_model.py +0 -0
  67. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/model.py +0 -0
  68. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nba/__init__.py +0 -0
  69. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nba/combined/__init__.py +0 -0
  70. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nba/combined/nba_combined_league_model.py +0 -0
  71. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nba/espn/__init__.py +0 -0
  72. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nba/espn/nba_espn_league_model.py +0 -0
  73. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nba/nba/__init__.py +0 -0
  74. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nba/nba/nba_nba_game_model.py +0 -0
  75. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nba/nba/nba_nba_league_model.py +0 -0
  76. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nba/nba/nba_nba_player_model.py +0 -0
  77. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nba/nba/nba_nba_team_model.py +0 -0
  78. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nba/oddsportal/__init__.py +0 -0
  79. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nba/oddsportal/nba_oddsportal_league_model.py +0 -0
  80. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nba/sportsdb/__init__.py +0 -0
  81. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nba/sportsdb/nba_sportsdb_league_model.py +0 -0
  82. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nba/sportsreference/__init__.py +0 -0
  83. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nba/sportsreference/nba_sportsreference_league_model.py +0 -0
  84. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/ncaab/__init__.py +0 -0
  85. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/ncaab/combined/__init__.py +0 -0
  86. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/ncaab/combined/ncaab_combined_league_model.py +0 -0
  87. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/ncaab/espn/__init__.py +0 -0
  88. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/ncaab/espn/ncaab_espn_league_model.py +0 -0
  89. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/ncaab/oddsportal/__init__.py +0 -0
  90. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/ncaab/oddsportal/ncaab_oddsportal_league_model.py +0 -0
  91. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/ncaab/sportsreference/__init__.py +0 -0
  92. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/ncaab/sportsreference/ncaab_sportsreference_league_model.py +0 -0
  93. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/ncaaf/__init__.py +0 -0
  94. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/ncaaf/combined/__init__.py +0 -0
  95. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/ncaaf/combined/ncaaf_combined_league_model.py +0 -0
  96. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/ncaaf/espn/__init__.py +0 -0
  97. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/ncaaf/espn/ncaaf_espn_league_model.py +0 -0
  98. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/ncaaf/oddsportal/__init__.py +0 -0
  99. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/ncaaf/oddsportal/ncaaf_oddsportal_league_model.py +0 -0
  100. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/news_model.py +0 -0
  101. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nfl/__init__.py +0 -0
  102. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nfl/aussportsbetting/__init__.py +0 -0
  103. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nfl/aussportsbetting/nfl_aussportsbetting_league_model.py +0 -0
  104. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nfl/combined/__init__.py +0 -0
  105. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nfl/combined/nfl_combined_league_model.py +0 -0
  106. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nfl/espn/__init__.py +0 -0
  107. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nfl/espn/nfl_espn_league_model.py +0 -0
  108. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nfl/oddsportal/__init__.py +0 -0
  109. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nfl/oddsportal/nfl_oddsportal_league_model.py +0 -0
  110. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nfl/sportsdb/__init__.py +0 -0
  111. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/nfl/sportsdb/nfl_sportsdb_league_model.py +0 -0
  112. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/odds_model.py +0 -0
  113. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/oddsportal/__init__.py +0 -0
  114. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/oddsportal/oddsportal_bookie_model.py +0 -0
  115. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/oddsportal/oddsportal_odds_model.py +0 -0
  116. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/oddsportal/oddsportal_venue_model.py +0 -0
  117. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/player_model.py +0 -0
  118. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/season_type.py +0 -0
  119. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/social_model.py +0 -0
  120. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/sportsdb/__init__.py +0 -0
  121. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/sportsdb/sportsdb_game_model.py +0 -0
  122. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/sportsdb/sportsdb_league_model.py +0 -0
  123. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/sportsdb/sportsdb_team_model.py +0 -0
  124. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/sportsdb/sportsdb_venue_model.py +0 -0
  125. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/sportsreference/__init__.py +0 -0
  126. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/sportsreference/sportsreference_game_model.py +0 -0
  127. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/sportsreference/sportsreference_league_model.py +0 -0
  128. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/sportsreference/sportsreference_player_model.py +0 -0
  129. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/sportsreference/sportsreference_team_model.py +0 -0
  130. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/sportsreference/sportsreference_venue_model.py +0 -0
  131. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/team_model.py +0 -0
  132. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/venue_model.py +0 -0
  133. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/weather/__init__.py +0 -0
  134. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/weather/gribstream/__init__.py +0 -0
  135. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/weather/gribstream/gribstream_weather_model.py +0 -0
  136. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/weather/multi_weather_model.py +0 -0
  137. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/weather/openmeteo/__init__.py +0 -0
  138. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/weather/openmeteo/openmeteo_weather_model.py +0 -0
  139. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/weather_model.py +0 -0
  140. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/wikipedia/__init__.py +0 -0
  141. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/wikipedia/wikipedia_venue_model.py +0 -0
  142. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/x/__init__.py +0 -0
  143. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/data/x/x_social_model.py +0 -0
  144. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/logger.py +0 -0
  145. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/loglevel.py +0 -0
  146. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/proxy_session.py +0 -0
  147. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/session.py +0 -0
  148. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/sportsball.py +0 -0
  149. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/vendor/__init__.py +0 -0
  150. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball/vendor/pygooglenews/__init__.py +0 -0
  151. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball.egg-info/dependency_links.txt +0 -0
  152. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball.egg-info/entry_points.txt +0 -0
  153. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball.egg-info/not-zip-safe +0 -0
  154. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball.egg-info/requires.txt +0 -0
  155. {sportsball-0.3.31 → sportsball-0.3.33}/sportsball.egg-info/top_level.txt +0 -0
  156. {sportsball-0.3.31 → sportsball-0.3.33}/tests/__init__.py +0 -0
  157. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/__init__.py +0 -0
  158. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/afl/__init__.py +0 -0
  159. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/afl/afltables/__init__.py +0 -0
  160. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/afl/afltables/afl_afltables_league_model_test.py +0 -0
  161. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/afl/afltables/afl_afltables_player_model_test.py +0 -0
  162. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/aussportsbetting/__init__.py +0 -0
  163. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/aussportsbetting/aussportsbetting_game_model_test.py +0 -0
  164. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/combined/__init__.py +0 -0
  165. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/combined/combined_game_model_test.py +0 -0
  166. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/combined/combined_player_model_test.py +0 -0
  167. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/espn/__init__.py +0 -0
  168. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/espn/espn_game_model_test.py +0 -0
  169. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/espn/espn_player_model_test.py +0 -0
  170. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/game_model_test.py +0 -0
  171. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/google/__init__.py +0 -0
  172. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/google/google_address_model_test.py +0 -0
  173. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/google/google_news_model_test.py +0 -0
  174. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/nba/__init__.py +0 -0
  175. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/nba/nba/__init__.py +0 -0
  176. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/nba/nba/nba_nba_game_model_test.py +0 -0
  177. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/nba/nba/nba_nba_league_model_test.py +0 -0
  178. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/nba/nba/nba_nba_player_model_test.py +0 -0
  179. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/nba/nba/nba_nba_team_model_test.py +0 -0
  180. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/nba/sportsdb/__init__.py +0 -0
  181. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/nba/sportsdb/nba_sportsdb_league_model_test.py +0 -0
  182. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/nba/sportsreference/__init__.py +0 -0
  183. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/nba/sportsreference/nba_sportsreference_league_model_test.py +0 -0
  184. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/ncaab/__init__.py +0 -0
  185. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/ncaab/sportsreference/__init__.py +0 -0
  186. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/ncaab/sportsreference/ncaab_sportsreference_league_model_test.py +0 -0
  187. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/nfl/__init__.py +0 -0
  188. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/nfl/sportsdb/__init__.py +0 -0
  189. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/nfl/sportsdb/nfl_sportsdb_league_model_test.py +0 -0
  190. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/oddsportal/__init__.py +0 -0
  191. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/oddsportal/oddsportal_game_model_test.py +0 -0
  192. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/player_model_test.py +0 -0
  193. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/social_model_test.py +0 -0
  194. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/sportsdb/__init__.py +0 -0
  195. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/sportsdb/sportsdb_game_model_test.py +0 -0
  196. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/sportsdb/sportsdb_league_model_test.py +0 -0
  197. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/sportsdb/sportsdb_team_model_test.py +0 -0
  198. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/sportsdb/sportsdb_venue_model_test.py +0 -0
  199. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/sportsreference/__init__.py +0 -0
  200. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/sportsreference/sportsreference_game_model_test.py +0 -0
  201. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/sportsreference/sportsreference_league_model_test.py +0 -0
  202. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/sportsreference/sportsreference_player_model_test.py +0 -0
  203. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/sportsreference/sportsreference_team_model_test.py +0 -0
  204. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/sportsreference/sportsreference_venue_model_test.py +0 -0
  205. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/team_model_test.py +0 -0
  206. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/x/__init__.py +0 -0
  207. {sportsball-0.3.31 → sportsball-0.3.33}/tests/data/x/x_social_model_test.py +0 -0
  208. {sportsball-0.3.31 → sportsball-0.3.33}/tests/proxy_session_test.py +0 -0
  209. {sportsball-0.3.31 → sportsball-0.3.33}/tests/sportsball_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: sportsball
3
- Version: 0.3.31
3
+ Version: 0.3.33
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.31',
29
+ version='0.3.33',
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',
@@ -1,3 +1,3 @@
1
1
  """The main module for sportsball."""
2
2
 
3
- __VERSION__ = "0.3.31"
3
+ __VERSION__ = "0.3.33"
@@ -11,7 +11,9 @@ class AddressModel(BaseModel):
11
11
 
12
12
  city: str = Field(..., json_schema_extra={TYPE_KEY: FieldType.CATEGORICAL})
13
13
  state: str = Field(..., json_schema_extra={TYPE_KEY: FieldType.CATEGORICAL})
14
- zipcode: str = Field(..., json_schema_extra={TYPE_KEY: FieldType.CATEGORICAL})
14
+ zipcode: str | None = Field(
15
+ ..., json_schema_extra={TYPE_KEY: FieldType.CATEGORICAL}
16
+ )
15
17
  latitude: float | None
16
18
  longitude: float | None
17
19
  housenumber: str | None = Field(
@@ -7828,6 +7828,142 @@ _CACHED_GEOCODES: dict[str, Any] = {
7828
7828
  country="USA",
7829
7829
  ),
7830
7830
  "Island Federal Credit Union Arena, New York, NY, USA": STONY_BROOK_ARENA,
7831
+ "Subiaco Oval, Perth, Australia": DOMAIN_STADIUM,
7832
+ "University of Tasmania Stadium, Launceston, Australia": UTAS_STADIUM,
7833
+ "Mars Stadium, Ballarat, Australia": MARS_STADIUM,
7834
+ "Savannah, Georgia": SportsballGeocodeTuple(
7835
+ city="Savannah",
7836
+ state="GA",
7837
+ postal="",
7838
+ lat=32.081111,
7839
+ lng=-81.091111,
7840
+ housenumber="",
7841
+ country="USA",
7842
+ ),
7843
+ "Blundstone Arena, Hobart, Australia": BLUNDSTONE_ARENA,
7844
+ "Akron, Ohio": SportsballGeocodeTuple(
7845
+ city="Akron",
7846
+ state="OH",
7847
+ postal="",
7848
+ lat=41.080556,
7849
+ lng=-81.522222,
7850
+ housenumber="",
7851
+ country="USA",
7852
+ ),
7853
+ "Michelob Ultra Arena, Paradise, Nevada": SportsballGeocodeTuple(
7854
+ city="Paradise",
7855
+ state="NV",
7856
+ postal="",
7857
+ lat=36.090678,
7858
+ lng=-115.178981,
7859
+ housenumber="3950",
7860
+ country="USA",
7861
+ ),
7862
+ "Sioux Falls, South Dakota": SportsballGeocodeTuple(
7863
+ city="Sioux Falls",
7864
+ state="SD",
7865
+ postal="",
7866
+ lat=43.536389,
7867
+ lng=-96.731667,
7868
+ housenumber="",
7869
+ country="USA",
7870
+ ),
7871
+ "TIO Traeger Park, Alice Springs, Australia": TIO_STADIUM,
7872
+ "Springfield, Massachusetts": SportsballGeocodeTuple(
7873
+ city="Springfield",
7874
+ state="MA",
7875
+ postal="",
7876
+ lat=42.101389,
7877
+ lng=-72.590278,
7878
+ housenumber="",
7879
+ country="USA",
7880
+ ),
7881
+ "Elmont, New York": SportsballGeocodeTuple(
7882
+ city="Elmont",
7883
+ state="NY",
7884
+ postal="",
7885
+ lat=40.701667,
7886
+ lng=-73.7025,
7887
+ housenumber="",
7888
+ country="USA",
7889
+ ),
7890
+ "Manuka Oval, Canberra, Australia": MANUKA_OVAL,
7891
+ "Tulsa, Oklahoma": SportsballGeocodeTuple(
7892
+ city="Tulsa",
7893
+ state="OK",
7894
+ postal="",
7895
+ lat=36.131389,
7896
+ lng=-95.937222,
7897
+ housenumber="",
7898
+ country="USA",
7899
+ ),
7900
+ "Sunrise, Florida": SportsballGeocodeTuple(
7901
+ city="Sunrise",
7902
+ state="FL",
7903
+ postal="",
7904
+ lat=26.157222,
7905
+ lng=-80.286111,
7906
+ housenumber="",
7907
+ country="USA",
7908
+ ),
7909
+ "Paradise, Nevada": SportsballGeocodeTuple(
7910
+ city="Paradise",
7911
+ state="NV",
7912
+ postal="",
7913
+ lat=36.081944,
7914
+ lng=-115.124722,
7915
+ housenumber="",
7916
+ country="USA",
7917
+ ),
7918
+ "Niceville, Florida": SportsballGeocodeTuple(
7919
+ city="Niceville",
7920
+ state="FL",
7921
+ postal="",
7922
+ lat=30.516111,
7923
+ lng=-86.471667,
7924
+ housenumber="",
7925
+ country="USA",
7926
+ ),
7927
+ "Jiangwan Stadium, Shanghai, China": JIANGWAN_STADIUM,
7928
+ "Ondrej Nepela Arena, Bratislava, Slovakia": SportsballGeocodeTuple(
7929
+ city="Bratislava",
7930
+ state="",
7931
+ postal="",
7932
+ lat=48.16,
7933
+ lng=17.135833,
7934
+ housenumber="9",
7935
+ country="Slovakia",
7936
+ ),
7937
+ "Cazaly's Stadium, Cairns, Australia": CAZALYS_STADIUM,
7938
+ "San Juan Capistrano, California": SportsballGeocodeTuple(
7939
+ city="San Juan Capistrano",
7940
+ state="CA",
7941
+ postal="",
7942
+ lat=33.499444,
7943
+ lng=-117.661667,
7944
+ housenumber="",
7945
+ country="USA",
7946
+ ),
7947
+ "Giants Stadium, East Rutherford, NJ, USA": METLIFE_STADIUM,
7948
+ "TIO Stadium, Darwin, Australia": TIO_STADIUM,
7949
+ "Fort Myers, Florida": SportsballGeocodeTuple(
7950
+ city="Fort Myers",
7951
+ state="FL",
7952
+ postal="",
7953
+ lat=26.616667,
7954
+ lng=-81.833333,
7955
+ housenumber="",
7956
+ country="USA",
7957
+ ),
7958
+ "Thunderdome Stadium, Nonthaburi, Thailand": SportsballGeocodeTuple(
7959
+ city="Nonthaburi",
7960
+ state="",
7961
+ postal="",
7962
+ lat=13.917989,
7963
+ lng=100.547411,
7964
+ housenumber="",
7965
+ country="Thailand",
7966
+ ),
7831
7967
  }
7832
7968
 
7833
7969
 
@@ -3,9 +3,11 @@
3
3
  # pylint: disable=too-many-locals
4
4
  import base64
5
5
  import json
6
+ import logging
6
7
  import urllib.parse
7
8
  from typing import Any
8
9
 
10
+ import requests
9
11
  import requests_cache
10
12
  from bs4 import BeautifulSoup
11
13
  from cryptography.hazmat.backends import default_backend
@@ -73,8 +75,18 @@ def fetch_data(
73
75
  url,
74
76
  headers=headers,
75
77
  )
76
- response.raise_for_status()
77
- decoded_data = base64.b64decode(response.content).decode()
78
+
79
+ try:
80
+ response.raise_for_status()
81
+ except requests.exceptions.HTTPError as exc:
82
+ logging.error("HTTP error: %s for URL: %s", str(exc), referer_url)
83
+ raise exc
84
+
85
+ try:
86
+ decoded_data = base64.b64decode(response.content).decode()
87
+ except UnicodeDecodeError as exc:
88
+ logging.error("Error base64 decoding payload: %s", response.content)
89
+ raise exc
78
90
  encrypted, key = decoded_data.split(":")
79
91
  encrypted_bytes = base64.urlsafe_b64decode(encrypted)
80
92
  key_bytes = bytes.fromhex(key)
@@ -3,6 +3,7 @@
3
3
  # pylint: disable=too-many-locals,too-many-statements,line-too-long
4
4
  import datetime
5
5
  import json
6
+ import logging
6
7
  import urllib.parse
7
8
 
8
9
  import pytest_is_running
@@ -22,8 +23,13 @@ def _create_oddsportal_game_model(
22
23
  session: requests_cache.CachedSession,
23
24
  url: str,
24
25
  league: League,
25
- ) -> GameModel:
26
- response = session.get(url, headers={X_NO_WAYBACK: "1"})
26
+ ) -> GameModel | None:
27
+ response = session.get(
28
+ url,
29
+ headers={
30
+ X_NO_WAYBACK: "1",
31
+ },
32
+ )
27
33
  response.raise_for_status()
28
34
 
29
35
  soup = BeautifulSoup(response.text, "html.parser")
@@ -32,7 +38,8 @@ def _create_oddsportal_game_model(
32
38
  soup_x = BeautifulSoup(response.text, "xml")
33
39
  event_tag = soup_x.find("Event")
34
40
  if not isinstance(event_tag, Tag):
35
- raise ValueError(f"event_tag is not a tag for URL: {url}.")
41
+ logging.error("event_tag is not a tag for URL: %s.", url)
42
+ return None
36
43
  event = json.loads(str(event_tag[":data"]))
37
44
  else:
38
45
  event = json.loads(str(event_tag["data"]))
@@ -72,8 +79,8 @@ def _create_oddsportal_game_model(
72
79
  event_body["venueCountry"],
73
80
  )
74
81
 
75
- url = f"https://www.oddsportal.com/match-event/{version_id}-{sport_id}-{unique_id}-{default_bet_id}-{default_scope_id}-{xhash}.dat"
76
- parsed_data = fetch_data(url, session, url, soup)
82
+ dat_url = f"https://www.oddsportal.com/match-event/{version_id}-{sport_id}-{unique_id}-{default_bet_id}-{default_scope_id}-{xhash}.dat"
83
+ parsed_data = fetch_data(dat_url, session, url, soup)
77
84
 
78
85
  return GameModel(
79
86
  dt=dt,
@@ -121,7 +128,7 @@ def _cached_create_oddsportal_game_model(
121
128
  session: requests_cache.CachedSession,
122
129
  url: str,
123
130
  league: League,
124
- ) -> GameModel:
131
+ ) -> GameModel | None:
125
132
  return _create_oddsportal_game_model(session, url, league)
126
133
 
127
134
 
@@ -130,7 +137,7 @@ def create_oddsportal_game_model(
130
137
  url: str,
131
138
  league: League,
132
139
  is_next: bool,
133
- ) -> GameModel:
140
+ ) -> GameModel | None:
134
141
  """Create a OddsPortal game model."""
135
142
  if not pytest_is_running.is_running() and not is_next:
136
143
  return _cached_create_oddsportal_game_model(session, url, league)
@@ -31,6 +31,17 @@ USA = "usa"
31
31
  NCAA = "ncaa"
32
32
 
33
33
 
34
+ def _find_ids(text: str) -> tuple[str, str]:
35
+ sentinel = "var pageOutrightsVar = '"
36
+ sanitised_text = text[text.find(sentinel) + len(sentinel) :]
37
+ sanitised_text = sanitised_text[: sanitised_text.find("'")]
38
+ try:
39
+ page_outrights = json.loads(sanitised_text)
40
+ except json.decoder.JSONDecodeError as exc:
41
+ raise exc
42
+ return str(page_outrights["sid"]), page_outrights["id"]
43
+
44
+
34
45
  def _process_results_pages(
35
46
  url: str,
36
47
  session: requests_cache.CachedSession,
@@ -40,28 +51,29 @@ def _process_results_pages(
40
51
  response: requests.Response,
41
52
  ) -> Iterator[GameModel]:
42
53
  # Fetch first page
43
- sanitised_text = response.text[response.text.find("var pageOutrightsVar = '") :]
44
- sanitised_text = sanitised_text[: sanitised_text.find("'")]
45
- page_outrights = json.loads(sanitised_text)
46
- sports_id = page_outrights["sid"]
47
- oddsportal_id = page_outrights["id"]
54
+ sports_id, oddsportal_id = _find_ids(response.text)
48
55
 
49
56
  current_page = 1
50
57
  total_pages = None
51
58
  while (current_page == 1 and total_pages is None) or (
52
- current_page <= 0 if total_pages is None else total_pages
59
+ current_page <= (0 if total_pages is None else total_pages)
53
60
  ):
54
61
  dat_url = f"https://www.oddsportal.com/ajax-sport-country-tournament-archive_/{sports_id}/{oddsportal_id}/X134529032X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X512X32X0X0X0X0X0X0X131072X0X2048/1/-5/page/{current_page}//"
55
62
  parsed_data = fetch_data(dat_url, session, url, soup)
56
63
  d = parsed_data["d"]
57
- for row in d["rows"]:
64
+ if d.get("total") == 0:
65
+ return
66
+ for row in d.get("rows", []):
58
67
  game_model = create_oddsportal_game_model(
59
68
  session, urllib.parse.urljoin(url, row["url"]), league, False
60
69
  )
70
+ if game_model is None:
71
+ continue
61
72
  pbar.update(1)
62
73
  pbar.set_description(f"OddsPortal {game_model.dt}")
63
74
  yield game_model
64
- total_pages = d["pagination"]["pages"]
75
+ pagination = d["pagination"]
76
+ total_pages = pagination["pages"]
65
77
  current_page += 1
66
78
 
67
79
 
@@ -87,7 +99,7 @@ class OddsPortalLeagueModel(LeagueModel):
87
99
  def _find_next(self, pbar: tqdm.tqdm) -> Iterator[GameModel]:
88
100
  base_url = "https://www.oddsportal.com/" + self._path
89
101
  with self.session.cache_disabled():
90
- response = self.session.get(base_url)
102
+ response = self.session.get(base_url, headers={X_NO_WAYBACK: "1"})
91
103
  response.raise_for_status()
92
104
  data = extruct.extract(response.text, base_url=base_url)
93
105
  for jsonld in data["json-ld"]:
@@ -100,6 +112,8 @@ class OddsPortalLeagueModel(LeagueModel):
100
112
  self.league,
101
113
  True,
102
114
  )
115
+ if game_model is None:
116
+ continue
103
117
  pbar.update(1)
104
118
  pbar.set_description(
105
119
  f"OddsPortal {game_model.year} - {game_model.season_type} - {game_model.dt}"
@@ -119,13 +133,13 @@ class OddsPortalLeagueModel(LeagueModel):
119
133
  url = queued_urls.pop()
120
134
  if url in seen_urls:
121
135
  continue
122
- logging.debug("processing url: %s", url)
123
136
  seen_urls.add(url)
124
137
 
125
- response = self.session.get(url, headers={X_NO_WAYBACK: "1"})
138
+ with self.session.cache_disabled():
139
+ response = self.session.get(url, headers={X_NO_WAYBACK: "1"})
126
140
  response.raise_for_status()
127
141
 
128
- soup = BeautifulSoup(response.text, "xml")
142
+ soup = BeautifulSoup(response.text, "html.parser")
129
143
 
130
144
  # Find next URLs
131
145
  for option in soup.find_all("option"):
@@ -2,6 +2,7 @@
2
2
 
3
3
  # pylint: disable=too-many-arguments,duplicate-code,line-too-long,too-many-locals
4
4
  import datetime
5
+ import logging
5
6
  from typing import Any
6
7
 
7
8
  import pytest_is_running
@@ -27,29 +28,34 @@ def _create_oddsportal_team_model(
27
28
  team_idx: int,
28
29
  parsed_data: dict[str, Any],
29
30
  ) -> TeamModel:
30
- try:
31
- odds_data = parsed_data["d"]["oddsdata"]["back"][
32
- f"E-{default_bet_id}-{default_scope_id}-0-0-0"
33
- ]
34
- except KeyError:
35
- back = parsed_data["d"]["oddsdata"]["back"]
36
- odds_data = back[sorted(list(back.keys()))[0]]
37
- try:
38
- outcome_id = odds_data["outcomeId"][team_idx]
39
- except KeyError:
40
- outcome_id = odds_data["outcomeId"][str(team_idx)]
41
- history = odds_data["history"][outcome_id]
31
+ back = parsed_data["d"]["oddsdata"]["back"]
42
32
  odds_models = []
43
- for bookie_id, bookie_name in bookie_names.items():
44
- for odds, _, timestamp in history.get(bookie_id, []):
45
- odds_models.append(
46
- create_oddsportal_odds_model(
47
- odds,
48
- datetime.datetime.fromtimestamp(timestamp),
49
- bookie_name,
50
- bookie_id, # type: ignore
33
+
34
+ if not isinstance(back, list):
35
+ try:
36
+ odds_data = back[f"E-{default_bet_id}-{default_scope_id}-0-0-0"]
37
+ except KeyError:
38
+ back = parsed_data["d"]["oddsdata"]["back"]
39
+ odds_data = back[sorted(list(back.keys()))[0]]
40
+ except TypeError as exc:
41
+ logging.error("Failed to parse the following odds")
42
+ raise exc
43
+ try:
44
+ outcome_id = odds_data["outcomeId"][team_idx]
45
+ except KeyError:
46
+ outcome_id = odds_data["outcomeId"][str(team_idx)]
47
+ history = odds_data["history"][outcome_id]
48
+
49
+ for bookie_id, bookie_name in bookie_names.items():
50
+ for odds, _, timestamp in history.get(bookie_id, []):
51
+ odds_models.append(
52
+ create_oddsportal_odds_model(
53
+ odds,
54
+ datetime.datetime.fromtimestamp(timestamp),
55
+ bookie_name,
56
+ bookie_id, # type: ignore
57
+ )
51
58
  )
52
- )
53
59
 
54
60
  return TeamModel(
55
61
  identifier=team_name,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: sportsball
3
- Version: 0.3.31
3
+ Version: 0.3.33
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
@@ -191,6 +191,7 @@ tests/data/nfl/sportsdb/__init__.py
191
191
  tests/data/nfl/sportsdb/nfl_sportsdb_league_model_test.py
192
192
  tests/data/oddsportal/__init__.py
193
193
  tests/data/oddsportal/oddsportal_game_model_test.py
194
+ tests/data/oddsportal/oddsportal_league_model_test.py
194
195
  tests/data/sportsdb/__init__.py
195
196
  tests/data/sportsdb/sportsdb_game_model_test.py
196
197
  tests/data/sportsdb/sportsdb_league_model_test.py
@@ -0,0 +1,19 @@
1
+ """Tests for the oddsportal league model class."""
2
+ import os
3
+ import unittest
4
+
5
+ import requests_cache
6
+ from sportsball.data.oddsportal.oddsportal_league_model import _find_ids
7
+
8
+
9
+ class TestOddsPortalLeagueModel(unittest.TestCase):
10
+
11
+ def setUp(self):
12
+ self.session = requests_cache.CachedSession(backend="memory")
13
+ self.dir = os.path.dirname(__file__)
14
+
15
+ def test_current_html_ids(self):
16
+ with open(os.path.join(self.dir, "results.html"), "r") as handle:
17
+ sports_id, oddsportal_id = _find_ids(handle.read())
18
+ self.assertEqual(sports_id, "18")
19
+ self.assertEqual(oddsportal_id, "6y3HOkJ7")
File without changes
File without changes
File without changes
File without changes