sportsball 0.5.4__tar.gz → 0.5.5__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 (262) hide show
  1. {sportsball-0.5.4/sportsball.egg-info → sportsball-0.5.5}/PKG-INFO +1 -1
  2. {sportsball-0.5.4 → sportsball-0.5.5}/setup.py +1 -1
  3. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/__init__.py +1 -1
  4. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/coach_model.py +4 -2
  5. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/combined/combined_coach_model.py +20 -2
  6. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/combined/combined_game_model.py +25 -2
  7. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/combined/combined_league_model.py +14 -8
  8. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/combined/combined_player_model.py +21 -2
  9. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/combined/combined_team_model.py +24 -4
  10. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/field_type.py +1 -0
  11. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/google/google_address_model.py +69 -27
  12. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/hkjc/hkjc/hkjc_hkjc_game_model.py +20 -4
  13. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/player_model.py +24 -8
  14. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/team_model.py +10 -2
  15. {sportsball-0.5.4 → sportsball-0.5.5/sportsball.egg-info}/PKG-INFO +1 -1
  16. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/combined/combined_game_model_test.py +6 -0
  17. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/combined/combined_player_model_test.py +4 -2
  18. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/combined/combined_team_model_test.py +18 -0
  19. {sportsball-0.5.4 → sportsball-0.5.5}/LICENSE +0 -0
  20. {sportsball-0.5.4 → sportsball-0.5.5}/MANIFEST.in +0 -0
  21. {sportsball-0.5.4 → sportsball-0.5.5}/README.md +0 -0
  22. {sportsball-0.5.4 → sportsball-0.5.5}/requirements.txt +0 -0
  23. {sportsball-0.5.4 → sportsball-0.5.5}/setup.cfg +0 -0
  24. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/__main__.py +0 -0
  25. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/args.py +0 -0
  26. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/cache.py +0 -0
  27. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/__init__.py +0 -0
  28. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/address_model.py +0 -0
  29. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/__init__.py +0 -0
  30. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/afl/__init__.py +0 -0
  31. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/afl/afl_afl_bookie_model.py +0 -0
  32. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/afl/afl_afl_game_model.py +0 -0
  33. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/afl/afl_afl_league_model.py +0 -0
  34. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/afl/afl_afl_odds_model.py +0 -0
  35. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/afl/afl_afl_player_model.py +0 -0
  36. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/afl/afl_afl_team_model.py +0 -0
  37. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/afl/afl_afl_venue_model.py +0 -0
  38. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/afltables/__init__.py +0 -0
  39. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/afltables/afl_afltables_coach_model.py +0 -0
  40. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/afltables/afl_afltables_game_model.py +0 -0
  41. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/afltables/afl_afltables_league_model.py +0 -0
  42. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/afltables/afl_afltables_player_model.py +0 -0
  43. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/afltables/afl_afltables_team_model.py +0 -0
  44. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/afltables/afl_afltables_venue_model.py +0 -0
  45. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/aussportsbetting/__init__.py +0 -0
  46. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/aussportsbetting/afl_aussportsbetting_league_model.py +0 -0
  47. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/combined/__init__.py +0 -0
  48. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/combined/afl_combined_league_model.py +0 -0
  49. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/espn/__init__.py +0 -0
  50. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/espn/afl_espn_league_model.py +0 -0
  51. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/oddsportal/__init__.py +0 -0
  52. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/oddsportal/afl_oddsportal_league_model.py +0 -0
  53. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/afl/position.py +0 -0
  54. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/aussportsbetting/__init__.py +0 -0
  55. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/aussportsbetting/aussportsbetting_bookie_model.py +0 -0
  56. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/aussportsbetting/aussportsbetting_game_model.py +0 -0
  57. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/aussportsbetting/aussportsbetting_league_model.py +0 -0
  58. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/aussportsbetting/aussportsbetting_odds_model.py +0 -0
  59. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/aussportsbetting/aussportsbetting_team_model.py +0 -0
  60. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/aussportsbetting/aussportsbetting_venue_model.py +0 -0
  61. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/bet.py +0 -0
  62. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/bookie_model.py +0 -0
  63. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/combined/__init__.py +0 -0
  64. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/combined/combined_address_model.py +0 -0
  65. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/combined/combined_venue_model.py +0 -0
  66. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/combined/combined_weather_model.py +0 -0
  67. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/combined/null_check.py +0 -0
  68. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/dividend_model.py +0 -0
  69. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/espn/__init__.py +0 -0
  70. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/espn/espn_bookie_model.py +0 -0
  71. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/espn/espn_coach_model.py +0 -0
  72. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/espn/espn_game_model.py +0 -0
  73. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/espn/espn_league_model.py +0 -0
  74. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/espn/espn_odds_model.py +0 -0
  75. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/espn/espn_player_model.py +0 -0
  76. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/espn/espn_team_model.py +0 -0
  77. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/espn/espn_venue_model.py +0 -0
  78. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/game_model.py +0 -0
  79. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/google/__init__.py +0 -0
  80. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/google/google_news_model.py +0 -0
  81. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/hkjc/__init__.py +0 -0
  82. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/hkjc/hkjc/__init__.py +0 -0
  83. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/hkjc/hkjc/hkjc_hkjc_bookie_model.py +0 -0
  84. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/hkjc/hkjc/hkjc_hkjc_coach_model.py +0 -0
  85. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/hkjc/hkjc/hkjc_hkjc_dividend_model.py +0 -0
  86. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/hkjc/hkjc/hkjc_hkjc_league_model.py +0 -0
  87. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/hkjc/hkjc/hkjc_hkjc_odds_model.py +0 -0
  88. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/hkjc/hkjc/hkjc_hkjc_owner_model.py +0 -0
  89. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/hkjc/hkjc/hkjc_hkjc_player_model.py +0 -0
  90. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/hkjc/hkjc/hkjc_hkjc_team_model.py +0 -0
  91. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/hkjc/hkjc/hkjc_hkjc_venue_model.py +0 -0
  92. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/hkjc/position.py +0 -0
  93. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/league.py +0 -0
  94. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/league_model.py +0 -0
  95. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/model.py +0 -0
  96. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/__init__.py +0 -0
  97. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/combined/__init__.py +0 -0
  98. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/combined/nba_combined_league_model.py +0 -0
  99. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/espn/__init__.py +0 -0
  100. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/espn/nba_espn_league_model.py +0 -0
  101. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/nba/__init__.py +0 -0
  102. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/nba/nba_nba_game_model.py +0 -0
  103. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/nba/nba_nba_league_model.py +0 -0
  104. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/nba/nba_nba_team_model.py +0 -0
  105. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/nbacom/__init__.py +0 -0
  106. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/nbacom/nba_nbacom_game_model.py +0 -0
  107. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/nbacom/nba_nbacom_league_model.py +0 -0
  108. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/nbacom/nba_nbacom_player_model.py +0 -0
  109. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/nbacom/nba_nbacom_team_model.py +0 -0
  110. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/nbacom/nba_nbacom_venue_model.py +0 -0
  111. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/oddsportal/__init__.py +0 -0
  112. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/oddsportal/nba_oddsportal_league_model.py +0 -0
  113. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/position.py +0 -0
  114. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/sportsdb/__init__.py +0 -0
  115. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/sportsdb/nba_sportsdb_league_model.py +0 -0
  116. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/sportsreference/__init__.py +0 -0
  117. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nba/sportsreference/nba_sportsreference_league_model.py +0 -0
  118. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/ncaab/__init__.py +0 -0
  119. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/ncaab/combined/__init__.py +0 -0
  120. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/ncaab/combined/ncaab_combined_league_model.py +0 -0
  121. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/ncaab/espn/__init__.py +0 -0
  122. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/ncaab/espn/ncaab_espn_league_model.py +0 -0
  123. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/ncaab/oddsportal/__init__.py +0 -0
  124. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/ncaab/oddsportal/ncaab_oddsportal_league_model.py +0 -0
  125. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/ncaab/sportsreference/__init__.py +0 -0
  126. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/ncaab/sportsreference/ncaab_sportsreference_league_model.py +0 -0
  127. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/ncaaf/__init__.py +0 -0
  128. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/ncaaf/combined/__init__.py +0 -0
  129. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/ncaaf/combined/ncaaf_combined_league_model.py +0 -0
  130. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/ncaaf/espn/__init__.py +0 -0
  131. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/ncaaf/espn/ncaaf_espn_league_model.py +0 -0
  132. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/ncaaf/oddsportal/__init__.py +0 -0
  133. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/ncaaf/oddsportal/ncaaf_oddsportal_league_model.py +0 -0
  134. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/news_model.py +0 -0
  135. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nfl/__init__.py +0 -0
  136. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nfl/aussportsbetting/__init__.py +0 -0
  137. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nfl/aussportsbetting/nfl_aussportsbetting_league_model.py +0 -0
  138. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nfl/combined/__init__.py +0 -0
  139. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nfl/combined/nfl_combined_league_model.py +0 -0
  140. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nfl/espn/__init__.py +0 -0
  141. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nfl/espn/nfl_espn_league_model.py +0 -0
  142. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nfl/oddsportal/__init__.py +0 -0
  143. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nfl/oddsportal/nfl_oddsportal_league_model.py +0 -0
  144. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nfl/position.py +0 -0
  145. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nfl/sportsdb/__init__.py +0 -0
  146. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/nfl/sportsdb/nfl_sportsdb_league_model.py +0 -0
  147. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/odds_model.py +0 -0
  148. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/oddsportal/__init__.py +0 -0
  149. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/oddsportal/decrypt.py +0 -0
  150. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/oddsportal/oddsportal_bookie_model.py +0 -0
  151. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/oddsportal/oddsportal_game_model.py +0 -0
  152. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/oddsportal/oddsportal_league_model.py +0 -0
  153. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/oddsportal/oddsportal_odds_model.py +0 -0
  154. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/oddsportal/oddsportal_team_model.py +0 -0
  155. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/oddsportal/oddsportal_venue_model.py +0 -0
  156. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/owner_model.py +0 -0
  157. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/season_type.py +0 -0
  158. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/sex.py +0 -0
  159. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/social_model.py +0 -0
  160. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/species.py +0 -0
  161. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/sportsdb/__init__.py +0 -0
  162. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/sportsdb/sportsdb_game_model.py +0 -0
  163. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/sportsdb/sportsdb_league_model.py +0 -0
  164. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/sportsdb/sportsdb_team_model.py +0 -0
  165. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/sportsdb/sportsdb_venue_model.py +0 -0
  166. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/sportsreference/__init__.py +0 -0
  167. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/sportsreference/sportsreference_coach_model.py +0 -0
  168. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/sportsreference/sportsreference_game_model.py +0 -0
  169. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/sportsreference/sportsreference_league_model.py +0 -0
  170. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/sportsreference/sportsreference_player_model.py +0 -0
  171. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/sportsreference/sportsreference_team_model.py +0 -0
  172. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/sportsreference/sportsreference_venue_model.py +0 -0
  173. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/venue_model.py +0 -0
  174. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/weather/__init__.py +0 -0
  175. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/weather/gribstream/__init__.py +0 -0
  176. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/weather/gribstream/gribstream_weather_model.py +0 -0
  177. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/weather/multi_weather_model.py +0 -0
  178. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/weather/openmeteo/__init__.py +0 -0
  179. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/weather/openmeteo/openmeteo_weather_model.py +0 -0
  180. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/weather_model.py +0 -0
  181. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/wikipedia/__init__.py +0 -0
  182. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/wikipedia/wikipedia_venue_model.py +0 -0
  183. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/x/__init__.py +0 -0
  184. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/data/x/x_social_model.py +0 -0
  185. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/logger.py +0 -0
  186. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/loglevel.py +0 -0
  187. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/playwright.py +0 -0
  188. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/proxy_session.py +0 -0
  189. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/session.py +0 -0
  190. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/sportsball.py +0 -0
  191. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/vendor/__init__.py +0 -0
  192. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball/vendor/pygooglenews/__init__.py +0 -0
  193. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball.egg-info/SOURCES.txt +0 -0
  194. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball.egg-info/dependency_links.txt +0 -0
  195. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball.egg-info/entry_points.txt +0 -0
  196. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball.egg-info/not-zip-safe +0 -0
  197. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball.egg-info/requires.txt +0 -0
  198. {sportsball-0.5.4 → sportsball-0.5.5}/sportsball.egg-info/top_level.txt +0 -0
  199. {sportsball-0.5.4 → sportsball-0.5.5}/tests/__init__.py +0 -0
  200. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/__init__.py +0 -0
  201. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/afl/__init__.py +0 -0
  202. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/afl/afl/__init__.py +0 -0
  203. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/afl/afl/afl_afl_game_model_test.py +0 -0
  204. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/afl/afl/afl_afl_league_model_test.py +0 -0
  205. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/afl/afltables/__init__.py +0 -0
  206. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/afl/afltables/afl_afltables_coach_model_test.py +0 -0
  207. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/afl/afltables/afl_afltables_game_model_test.py +0 -0
  208. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/afl/afltables/afl_afltables_league_model_test.py +0 -0
  209. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/afl/afltables/afl_afltables_player_model_test.py +0 -0
  210. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/aussportsbetting/__init__.py +0 -0
  211. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/aussportsbetting/aussportsbetting_game_model_test.py +0 -0
  212. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/combined/__init__.py +0 -0
  213. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/combined/combined_venue_model_test.py +0 -0
  214. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/espn/__init__.py +0 -0
  215. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/espn/espn_game_model_test.py +0 -0
  216. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/espn/espn_player_model_test.py +0 -0
  217. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/game_model_test.py +0 -0
  218. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/google/__init__.py +0 -0
  219. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/google/google_address_model_test.py +0 -0
  220. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/google/google_news_model_test.py +0 -0
  221. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/hkjc/__init__.py +0 -0
  222. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/hkjc/hkjc/__init__.py +0 -0
  223. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/hkjc/hkjc/hkjc_hkjc_game_model_test.py +0 -0
  224. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/hkjc/hkjc/hkjc_hkjc_player_model_test.py +0 -0
  225. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/nba/__init__.py +0 -0
  226. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/nba/nba/__init__.py +0 -0
  227. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/nba/nba/nba_nba_game_model_test.py +0 -0
  228. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/nba/nba/nba_nba_league_model_test.py +0 -0
  229. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/nba/nba/nba_nba_team_model_test.py +0 -0
  230. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/nba/sportsdb/__init__.py +0 -0
  231. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/nba/sportsdb/nba_sportsdb_league_model_test.py +0 -0
  232. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/nba/sportsreference/__init__.py +0 -0
  233. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/nba/sportsreference/nba_sportsreference_league_model_test.py +0 -0
  234. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/ncaab/__init__.py +0 -0
  235. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/ncaab/sportsreference/__init__.py +0 -0
  236. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/ncaab/sportsreference/ncaab_sportsreference_league_model_test.py +0 -0
  237. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/nfl/__init__.py +0 -0
  238. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/nfl/sportsdb/__init__.py +0 -0
  239. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/nfl/sportsdb/nfl_sportsdb_league_model_test.py +0 -0
  240. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/oddsportal/__init__.py +0 -0
  241. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/oddsportal/decrypt_test.py +0 -0
  242. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/oddsportal/oddsportal_game_model_test.py +0 -0
  243. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/oddsportal/oddsportal_league_model_test.py +0 -0
  244. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/player_model_test.py +0 -0
  245. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/social_model_test.py +0 -0
  246. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/sportsdb/__init__.py +0 -0
  247. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/sportsdb/sportsdb_game_model_test.py +0 -0
  248. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/sportsdb/sportsdb_league_model_test.py +0 -0
  249. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/sportsdb/sportsdb_team_model_test.py +0 -0
  250. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/sportsdb/sportsdb_venue_model_test.py +0 -0
  251. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/sportsreference/__init__.py +0 -0
  252. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/sportsreference/sportsreference_coach_model_test.py +0 -0
  253. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/sportsreference/sportsreference_game_model_test.py +0 -0
  254. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/sportsreference/sportsreference_league_model_test.py +0 -0
  255. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/sportsreference/sportsreference_player_model_test.py +0 -0
  256. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/sportsreference/sportsreference_team_model_test.py +0 -0
  257. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/sportsreference/sportsreference_venue_model_test.py +0 -0
  258. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/team_model_test.py +0 -0
  259. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/x/__init__.py +0 -0
  260. {sportsball-0.5.4 → sportsball-0.5.5}/tests/data/x/x_social_model_test.py +0 -0
  261. {sportsball-0.5.4 → sportsball-0.5.5}/tests/proxy_session_test.py +0 -0
  262. {sportsball-0.5.4 → sportsball-0.5.5}/tests/sportsball_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: sportsball
3
- Version: 0.5.4
3
+ Version: 0.5.5
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.5.4',
29
+ version='0.5.5',
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.5.4"
7
+ __VERSION__ = "0.5.5"
@@ -5,7 +5,7 @@ from typing import Literal
5
5
 
6
6
  from pydantic import BaseModel, Field
7
7
 
8
- from .field_type import TYPE_KEY, FieldType
8
+ from .field_type import FFILL_KEY, TYPE_KEY, FieldType
9
9
 
10
10
  COACH_IDENTIFIER_COLUMN: Literal["identifier"] = "identifier"
11
11
  COACH_NAME_COLUMN: Literal["name"] = "name"
@@ -22,5 +22,7 @@ class CoachModel(BaseModel):
22
22
  alias=COACH_IDENTIFIER_COLUMN,
23
23
  )
24
24
  name: str = Field(..., alias=COACH_NAME_COLUMN)
25
- birth_date: datetime.date | None = Field(..., alias=COACH_BIRTH_DATE_COLUMN)
25
+ birth_date: datetime.date | None = Field(
26
+ ..., json_schema_extra={FFILL_KEY: True}, alias=COACH_BIRTH_DATE_COLUMN
27
+ )
26
28
  age: int | None = Field(..., alias=COACH_AGE_COLUMN)
@@ -1,11 +1,16 @@
1
1
  """Combined coach model."""
2
2
 
3
+ from typing import Any
4
+
3
5
  from ..coach_model import CoachModel
6
+ from ..field_type import FFILL_KEY
4
7
  from .null_check import is_null
5
8
 
6
9
 
7
10
  def create_combined_coach_model(
8
- coach_models: list[CoachModel], identifier: str
11
+ coach_models: list[CoachModel],
12
+ identifier: str,
13
+ coach_ffill: dict[str, dict[str, Any]],
9
14
  ) -> CoachModel:
10
15
  """Create a coach model by combining many coach models."""
11
16
  name = None
@@ -23,9 +28,22 @@ def create_combined_coach_model(
23
28
  age = coach_model_age
24
29
  if name is None:
25
30
  raise ValueError("name is null.")
26
- return CoachModel(
31
+ coach_model = CoachModel(
27
32
  identifier=identifier,
28
33
  name=name,
29
34
  birth_date=birth_date,
30
35
  age=age,
31
36
  )
37
+
38
+ coach_instance_ffill = coach_ffill.get(identifier, {})
39
+ for field_name, field in coach_model.model_fields.items():
40
+ extra = field.json_schema_extra or {}
41
+ if extra.get(FFILL_KEY, False): # type: ignore
42
+ current_value = getattr(coach_model, field_name)
43
+ if current_value is None:
44
+ setattr(coach_model, field_name, coach_instance_ffill.get(field_name))
45
+ else:
46
+ coach_instance_ffill[field_name] = current_value
47
+ coach_ffill[identifier] = coach_instance_ffill
48
+
49
+ return coach_model
@@ -2,6 +2,7 @@
2
2
 
3
3
  # pylint: disable=too-many-locals,line-too-long,too-many-arguments,too-many-branches,too-many-statements
4
4
  import logging
5
+ from typing import Any
5
6
 
6
7
  import requests
7
8
 
@@ -38,6 +39,9 @@ def _team_models(
38
39
  player_identity_map: dict[str, str],
39
40
  names: dict[str, str],
40
41
  coach_names: dict[str, str],
42
+ player_ffill: dict[str, dict[str, Any]],
43
+ team_ffill: dict[str, dict[str, Any]],
44
+ coach_ffill: dict[str, dict[str, Any]],
41
45
  ) -> list[TeamModel]:
42
46
  team_models: dict[str, list[TeamModel]] = {}
43
47
  for game_model in game_models:
@@ -54,7 +58,16 @@ def _team_models(
54
58
  team_model
55
59
  ]
56
60
  return [
57
- create_combined_team_model(v, k, player_identity_map, names, coach_names) # pyright: ignore
61
+ create_combined_team_model(
62
+ v,
63
+ k,
64
+ player_identity_map,
65
+ names,
66
+ coach_names,
67
+ player_ffill,
68
+ team_ffill,
69
+ coach_ffill,
70
+ ) # pyright: ignore
58
71
  for k, v in team_models.items()
59
72
  ]
60
73
 
@@ -68,11 +81,21 @@ def create_combined_game_model(
68
81
  names: dict[str, str],
69
82
  coach_names: dict[str, str],
70
83
  last_game_number: int | None,
84
+ player_ffill: dict[str, dict[str, Any]],
85
+ team_ffill: dict[str, dict[str, Any]],
86
+ coach_ffill: dict[str, dict[str, Any]],
71
87
  ) -> GameModel:
72
88
  """Create a game model by combining many game models."""
73
89
  venue_models, full_venue_identity = _venue_models(game_models, venue_identity_map)
74
90
  full_team_models = _team_models(
75
- game_models, team_identity_map, player_identity_map, names, coach_names
91
+ game_models,
92
+ team_identity_map,
93
+ player_identity_map,
94
+ names,
95
+ coach_names,
96
+ player_ffill,
97
+ team_ffill,
98
+ coach_ffill,
76
99
  )
77
100
  attendance = None
78
101
  end_dt = None
@@ -91,17 +91,23 @@ class CombinedLeagueModel(LeagueModel):
91
91
  games[key] = games.get(key, []) + [game_model]
92
92
  names: dict[str, str] = {}
93
93
  coach_names: dict[str, str] = {}
94
+ player_ffill: dict[str, dict[str, Any]] = {}
95
+ team_ffill: dict[str, dict[str, Any]] = {}
96
+ coach_ffill: dict[str, dict[str, Any]] = {}
94
97
  last_game_number = None
95
98
  for game_models in games.values():
96
99
  game_model = create_combined_game_model( # type: ignore
97
- game_models,
98
- self.venue_identity_map(),
99
- team_identity_map,
100
- self.player_identity_map(),
101
- self.session,
102
- names,
103
- coach_names,
104
- last_game_number,
100
+ game_models=game_models,
101
+ venue_identity_map=self.venue_identity_map(),
102
+ team_identity_map=team_identity_map,
103
+ player_identity_map=self.player_identity_map(),
104
+ session=self.session,
105
+ names=names,
106
+ coach_names=coach_names,
107
+ last_game_number=last_game_number,
108
+ player_ffill=player_ffill,
109
+ team_ffill=team_ffill,
110
+ coach_ffill=coach_ffill,
105
111
  )
106
112
  last_game_number = game_model.game_number
107
113
  yield game_model
@@ -1,12 +1,17 @@
1
1
  """Combined player model."""
2
2
 
3
3
  # pylint: disable=too-many-locals,too-many-branches,too-many-statements,duplicate-code
4
+ from typing import Any
5
+
6
+ from ..field_type import FFILL_KEY
4
7
  from ..player_model import PlayerModel
5
8
  from .null_check import is_null
6
9
 
7
10
 
8
11
  def create_combined_player_model(
9
- player_models: list[PlayerModel], identifier: str
12
+ player_models: list[PlayerModel],
13
+ identifier: str,
14
+ player_ffill: dict[str, dict[str, Any]],
10
15
  ) -> PlayerModel:
11
16
  """Create a player model by combining many player models."""
12
17
  jersey = None
@@ -234,7 +239,8 @@ def create_combined_player_model(
234
239
  raise ValueError("name is null")
235
240
  if species is None:
236
241
  raise ValueError("species is null")
237
- return PlayerModel(
242
+
243
+ player_model = PlayerModel(
238
244
  identifier=identifier,
239
245
  jersey=jersey,
240
246
  kicks=kicks,
@@ -291,3 +297,16 @@ def create_combined_player_model(
291
297
  game_score=game_score,
292
298
  point_differential=point_differential,
293
299
  )
300
+
301
+ player_instance_ffill = player_ffill.get(identifier, {})
302
+ for field_name, field in player_model.model_fields.items():
303
+ extra = field.json_schema_extra or {}
304
+ if extra.get(FFILL_KEY, False): # type: ignore
305
+ current_value = getattr(player_model, field_name)
306
+ if current_value is None:
307
+ setattr(player_model, field_name, player_instance_ffill.get(field_name))
308
+ else:
309
+ player_instance_ffill[field_name] = current_value
310
+ player_ffill[identifier] = player_instance_ffill
311
+
312
+ return player_model
@@ -1,10 +1,12 @@
1
1
  """Combined team model."""
2
2
 
3
- # pylint: disable=too-many-locals,too-many-branches,too-many-statements
3
+ # pylint: disable=too-many-locals,too-many-branches,too-many-statements,too-many-arguments
4
4
  import re
5
5
  import unicodedata
6
+ from typing import Any
6
7
 
7
8
  from ..coach_model import CoachModel
9
+ from ..field_type import FFILL_KEY
8
10
  from ..news_model import NewsModel
9
11
  from ..odds_model import OddsModel
10
12
  from ..player_model import PlayerModel
@@ -30,6 +32,9 @@ def create_combined_team_model(
30
32
  player_identity_map: dict[str, str],
31
33
  names: dict[str, str],
32
34
  coach_names: dict[str, str],
35
+ player_ffill: dict[str, dict[str, Any]],
36
+ team_ffill: dict[str, dict[str, Any]],
37
+ coach_ffill: dict[str, dict[str, Any]],
33
38
  ) -> TeamModel:
34
39
  """Create a team model by combining many team models."""
35
40
  location = None
@@ -99,12 +104,12 @@ def create_combined_team_model(
99
104
  if not is_null(team_model_end_dt):
100
105
  end_dt = team_model_end_dt
101
106
 
102
- return TeamModel(
107
+ team_model = TeamModel(
103
108
  identifier=identifier,
104
109
  name=team_models[0].name,
105
110
  location=location,
106
111
  players=[ # pyright: ignore
107
- create_combined_player_model(v, k) for k, v in players.items()
112
+ create_combined_player_model(v, k, player_ffill) for k, v in players.items()
108
113
  ],
109
114
  odds=[x[0] for x in odds.values()],
110
115
  points=points,
@@ -112,7 +117,22 @@ def create_combined_team_model(
112
117
  news=sorted(news.values(), key=lambda x: x.published),
113
118
  social=sorted(social.values(), key=lambda x: x.published),
114
119
  field_goals=field_goals,
115
- coaches=[create_combined_coach_model(v, k) for k, v in coaches.items()],
120
+ coaches=[
121
+ create_combined_coach_model(v, k, coach_ffill) for k, v in coaches.items()
122
+ ],
116
123
  lbw=lbw,
117
124
  end_dt=end_dt,
118
125
  )
126
+
127
+ team_instance_ffill = team_ffill.get(identifier, {})
128
+ for field_name, field in team_model.model_fields.items():
129
+ extra = field.json_schema_extra or {}
130
+ if extra.get(FFILL_KEY, False): # type: ignore
131
+ current_value = getattr(team_model, field_name)
132
+ if current_value is None:
133
+ setattr(team_model, field_name, team_instance_ffill.get(field_name))
134
+ else:
135
+ team_instance_ffill[field_name] = current_value
136
+ team_ffill[identifier] = team_instance_ffill
137
+
138
+ return team_model
@@ -3,6 +3,7 @@
3
3
  from enum import StrEnum
4
4
 
5
5
  TYPE_KEY = "type"
6
+ FFILL_KEY = "ffill"
6
7
 
7
8
 
8
9
  class FieldType(StrEnum):
@@ -3232,6 +3232,33 @@ MADISON = SportsballGeocodeTuple(
3232
3232
  housenumber="",
3233
3233
  country="USA",
3234
3234
  )
3235
+ SAN_JOSE = SportsballGeocodeTuple(
3236
+ city="San Jose",
3237
+ state="CA",
3238
+ postal="",
3239
+ lat=37.336111,
3240
+ lng=-121.890556,
3241
+ housenumber="",
3242
+ country="USA",
3243
+ )
3244
+ MIAMI_ARENA = SportsballGeocodeTuple(
3245
+ city="Miami",
3246
+ state="FL",
3247
+ postal="",
3248
+ lat=25.781111,
3249
+ lng=-80.194722,
3250
+ housenumber="721",
3251
+ country="USA",
3252
+ )
3253
+ SILVIO_O_CONTE_FORUM = SportsballGeocodeTuple(
3254
+ city="Chestnut Hill",
3255
+ state="MA",
3256
+ postal="",
3257
+ lat=42.335,
3258
+ lng=-71.1675,
3259
+ housenumber="",
3260
+ country="USA",
3261
+ )
3235
3262
  _CACHED_GEOCODES: dict[str, Any] = {
3236
3263
  "S.C.G. - Australia": SCG,
3237
3264
  "Victoria Park - Australia": SportsballGeocodeTuple(
@@ -6788,15 +6815,7 @@ _CACHED_GEOCODES: dict[str, Any] = {
6788
6815
  housenumber="2168",
6789
6816
  country="USA",
6790
6817
  ),
6791
- "Silvio O. Conte Forum, Chestnut Hill, Massachusetts": SportsballGeocodeTuple(
6792
- city="Chestnut Hill",
6793
- state="MA",
6794
- postal="",
6795
- lat=42.335,
6796
- lng=-71.1675,
6797
- housenumber="",
6798
- country="USA",
6799
- ),
6818
+ "Silvio O. Conte Forum, Chestnut Hill, Massachusetts": SILVIO_O_CONTE_FORUM,
6800
6819
  "Millett Hall, Oxford, Ohio": SportsballGeocodeTuple(
6801
6820
  city="Oxford",
6802
6821
  state="OH",
@@ -7987,15 +8006,7 @@ _CACHED_GEOCODES: dict[str, Any] = {
7987
8006
  "Charlotte Coliseum": CHARLOTTE_COLISEUM,
7988
8007
  "Toyota Center, Houston, Texas": TOYOTA_CENTRE,
7989
8008
  "American Airlines Center, Dallas, Texas": AMERICAN_AIRLINES_ARENA,
7990
- "Miami Arena": SportsballGeocodeTuple(
7991
- city="Miami",
7992
- state="FL",
7993
- postal="",
7994
- lat=25.781111,
7995
- lng=-80.194722,
7996
- housenumber="721",
7997
- country="USA",
7998
- ),
8009
+ "Miami Arena": MIAMI_ARENA,
7999
8010
  "Al McGuire Center, Milwaukee, Wisconsin": SportsballGeocodeTuple(
8000
8011
  city="Milwaukee",
8001
8012
  state="WI",
@@ -10350,15 +10361,7 @@ _CACHED_GEOCODES: dict[str, Any] = {
10350
10361
  housenumber="",
10351
10362
  country="USA",
10352
10363
  ),
10353
- "San Jose, California": SportsballGeocodeTuple(
10354
- city="San Jose",
10355
- state="CA",
10356
- postal="",
10357
- lat=37.336111,
10358
- lng=-121.890556,
10359
- housenumber="",
10360
- country="USA",
10361
- ),
10364
+ "San Jose, California": SAN_JOSE,
10362
10365
  "Columbia, South Carolina": SportsballGeocodeTuple(
10363
10366
  city="Columbia",
10364
10367
  state="SC",
@@ -15693,6 +15696,45 @@ _CACHED_GEOCODES: dict[str, Any] = {
15693
15696
  housenumber="",
15694
15697
  country="USA",
15695
15698
  ),
15699
+ "Danville, Virginia, United States": SportsballGeocodeTuple(
15700
+ city="Danville",
15701
+ state="VA",
15702
+ postal="",
15703
+ lat=36.587222,
15704
+ lng=-79.404444,
15705
+ housenumber="",
15706
+ country="USA",
15707
+ ),
15708
+ "Antioch, CA, USA": SportsballGeocodeTuple(
15709
+ city="Antioch",
15710
+ state="CA",
15711
+ postal="",
15712
+ lat=38.005,
15713
+ lng=-121.805833,
15714
+ housenumber="",
15715
+ country="USA",
15716
+ ),
15717
+ "San Jose, CA, USA": SAN_JOSE,
15718
+ "Miami Arena, Miami, Florida": MIAMI_ARENA,
15719
+ "Silvio O. Conte Forum, Boston, Massachusetts": SILVIO_O_CONTE_FORUM,
15720
+ "IND": SportsballGeocodeTuple(
15721
+ city="",
15722
+ state="",
15723
+ postal="",
15724
+ lat=21.0,
15725
+ lng=78.0,
15726
+ housenumber="",
15727
+ country="India",
15728
+ ),
15729
+ "Tokyo Dome, Tokyo, Japan": SportsballGeocodeTuple(
15730
+ city="Tokyo",
15731
+ state="",
15732
+ postal="",
15733
+ lat=35.705556,
15734
+ lng=139.751944,
15735
+ housenumber="3",
15736
+ country="Japan",
15737
+ ),
15696
15738
  }
15697
15739
 
15698
15740
 
@@ -52,7 +52,11 @@ def _create_hkjc_hkjc_game_model(
52
52
 
53
53
  o = urlparse(url)
54
54
  query = urllib.parse.parse_qs(o.query)
55
- dt = parse(query[RACE_DATE_QUERY_KEY][0])
55
+ try:
56
+ dt = parse(query[RACE_DATE_QUERY_KEY][0])
57
+ except KeyError:
58
+ logging.error(url)
59
+ return None
56
60
  game_number = int(query[RACE_NUMBER_QUERY_KEY][0])
57
61
  venue_code = query[RACE_COURSE_QUERY_KEY][0]
58
62
 
@@ -69,7 +73,7 @@ def _create_hkjc_hkjc_game_model(
69
73
  if count == 1:
70
74
  race_track = ""
71
75
  try:
72
- race_track = df.iat[2, 2].split("-")[0].strip()
76
+ race_track = str(df.iat[2, 2]).split("-", maxsplit=1)[0].strip()
73
77
  except IndexError:
74
78
  logging.error(url)
75
79
  raise
@@ -86,7 +90,7 @@ def _create_hkjc_hkjc_game_model(
86
90
  for _, row in df.iterrows():
87
91
  horse_name = None
88
92
  try:
89
- horse_name = row["Horse"].split("(")[0].strip()
93
+ horse_name = "(".join(row["Horse"].split("(")[:-1]).strip()
90
94
  except KeyError:
91
95
  logging.error(url)
92
96
  continue
@@ -141,6 +145,8 @@ def _create_hkjc_hkjc_game_model(
141
145
  lbw = 2.4 * 0.07
142
146
  elif lbw_str == "+SH":
143
147
  lbw = 2.4 * 0.2 * 0.5
148
+ elif lbw_str in {"HD+", "+HD"}:
149
+ lbw = 2.4 * 0.2 * 1.5
144
150
  elif lbw_str and lbw_str != "-" and lbw_str != "---":
145
151
  if lbw is not None:
146
152
  if "-" in lbw_str:
@@ -190,6 +196,8 @@ def _create_hkjc_hkjc_game_model(
190
196
  if place is None:
191
197
  continue
192
198
  if horse_url is None:
199
+ logging.error(url)
200
+ logging.error(row)
193
201
  raise ValueError("horse_url is null")
194
202
 
195
203
  team_model = create_hkjc_hkjc_team_model(
@@ -221,7 +229,15 @@ def _create_hkjc_hkjc_game_model(
221
229
  continue
222
230
  if dividend_str == "detail":
223
231
  continue
224
- dividend_str = dividend_str.split("/", maxsplit=1)[0].replace(",", "")
232
+ dividend_str = (
233
+ dividend_str.split("/", maxsplit=1)[0]
234
+ .replace(",", "")
235
+ .replace("$", "")
236
+ .replace("(", "")
237
+ .replace(")", "")
238
+ )
239
+ if dividend_str == "win":
240
+ continue
225
241
  dividend = float(dividend_str)
226
242
 
227
243
  combination = None
@@ -9,7 +9,7 @@ import gender_guesser.detector as gender # type: ignore
9
9
  from pydantic import BaseModel, Field
10
10
 
11
11
  from .address_model import AddressModel
12
- from .field_type import TYPE_KEY, FieldType
12
+ from .field_type import FFILL_KEY, TYPE_KEY, FieldType
13
13
  from .owner_model import OwnerModel
14
14
  from .sex import Sex
15
15
 
@@ -113,6 +113,8 @@ def _calculate_field_goals_percentage(data: dict[str, Any]) -> float | None:
113
113
  field_goals_attempted = data.get(FIELD_GOALS_ATTEMPTED_COLUMN)
114
114
  if field_goals_attempted is None:
115
115
  return None
116
+ if field_goals_attempted == 0:
117
+ return 0.0
116
118
  return float(field_goals) / float(field_goals_attempted) # type: ignore
117
119
 
118
120
 
@@ -125,6 +127,8 @@ def _calculate_three_point_field_goals_percentage(data: dict[str, Any]) -> float
125
127
  )
126
128
  if three_point_field_goals_attempted is None:
127
129
  return None
130
+ if three_point_field_goals_attempted == 0:
131
+ return 0.0
128
132
  return float(three_point_field_goals) / float(three_point_field_goals_attempted) # type: ignore
129
133
 
130
134
 
@@ -135,6 +139,8 @@ def _calculate_free_throws_percentage(data: dict[str, Any]) -> float | None:
135
139
  free_throws_attempted = data.get(PLAYER_FREE_THROWS_ATTEMPTED_COLUMN)
136
140
  if free_throws_attempted is None:
137
141
  return None
142
+ if free_throws_attempted == 0:
143
+ return 0.0
138
144
  return float(free_throws) / float(free_throws_attempted) # type: ignore
139
145
 
140
146
 
@@ -308,17 +314,21 @@ class PlayerModel(BaseModel):
308
314
  json_schema_extra={TYPE_KEY: FieldType.LOOKAHEAD},
309
315
  alias=PLAYER_PERCENTAGE_PLAYED_COLUMN,
310
316
  )
311
- birth_date: datetime.date | None = Field(..., alias=PLAYER_BIRTH_DATE_COLUMN)
317
+ birth_date: datetime.date | None = Field(
318
+ ..., json_schema_extra={FFILL_KEY: True}, alias=PLAYER_BIRTH_DATE_COLUMN
319
+ )
312
320
  species: str = Field(
313
321
  ...,
314
- json_schema_extra={TYPE_KEY: FieldType.CATEGORICAL},
322
+ json_schema_extra={TYPE_KEY: FieldType.CATEGORICAL, FFILL_KEY: True},
315
323
  alias=PLAYER_SPECIES_COLUMN,
316
324
  )
317
325
  handicap_weight: float | None = Field(..., alias=PLAYER_HANDICAP_WEIGHT_COLUMN)
318
- father: PlayerModel | None = Field(..., alias=PLAYER_FATHER_COLUMN)
326
+ father: PlayerModel | None = Field(
327
+ ..., json_schema_extra={FFILL_KEY: True}, alias=PLAYER_FATHER_COLUMN
328
+ )
319
329
  sex: str | None = Field(
320
330
  default_factory=_guess_sex,
321
- json_schema_extra={TYPE_KEY: FieldType.CATEGORICAL},
331
+ json_schema_extra={TYPE_KEY: FieldType.CATEGORICAL, FFILL_KEY: True},
322
332
  alias=PLAYER_SEX_COLUMN,
323
333
  )
324
334
  age: int | None = Field(..., alias=PLAYER_AGE_COLUMN)
@@ -327,9 +337,15 @@ class PlayerModel(BaseModel):
327
337
  json_schema_extra={TYPE_KEY: FieldType.CATEGORICAL},
328
338
  alias=PLAYER_STARTING_POSITION_COLUMN,
329
339
  )
330
- weight: float | None = Field(..., alias=PLAYER_WEIGHT_COLUMN)
331
- birth_address: AddressModel | None = Field(..., alias=PLAYER_BIRTH_ADDRESS_COLUMN)
332
- owner: OwnerModel | None = Field(..., alias=PLAYER_OWNER_COLUMN)
340
+ weight: float | None = Field(
341
+ ..., json_schema_extra={FFILL_KEY: True}, alias=PLAYER_WEIGHT_COLUMN
342
+ )
343
+ birth_address: AddressModel | None = Field(
344
+ ..., json_schema_extra={FFILL_KEY: True}, alias=PLAYER_BIRTH_ADDRESS_COLUMN
345
+ )
346
+ owner: OwnerModel | None = Field(
347
+ ..., json_schema_extra={FFILL_KEY: True}, alias=PLAYER_OWNER_COLUMN
348
+ )
333
349
  seconds_played: int | None = Field(
334
350
  ...,
335
351
  json_schema_extra={TYPE_KEY: FieldType.LOOKAHEAD},
@@ -7,7 +7,7 @@ from typing import Any, Literal
7
7
  from pydantic import BaseModel, Field
8
8
 
9
9
  from .coach_model import CoachModel
10
- from .field_type import TYPE_KEY, FieldType
10
+ from .field_type import FFILL_KEY, TYPE_KEY, FieldType
11
11
  from .news_model import NewsModel
12
12
  from .odds_model import OddsModel
13
13
  from .player_model import PlayerModel
@@ -464,6 +464,8 @@ def _calcualte_field_goals_percentage(data: dict[str, Any]) -> float | None:
464
464
  field_goals_attempted = data.get(FIELD_GOALS_ATTEMPTED_COLUMN)
465
465
  if field_goals_attempted is None:
466
466
  return None
467
+ if field_goals_attempted == 0:
468
+ return 0.0
467
469
  return float(field_goals) / float(field_goals_attempted) # type: ignore
468
470
 
469
471
 
@@ -506,6 +508,8 @@ def _calculate_three_point_field_goals_percentage(data: dict[str, Any]) -> float
506
508
  )
507
509
  if three_point_field_goals_attempted is None:
508
510
  return None
511
+ if three_point_field_goals_attempted == 0:
512
+ return 0.0
509
513
  return float(three_point_field_goals) / float(three_point_field_goals_attempted) # type: ignore
510
514
 
511
515
 
@@ -544,6 +548,8 @@ def _calculate_free_throws_percentage(data: dict[str, Any]) -> float | None:
544
548
  free_throws_attempted = data.get(TEAM_FREE_THROWS_ATTEMPTED_COLUMN)
545
549
  if free_throws_attempted is None:
546
550
  return None
551
+ if free_throws_attempted == 0:
552
+ return 0.0
547
553
  return float(free_throws) / float(free_throws_attempted) # type: ignore
548
554
 
549
555
 
@@ -770,7 +776,9 @@ class TeamModel(BaseModel):
770
776
  json_schema_extra={TYPE_KEY: FieldType.LOOKAHEAD},
771
777
  alias=TEAM_GOAL_ASSISTS_COLUMN,
772
778
  )
773
- coaches: list[CoachModel] = Field(..., alias=TEAM_COACHES_COLUMN)
779
+ coaches: list[CoachModel] = Field(
780
+ ..., json_schema_extra={FFILL_KEY: True}, alias=TEAM_COACHES_COLUMN
781
+ )
774
782
  lbw: float | None = Field(
775
783
  ...,
776
784
  json_schema_extra={TYPE_KEY: FieldType.LOOKAHEAD},
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: sportsball
3
- Version: 0.5.4
3
+ Version: 0.5.5
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
@@ -39,6 +39,9 @@ class TestCombinedGameModel(unittest.TestCase):
39
39
  )
40
40
  names = {}
41
41
  coach_names = {}
42
+ players_ffill = {}
43
+ teams_ffill = {}
44
+ coaches_ffill = {}
42
45
  combined_game_model = create_combined_game_model(
43
46
  game_models=[game_model],
44
47
  venue_identity_map={},
@@ -48,5 +51,8 @@ class TestCombinedGameModel(unittest.TestCase):
48
51
  names=names,
49
52
  coach_names=coach_names,
50
53
  last_game_number=None,
54
+ player_ffill=players_ffill,
55
+ team_ffill=teams_ffill,
56
+ coach_ffill=coaches_ffill,
51
57
  )
52
58
  self.assertEqual(combined_game_model.dt, dt)
@@ -75,8 +75,10 @@ class TestCombinedPlayerModel(unittest.TestCase):
75
75
  game_score=None,
76
76
  point_differential=None,
77
77
  )
78
+ players_ffill = {}
78
79
  combined_player_model = create_combined_player_model(
79
- [player_model],
80
- identifier,
80
+ player_models=[player_model],
81
+ identifier=identifier,
82
+ player_ffill=players_ffill,
81
83
  )
82
84
  self.assertEqual(combined_player_model.field_goals_attempted, field_goals_attempted)