cfb-data 0.7.1__tar.gz → 0.9.0__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 (347) hide show
  1. {cfb_data-0.7.1 → cfb_data-0.9.0}/PKG-INFO +60 -11
  2. {cfb_data-0.7.1 → cfb_data-0.9.0}/README.md +44 -8
  3. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/_executor.py +4 -0
  4. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/_observability.py +27 -2
  5. cfb_data-0.9.0/cfb_data/cfb_data/_operation.py +167 -0
  6. {cfb_data-0.7.1/cfb_data/cfb_data/cache → cfb_data-0.9.0/cfb_data/cfb_data}/_sqlite_sql.py +3 -14
  7. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/_tabular.py +192 -1
  8. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/_transport.py +41 -1
  9. cfb_data-0.9.0/cfb_data/cfb_data/adjusted_metrics/_operations.py +58 -0
  10. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/adjusted_metrics/resource.py +19 -63
  11. cfb_data-0.9.0/cfb_data/cfb_data/adjusted_metrics/sources.py +114 -0
  12. cfb_data-0.9.0/cfb_data/cfb_data/analytics/__init__.py +182 -0
  13. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_artifact_contract.py +171 -0
  14. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_artifacts.py +767 -0
  15. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_checkpoints.py +123 -0
  16. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_compiler.py +444 -0
  17. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_compute.py +89 -0
  18. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_contracts.py +73 -0
  19. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_dask.py +505 -0
  20. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_dask_transport.py +324 -0
  21. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_declarations.py +44 -0
  22. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_execution.py +140 -0
  23. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_graph.py +133 -0
  24. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_graph_context.py +34 -0
  25. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_native_execution.py +223 -0
  26. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_native_tables.py +443 -0
  27. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_observability.py +38 -0
  28. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_parameters.py +148 -0
  29. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_persistence.py +1595 -0
  30. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_recipes.py +867 -0
  31. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_registration.py +115 -0
  32. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_runtime.py +756 -0
  33. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_sources.py +712 -0
  34. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_sqlite_sql.py +18 -0
  35. cfb_data-0.9.0/cfb_data/cfb_data/analytics/_transforms.py +1173 -0
  36. cfb_data-0.9.0/cfb_data/cfb_data/analytics/config.py +38 -0
  37. cfb_data-0.9.0/cfb_data/cfb_data/analytics/discovery.py +241 -0
  38. cfb_data-0.9.0/cfb_data/cfb_data/analytics/errors.py +168 -0
  39. cfb_data-0.9.0/cfb_data/cfb_data/analytics/maintenance.py +630 -0
  40. cfb_data-0.9.0/cfb_data/cfb_data/analytics/observability.py +143 -0
  41. cfb_data-0.9.0/cfb_data/cfb_data/analytics/operations.py +339 -0
  42. cfb_data-0.9.0/cfb_data/cfb_data/analytics/planning.py +507 -0
  43. cfb_data-0.9.0/cfb_data/cfb_data/analytics/results.py +490 -0
  44. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/artifacts/insert_gc_transition.sql +2 -0
  45. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/artifacts/insert_object.sql +4 -0
  46. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/artifacts/insert_pin_transition.sql +3 -0
  47. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/artifacts/require_registered.sql +1 -0
  48. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/artifacts/select_active_pins.sql +11 -0
  49. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/artifacts/select_eligible_for_prune.sql +37 -0
  50. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/artifacts/select_gc_state.sql +4 -0
  51. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/artifacts/select_manifest.sql +3 -0
  52. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/artifacts/select_pin_state.sql +4 -0
  53. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/artifacts/select_referenced_runs.sql +4 -0
  54. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/artifacts/select_registered_digests.sql +3 -0
  55. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/attempts/count_by_run.sql +3 -0
  56. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/attempts/insert_reservation.sql +3 -0
  57. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/checkpoints/select_global.sql +11 -0
  58. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/checkpoints/select_parent.sql +21 -0
  59. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/config/set_busy_timeout.sql +1 -0
  60. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/config/set_journal_delete.sql +1 -0
  61. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/config/set_query_only.sql +1 -0
  62. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/config/set_synchronous_full.sql +1 -0
  63. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/leases/acquire_node_lease.sql +10 -0
  64. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/leases/release_node_lease.sql +3 -0
  65. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/leases/renew_node_lease.sql +5 -0
  66. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/leases/select_node_lease.sql +3 -0
  67. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/migrations/001_initial.sql +96 -0
  68. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/migrations/002_credential_scope.sql +4 -0
  69. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/migrations/003_retention.sql +53 -0
  70. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/migrations/004_attempt_reservations.sql +26 -0
  71. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/migrations/005_checkpoint_eligibility.sql +8 -0
  72. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/migrations/006_node_leases.sql +16 -0
  73. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/migrations/get_user_version.sql +1 -0
  74. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/nodes/insert_binding.sql +4 -0
  75. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/nodes/insert_transition.sql +3 -0
  76. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/nodes/select_bindings.sql +3 -0
  77. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/nodes/select_current_state.sql +4 -0
  78. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/runs/insert_retention_transition.sql +2 -0
  79. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/runs/insert_run.sql +5 -0
  80. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/runs/insert_transition.sql +3 -0
  81. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/runs/require_run.sql +1 -0
  82. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/runs/select_attempt_limit.sql +1 -0
  83. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/runs/select_current_state.sql +4 -0
  84. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/runs/select_newest_compatible_run.sql +15 -0
  85. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/runs/select_retention_state.sql +4 -0
  86. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/runs/select_run.sql +9 -0
  87. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/runs/select_runs.sql +10 -0
  88. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/runs/select_unavailable_retained_content.sql +14 -0
  89. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/transaction/commit.sql +1 -0
  90. cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/transaction/rollback.sql +1 -0
  91. cfb_data-0.9.0/cfb_data/cfb_data/analytics/tables.py +691 -0
  92. cfb_data-0.9.0/cfb_data/cfb_data/analytics/tabular.py +261 -0
  93. cfb_data-0.9.0/cfb_data/cfb_data/analytics/types.py +85 -0
  94. cfb_data-0.9.0/cfb_data/cfb_data/analytics/yaml.py +704 -0
  95. cfb_data-0.9.0/cfb_data/cfb_data/betting/_operations.py +19 -0
  96. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/betting/resource.py +4 -18
  97. cfb_data-0.9.0/cfb_data/cfb_data/betting/sources.py +66 -0
  98. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/_backend.py +5 -1
  99. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/_coordinator.py +23 -1
  100. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/_models.py +18 -0
  101. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/_null.py +5 -1
  102. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/_redis.py +27 -1
  103. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/_sqlite.py +37 -1
  104. cfb_data-0.9.0/cfb_data/cfb_data/cache/_sqlite_sql.py +15 -0
  105. cfb_data-0.9.0/cfb_data/cfb_data/cache/sql/begin_immediate.sql +1 -0
  106. cfb_data-0.9.0/cfb_data/cfb_data/cache/sql/enable_foreign_keys.sql +1 -0
  107. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/client.py +53 -5
  108. cfb_data-0.9.0/cfb_data/cfb_data/coaches/_operations.py +32 -0
  109. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/coaches/resource.py +7 -14
  110. cfb_data-0.9.0/cfb_data/cfb_data/coaches/sources.py +65 -0
  111. cfb_data-0.9.0/cfb_data/cfb_data/drives/_operations.py +19 -0
  112. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/drives/resource.py +4 -19
  113. cfb_data-0.9.0/cfb_data/cfb_data/drives/sources.py +70 -0
  114. cfb_data-0.9.0/cfb_data/cfb_data/games/_operations.py +95 -0
  115. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/games/resource.py +31 -66
  116. cfb_data-0.9.0/cfb_data/cfb_data/games/sources.py +285 -0
  117. cfb_data-0.9.0/cfb_data/cfb_data/metrics/_operations.py +71 -0
  118. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/metrics/resource.py +22 -35
  119. cfb_data-0.9.0/cfb_data/cfb_data/metrics/sources.py +181 -0
  120. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/observability.py +4 -0
  121. cfb_data-0.9.0/cfb_data/cfb_data/players/_operations.py +32 -0
  122. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/players/resource.py +7 -14
  123. cfb_data-0.9.0/cfb_data/cfb_data/players/sources.py +61 -0
  124. cfb_data-0.9.0/cfb_data/cfb_data/plays/_operations.py +44 -0
  125. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/plays/models/pydantic/requests.py +6 -0
  126. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/plays/resource.py +8 -46
  127. cfb_data-0.9.0/cfb_data/cfb_data/plays/sources.py +73 -0
  128. cfb_data-0.9.0/cfb_data/cfb_data/rankings/_operations.py +19 -0
  129. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/rankings/resource.py +4 -18
  130. cfb_data-0.9.0/cfb_data/cfb_data/rankings/sources.py +58 -0
  131. cfb_data-0.9.0/cfb_data/cfb_data/ratings/_operations.py +95 -0
  132. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/ratings/resource.py +31 -85
  133. cfb_data-0.9.0/cfb_data/cfb_data/ratings/sources.py +202 -0
  134. cfb_data-0.9.0/cfb_data/cfb_data/recruiting/_operations.py +35 -0
  135. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/recruiting/resource.py +7 -14
  136. cfb_data-0.9.0/cfb_data/cfb_data/recruiting/sources.py +66 -0
  137. cfb_data-0.9.0/cfb_data/cfb_data/stats/_operations.py +95 -0
  138. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/stats/resource.py +32 -86
  139. cfb_data-0.9.0/cfb_data/cfb_data/stats/sources.py +289 -0
  140. cfb_data-0.9.0/cfb_data/cfb_data/teams/_operations.py +59 -0
  141. cfb_data-0.9.0/cfb_data/cfb_data/teams/identity.py +143 -0
  142. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/teams/resource.py +13 -46
  143. cfb_data-0.9.0/cfb_data/cfb_data/teams/sources.py +94 -0
  144. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data.egg-info/PKG-INFO +60 -11
  145. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data.egg-info/SOURCES.txt +134 -1
  146. cfb_data-0.9.0/cfb_data/cfb_data.egg-info/entry_points.txt +2 -0
  147. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data.egg-info/requires.txt +15 -0
  148. cfb_data-0.9.0/cfb_data/cfb_data.egg-info/top_level.txt +2 -0
  149. cfb_data-0.9.0/cfb_data/cfb_data_recipes/__init__.py +6 -0
  150. cfb_data-0.9.0/cfb_data/cfb_data_recipes/betting_lines.py +172 -0
  151. cfb_data-0.9.0/cfb_data/cfb_data_recipes/coach_seasons.py +244 -0
  152. cfb_data-0.9.0/cfb_data/cfb_data_recipes/drives.py +214 -0
  153. cfb_data-0.9.0/cfb_data/cfb_data_recipes/game_summaries.py +579 -0
  154. cfb_data-0.9.0/cfb_data/cfb_data_recipes/play_player_stats.py +316 -0
  155. cfb_data-0.9.0/cfb_data/cfb_data_recipes/player_game_stats.py +226 -0
  156. cfb_data-0.9.0/cfb_data/cfb_data_recipes/player_seasons.py +456 -0
  157. cfb_data-0.9.0/cfb_data/cfb_data_recipes/plays.py +277 -0
  158. cfb_data-0.9.0/cfb_data/cfb_data_recipes/poll_rankings.py +133 -0
  159. cfb_data-0.9.0/cfb_data/cfb_data_recipes/program_history.py +256 -0
  160. cfb_data-0.9.0/cfb_data/cfb_data_recipes/py.typed +0 -0
  161. cfb_data-0.9.0/cfb_data/cfb_data_recipes/recruiting_classes.py +206 -0
  162. cfb_data-0.9.0/cfb_data/cfb_data_recipes/rosters.py +152 -0
  163. cfb_data-0.9.0/cfb_data/cfb_data_recipes/single_game_analysis.py +92 -0
  164. cfb_data-0.9.0/cfb_data/cfb_data_recipes/team_games.py +653 -0
  165. cfb_data-0.9.0/cfb_data/cfb_data_recipes/team_season_analysis.py +178 -0
  166. cfb_data-0.9.0/cfb_data/cfb_data_recipes/team_seasons.py +477 -0
  167. {cfb_data-0.7.1 → cfb_data-0.9.0}/pyproject.toml +27 -6
  168. cfb_data-0.7.1/cfb_data/cfb_data.egg-info/top_level.txt +0 -1
  169. {cfb_data-0.7.1 → cfb_data-0.9.0}/LICENSE +0 -0
  170. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/__init__.py +0 -0
  171. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/_catalog/__init__.py +0 -0
  172. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/_catalog/merge.py +0 -0
  173. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/_catalog/models.py +0 -0
  174. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/_catalog/projection.py +0 -0
  175. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/_catalog/sources.py +0 -0
  176. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/_dataframes.py +0 -0
  177. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/_parquet.py +0 -0
  178. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/_reference_enums.py +0 -0
  179. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/_request_rules.py +0 -0
  180. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/_requests.py +0 -0
  181. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/adjusted_metrics/__init__.py +0 -0
  182. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/adjusted_metrics/models/__init__.py +0 -0
  183. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/adjusted_metrics/models/pydantic/__init__.py +0 -0
  184. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/adjusted_metrics/models/pydantic/requests.py +0 -0
  185. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/adjusted_metrics/models/pydantic/responses.py +0 -0
  186. {cfb_data-0.7.1/cfb_data/cfb_data/cache/sql → cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/config}/enable_foreign_keys.sql +0 -0
  187. {cfb_data-0.7.1/cfb_data/cfb_data/cache/sql → cfb_data-0.9.0/cfb_data/cfb_data/analytics/sql/transaction}/begin_immediate.sql +0 -0
  188. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/base/__init__.py +0 -0
  189. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/base/types.py +0 -0
  190. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/betting/__init__.py +0 -0
  191. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/betting/models/__init__.py +0 -0
  192. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/betting/models/pydantic/__init__.py +0 -0
  193. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/betting/models/pydantic/requests.py +0 -0
  194. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/betting/models/pydantic/responses.py +0 -0
  195. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/__init__.py +0 -0
  196. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/_catalog.py +0 -0
  197. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/_catalog_codecs.py +0 -0
  198. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/_identity_codecs.py +0 -0
  199. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/_key.py +0 -0
  200. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/config.py +0 -0
  201. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/policy.py +0 -0
  202. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/acquire_refresh_lease.sql +0 -0
  203. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/catalog_counts.sql +0 -0
  204. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/cleanup_responses.sql +0 -0
  205. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/delete_coverage_failure.sql +0 -0
  206. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/delete_response.sql +0 -0
  207. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/delete_team_aliases.sql +0 -0
  208. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/enable_wal.sql +0 -0
  209. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/find_athletes.sql +0 -0
  210. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/find_conference_by_id.sql +0 -0
  211. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/find_conference_by_name.sql +0 -0
  212. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/find_fresh_coverage.sql +0 -0
  213. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/find_game_by_id.sql +0 -0
  214. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/find_games.sql +0 -0
  215. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/find_team_by_id.sql +0 -0
  216. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/find_team_by_name.sql +0 -0
  217. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/find_venue_by_id.sql +0 -0
  218. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/find_venue_by_name.sql +0 -0
  219. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/get_response.sql +0 -0
  220. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/get_response_size.sql +0 -0
  221. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/get_schema_version.sql +0 -0
  222. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/initialize_schema_version.sql +0 -0
  223. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/release_refresh_lease.sql +0 -0
  224. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/renew_refresh_lease.sql +0 -0
  225. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/schema.sql +0 -0
  226. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/select_catalog_observations.sql +0 -0
  227. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/select_projection_contract.sql +0 -0
  228. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/set_busy_timeout.sql +0 -0
  229. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/set_synchronous_normal.sql +0 -0
  230. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_athlete.sql +0 -0
  231. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_athlete_team_season.sql +0 -0
  232. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_catalog_observation.sql +0 -0
  233. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_coach.sql +0 -0
  234. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_coach_team_season.sql +0 -0
  235. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_conference.sql +0 -0
  236. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_conference_affiliation.sql +0 -0
  237. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_coverage.sql +0 -0
  238. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_coverage_failure.sql +0 -0
  239. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_drive.sql +0 -0
  240. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_game.sql +0 -0
  241. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_play.sql +0 -0
  242. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_playoff_matchup.sql +0 -0
  243. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_recruit.sql +0 -0
  244. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_response.sql +0 -0
  245. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_team.sql +0 -0
  246. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_team_alias.sql +0 -0
  247. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_team_season.sql +0 -0
  248. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_venue.sql +0 -0
  249. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/cache/sql/upsert_vocabulary.sql +0 -0
  250. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/coaches/__init__.py +0 -0
  251. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/coaches/models/__init__.py +0 -0
  252. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/coaches/models/pydantic/__init__.py +0 -0
  253. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/coaches/models/pydantic/requests.py +0 -0
  254. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/coaches/models/pydantic/responses.py +0 -0
  255. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/conferences/__init__.py +0 -0
  256. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/conferences/models/__init__.py +0 -0
  257. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/conferences/models/pydantic/__init__.py +0 -0
  258. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/conferences/models/pydantic/identity.py +0 -0
  259. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/conferences/models/pydantic/requests.py +0 -0
  260. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/conferences/models/pydantic/responses.py +0 -0
  261. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/conferences/resource.py +0 -0
  262. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/draft/__init__.py +0 -0
  263. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/draft/models/__init__.py +0 -0
  264. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/draft/models/pydantic/__init__.py +0 -0
  265. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/draft/models/pydantic/requests.py +0 -0
  266. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/draft/models/pydantic/responses.py +0 -0
  267. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/draft/resource.py +0 -0
  268. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/drives/__init__.py +0 -0
  269. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/drives/models/__init__.py +0 -0
  270. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/drives/models/pydantic/__init__.py +0 -0
  271. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/drives/models/pydantic/requests.py +0 -0
  272. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/drives/models/pydantic/responses.py +0 -0
  273. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/enums.py +0 -0
  274. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/errors.py +0 -0
  275. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/games/__init__.py +0 -0
  276. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/games/models/__init__.py +0 -0
  277. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/games/models/pydantic/__init__.py +0 -0
  278. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/games/models/pydantic/identity.py +0 -0
  279. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/games/models/pydantic/requests.py +0 -0
  280. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/games/models/pydantic/responses.py +0 -0
  281. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/identities/__init__.py +0 -0
  282. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/identities/_normalization.py +0 -0
  283. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/identities/contracts.py +0 -0
  284. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/identities/resource.py +0 -0
  285. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/info/__init__.py +0 -0
  286. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/info/models/__init__.py +0 -0
  287. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/info/models/pydantic/__init__.py +0 -0
  288. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/info/models/pydantic/requests.py +0 -0
  289. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/info/models/pydantic/responses.py +0 -0
  290. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/info/resource.py +0 -0
  291. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/metrics/__init__.py +0 -0
  292. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/metrics/models/__init__.py +0 -0
  293. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/metrics/models/pydantic/__init__.py +0 -0
  294. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/metrics/models/pydantic/requests.py +0 -0
  295. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/metrics/models/pydantic/responses.py +0 -0
  296. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/players/__init__.py +0 -0
  297. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/players/models/__init__.py +0 -0
  298. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/players/models/pydantic/__init__.py +0 -0
  299. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/players/models/pydantic/identity.py +0 -0
  300. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/players/models/pydantic/requests.py +0 -0
  301. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/players/models/pydantic/responses.py +0 -0
  302. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/playoffs/__init__.py +0 -0
  303. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/playoffs/models/__init__.py +0 -0
  304. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/playoffs/models/pydantic/__init__.py +0 -0
  305. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/playoffs/models/pydantic/requests.py +0 -0
  306. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/playoffs/models/pydantic/responses.py +0 -0
  307. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/playoffs/resource.py +0 -0
  308. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/plays/__init__.py +0 -0
  309. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/plays/models/__init__.py +0 -0
  310. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/plays/models/pydantic/__init__.py +0 -0
  311. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/plays/models/pydantic/responses.py +0 -0
  312. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/py.typed +0 -0
  313. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/rankings/__init__.py +0 -0
  314. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/rankings/models/__init__.py +0 -0
  315. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/rankings/models/pydantic/__init__.py +0 -0
  316. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/rankings/models/pydantic/requests.py +0 -0
  317. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/rankings/models/pydantic/responses.py +0 -0
  318. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/ratings/__init__.py +0 -0
  319. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/ratings/models/__init__.py +0 -0
  320. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/ratings/models/pydantic/__init__.py +0 -0
  321. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/ratings/models/pydantic/requests.py +0 -0
  322. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/ratings/models/pydantic/responses.py +0 -0
  323. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/recruiting/__init__.py +0 -0
  324. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/recruiting/models/__init__.py +0 -0
  325. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/recruiting/models/pydantic/__init__.py +0 -0
  326. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/recruiting/models/pydantic/requests.py +0 -0
  327. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/recruiting/models/pydantic/responses.py +0 -0
  328. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/retry.py +0 -0
  329. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/stats/__init__.py +0 -0
  330. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/stats/models/__init__.py +0 -0
  331. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/stats/models/pydantic/__init__.py +0 -0
  332. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/stats/models/pydantic/requests.py +0 -0
  333. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/stats/models/pydantic/responses.py +0 -0
  334. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/teams/__init__.py +0 -0
  335. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/teams/models/__init__.py +0 -0
  336. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/teams/models/pydantic/__init__.py +0 -0
  337. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/teams/models/pydantic/identity.py +0 -0
  338. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/teams/models/pydantic/requests.py +0 -0
  339. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/teams/models/pydantic/responses.py +0 -0
  340. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/venues/__init__.py +0 -0
  341. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/venues/models/__init__.py +0 -0
  342. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/venues/models/pydantic/__init__.py +0 -0
  343. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/venues/models/pydantic/identity.py +0 -0
  344. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/venues/models/pydantic/responses.py +0 -0
  345. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data/venues/resource.py +0 -0
  346. {cfb_data-0.7.1 → cfb_data-0.9.0}/cfb_data/cfb_data.egg-info/dependency_links.txt +0 -0
  347. {cfb_data-0.7.1 → cfb_data-0.9.0}/setup.cfg +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cfb-data
3
- Version: 0.7.1
4
- Summary: Async validated CollegeFootballData access for pandas and Polars
3
+ Version: 0.9.0
4
+ Summary: Async validated CollegeFootballData access for pandas and Polars, with native Dask analytics
5
5
  Author: Ryan Anderson
6
6
  License-Expression: MIT
7
7
  Project-URL: Documentation, https://ryanpaulanderson.github.io/cfb-data/
8
8
  Project-URL: Repository, https://github.com/ryanpaulanderson/cfb-data
9
9
  Project-URL: Issues, https://github.com/ryanpaulanderson/cfb-data/issues
10
- Classifier: Development Status :: 2 - Pre-Alpha
10
+ Classifier: Development Status :: 4 - Beta
11
11
  Classifier: Intended Audience :: Developers
12
12
  Classifier: Programming Language :: Python :: 3
13
13
  Classifier: Programming Language :: Python :: 3.12
@@ -17,14 +17,22 @@ Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
18
  Requires-Dist: aiohttp<4,>=3.13
19
19
  Requires-Dist: aiosqlite<1,>=0.22
20
+ Requires-Dist: dask[dataframe]<2027,>=2026.7.1
20
21
  Requires-Dist: jinja2<4,>=3.1
22
+ Requires-Dist: narwhals<3,>=2.24
23
+ Requires-Dist: numpy<3,>=2
21
24
  Requires-Dist: pandas<4,>=3.0
25
+ Requires-Dist: platformdirs<5,>=4.11
22
26
  Requires-Dist: pydantic<3,>=2.12
23
27
  Requires-Dist: pyarrow<26,>=25
24
28
  Provides-Extra: polars
25
29
  Requires-Dist: polars<2,>=1.43.2; extra == "polars"
26
30
  Provides-Extra: redis
27
31
  Requires-Dist: redis<9,>=7.1; extra == "redis"
32
+ Provides-Extra: dask
33
+ Requires-Dist: distributed<2027,>=2026.7.1; extra == "dask"
34
+ Provides-Extra: yaml
35
+ Requires-Dist: PyYAML<7,>=6.0.3; extra == "yaml"
28
36
  Provides-Extra: dev
29
37
  Requires-Dist: build<2,>=1.5; extra == "dev"
30
38
  Requires-Dist: furo>=2025.12.19; extra == "dev"
@@ -34,14 +42,19 @@ Requires-Dist: pre-commit<5,>=4.5; extra == "dev"
34
42
  Requires-Dist: pyarrow-stubs<21,>=20.0.0.20260625; extra == "dev"
35
43
  Requires-Dist: pytest<10,>=9; extra == "dev"
36
44
  Requires-Dist: pytest-asyncio<2,>=1.3; extra == "dev"
45
+ Requires-Dist: pytest-split<1,>=0.11; extra == "dev"
46
+ Requires-Dist: pytest-xdist<4,>=3.8; extra == "dev"
37
47
  Requires-Dist: ruff<0.17,>=0.15.22; extra == "dev"
48
+ Requires-Dist: setuptools<85,>=80; extra == "dev"
38
49
  Requires-Dist: sphinx<10,>=9.1; extra == "dev"
39
50
  Requires-Dist: twine<8,>=7; extra == "dev"
51
+ Requires-Dist: types-PyYAML<6.1,>=6.0.12.20260815; extra == "dev"
52
+ Requires-Dist: wheel<1,>=0.46; extra == "dev"
40
53
  Dynamic: license-file
41
54
 
42
55
  # College Football Data Python Toolkit
43
56
 
44
- `cfb-data` 0.7.1 is a pre-alpha Python toolkit for exploring the public
57
+ `cfb-data` 0.9.0 is a beta Python toolkit for exploring the public
45
58
  [CollegeFootballData API](https://collegefootballdata.com/). Most calls return
46
59
  eager pandas DataFrames that are ready for analysis. Polars is available as an
47
60
  option, and a few naturally nested results return Pydantic models.
@@ -55,7 +68,7 @@ HTTP client or cleaning up inconsistent response shapes.
55
68
  - Pull games, plays, drives, ratings, rosters, recruiting, betting, draft, and
56
69
  other CFBD data into Python.
57
70
  - Explore one team or season in a notebook.
58
- - Build repeatable pandas or Polars analyses across several endpoints.
71
+ - Run or author durable pandas or Polars recipes across several endpoints.
59
72
  - Cache responses locally so rerunning an analysis does not repeat every API
60
73
  call.
61
74
  - Resolve team, venue, game, and athlete names and IDs when joining data.
@@ -66,7 +79,7 @@ Arrow, HTTP retry logic, or the cache implementation.
66
79
 
67
80
  ## Install
68
81
 
69
- Python 3.12 and 3.13 are supported. pandas and PyArrow are included:
82
+ Python 3.12 and 3.13 are supported. pandas, PyArrow, and native Dask DataFrame processing are included:
70
83
 
71
84
  ```shell
72
85
  python -m pip install cfb-data
@@ -86,6 +99,12 @@ python -m pip install "cfb-data[redis]"
86
99
 
87
100
  SQLite caching is included in the normal installation.
88
101
 
102
+ For parallel Dask workers or safe declarative YAML recipes:
103
+
104
+ ```shell
105
+ python -m pip install "cfb-data[dask,yaml]"
106
+ ```
107
+
89
108
  ## Make a first request
90
109
 
91
110
  Get an API key from [CollegeFootballData](https://collegefootballdata.com/) and
@@ -124,6 +143,32 @@ The `async with` block lets related calls share one HTTP session and closes it
124
143
  when the block ends. Async is limited to gathering and validating data; the
125
144
  pandas calculation starts synchronously after the completed frame is returned.
126
145
 
146
+ ## Run a modular analytics recipe
147
+
148
+ First-party datasets and workflows are ordinary independently importable
149
+ recipe modules. They use the same authoring and execution surface available to
150
+ your own package:
151
+
152
+ ```python
153
+ from cfb_data_recipes.team_seasons import team_seasons
154
+
155
+ async with CFBDClient() as client:
156
+ season = await team_seasons(
157
+ client,
158
+ season=2024,
159
+ team="Penn State",
160
+ )
161
+
162
+ print(season[["team", "season", "expected_wins", "total"]])
163
+ ```
164
+
165
+ Use ``.plan()`` for a pure no-I/O execution plan and ``.run()`` for durable
166
+ artifacts, lineage, source coverage, quality results, and recovery evidence.
167
+ Workflows return explicit named outputs rather than choosing a hidden primary
168
+ table. See [Build durable analyses with modular
169
+ recipes](docs/guides/modular-analytics.md) for the thirteen included datasets,
170
+ three workflows, Dask execution, safe YAML, recovery, and user authoring.
171
+
127
172
  ## Find the data you need
128
173
 
129
174
  Methods are grouped by subject:
@@ -244,8 +289,8 @@ async with CFBDClient(cache=SQLiteCacheConfig(), observer=stats) as client:
244
289
  await client.games.list(year=2025)
245
290
 
246
291
  snapshot = stats.snapshot()
247
- print(snapshot.http_attempts) # actual client-side HTTP attempts
248
- print(snapshot.fresh_cache_hits) # fresh initial cache hits
292
+ print(snapshot.http_attempts) # actual client-side HTTP attempts
293
+ print(snapshot.fresh_cache_hits) # fresh initial cache hits
249
294
  print(snapshot.fresh_hit_rate)
250
295
  ```
251
296
 
@@ -271,8 +316,9 @@ The [complete documentation](https://ryanpaulanderson.github.io/cfb-data/)
271
316
  is organized in layers:
272
317
 
273
318
  - **Start and use:** installation, examples, requests, results, caching, and
274
- troubleshooting, including [common notebook
275
- recipes](docs/guides/common-recipes.md).
319
+ troubleshooting, including [modular analytics
320
+ recipes](docs/guides/modular-analytics.md) and [common notebook
321
+ patterns](docs/guides/common-recipes.md).
276
322
  - **Advanced details:** exact enum values, dtypes, TTLs, retries, and storage
277
323
  behavior.
278
324
  - **Project internals:** architecture decisions and contributor-facing design.
@@ -280,7 +326,10 @@ is organized in layers:
280
326
  The [product constitution](docs/product-constitution.md) is the concise north
281
327
  star used to evaluate product and engineering decisions.
282
328
 
283
- The project is pre-alpha, and the documentation describes the current version.
329
+ The project is in beta: its core retrieval, validation, DataFrame, caching, and
330
+ identity workflows are usable and carefully tested. Public APIs and local cache
331
+ formats may still change before 1.0, and the documentation describes the
332
+ current version.
284
333
 
285
334
  ## Development
286
335
 
@@ -1,6 +1,6 @@
1
1
  # College Football Data Python Toolkit
2
2
 
3
- `cfb-data` 0.7.1 is a pre-alpha Python toolkit for exploring the public
3
+ `cfb-data` 0.9.0 is a beta Python toolkit for exploring the public
4
4
  [CollegeFootballData API](https://collegefootballdata.com/). Most calls return
5
5
  eager pandas DataFrames that are ready for analysis. Polars is available as an
6
6
  option, and a few naturally nested results return Pydantic models.
@@ -14,7 +14,7 @@ HTTP client or cleaning up inconsistent response shapes.
14
14
  - Pull games, plays, drives, ratings, rosters, recruiting, betting, draft, and
15
15
  other CFBD data into Python.
16
16
  - Explore one team or season in a notebook.
17
- - Build repeatable pandas or Polars analyses across several endpoints.
17
+ - Run or author durable pandas or Polars recipes across several endpoints.
18
18
  - Cache responses locally so rerunning an analysis does not repeat every API
19
19
  call.
20
20
  - Resolve team, venue, game, and athlete names and IDs when joining data.
@@ -25,7 +25,7 @@ Arrow, HTTP retry logic, or the cache implementation.
25
25
 
26
26
  ## Install
27
27
 
28
- Python 3.12 and 3.13 are supported. pandas and PyArrow are included:
28
+ Python 3.12 and 3.13 are supported. pandas, PyArrow, and native Dask DataFrame processing are included:
29
29
 
30
30
  ```shell
31
31
  python -m pip install cfb-data
@@ -45,6 +45,12 @@ python -m pip install "cfb-data[redis]"
45
45
 
46
46
  SQLite caching is included in the normal installation.
47
47
 
48
+ For parallel Dask workers or safe declarative YAML recipes:
49
+
50
+ ```shell
51
+ python -m pip install "cfb-data[dask,yaml]"
52
+ ```
53
+
48
54
  ## Make a first request
49
55
 
50
56
  Get an API key from [CollegeFootballData](https://collegefootballdata.com/) and
@@ -83,6 +89,32 @@ The `async with` block lets related calls share one HTTP session and closes it
83
89
  when the block ends. Async is limited to gathering and validating data; the
84
90
  pandas calculation starts synchronously after the completed frame is returned.
85
91
 
92
+ ## Run a modular analytics recipe
93
+
94
+ First-party datasets and workflows are ordinary independently importable
95
+ recipe modules. They use the same authoring and execution surface available to
96
+ your own package:
97
+
98
+ ```python
99
+ from cfb_data_recipes.team_seasons import team_seasons
100
+
101
+ async with CFBDClient() as client:
102
+ season = await team_seasons(
103
+ client,
104
+ season=2024,
105
+ team="Penn State",
106
+ )
107
+
108
+ print(season[["team", "season", "expected_wins", "total"]])
109
+ ```
110
+
111
+ Use ``.plan()`` for a pure no-I/O execution plan and ``.run()`` for durable
112
+ artifacts, lineage, source coverage, quality results, and recovery evidence.
113
+ Workflows return explicit named outputs rather than choosing a hidden primary
114
+ table. See [Build durable analyses with modular
115
+ recipes](docs/guides/modular-analytics.md) for the thirteen included datasets,
116
+ three workflows, Dask execution, safe YAML, recovery, and user authoring.
117
+
86
118
  ## Find the data you need
87
119
 
88
120
  Methods are grouped by subject:
@@ -203,8 +235,8 @@ async with CFBDClient(cache=SQLiteCacheConfig(), observer=stats) as client:
203
235
  await client.games.list(year=2025)
204
236
 
205
237
  snapshot = stats.snapshot()
206
- print(snapshot.http_attempts) # actual client-side HTTP attempts
207
- print(snapshot.fresh_cache_hits) # fresh initial cache hits
238
+ print(snapshot.http_attempts) # actual client-side HTTP attempts
239
+ print(snapshot.fresh_cache_hits) # fresh initial cache hits
208
240
  print(snapshot.fresh_hit_rate)
209
241
  ```
210
242
 
@@ -230,8 +262,9 @@ The [complete documentation](https://ryanpaulanderson.github.io/cfb-data/)
230
262
  is organized in layers:
231
263
 
232
264
  - **Start and use:** installation, examples, requests, results, caching, and
233
- troubleshooting, including [common notebook
234
- recipes](docs/guides/common-recipes.md).
265
+ troubleshooting, including [modular analytics
266
+ recipes](docs/guides/modular-analytics.md) and [common notebook
267
+ patterns](docs/guides/common-recipes.md).
235
268
  - **Advanced details:** exact enum values, dtypes, TTLs, retries, and storage
236
269
  behavior.
237
270
  - **Project internals:** architecture decisions and contributor-facing design.
@@ -239,7 +272,10 @@ is organized in layers:
239
272
  The [product constitution](docs/product-constitution.md) is the concise north
240
273
  star used to evaluate product and engineering decisions.
241
274
 
242
- The project is pre-alpha, and the documentation describes the current version.
275
+ The project is in beta: its core retrieval, validation, DataFrame, caching, and
276
+ identity workflows are usable and carefully tested. Public APIs and local cache
277
+ formats may still change before 1.0, and the documentation describes the
278
+ current version.
243
279
 
244
280
  ## Development
245
281
 
@@ -149,6 +149,8 @@ class _EndpointExecutor:
149
149
  endpoint=endpoint,
150
150
  parameter_names=tuple(sorted(parameters)),
151
151
  cache_mode=self._cache_coordinator.current_mode,
152
+ analytics_run_id=context.analytics_run_id,
153
+ analytics_node_id=context.analytics_node_id,
152
154
  )
153
155
  )
154
156
  try:
@@ -190,6 +192,8 @@ class _EndpointExecutor:
190
192
  failure_category=(
191
193
  _failure_category(error) if error is not None else None
192
194
  ),
195
+ analytics_run_id=context.analytics_run_id,
196
+ analytics_node_id=context.analytics_node_id,
193
197
  )
194
198
  )
195
199
 
@@ -6,7 +6,9 @@ import asyncio
6
6
  import logging
7
7
  import time
8
8
  import uuid
9
- from collections.abc import Callable
9
+ from collections.abc import Callable, Iterator
10
+ from contextlib import contextmanager
11
+ from contextvars import ContextVar
10
12
  from dataclasses import dataclass
11
13
 
12
14
  from cfb_data.observability import (
@@ -16,6 +18,9 @@ from cfb_data.observability import (
16
18
  )
17
19
 
18
20
  _LOGGER = logging.getLogger(__name__)
21
+ _ANALYTICS_CORRELATION: ContextVar[tuple[str, str] | None] = ContextVar(
22
+ "cfb_data_analytics_retrieval_correlation", default=None
23
+ )
19
24
 
20
25
 
21
26
  @dataclass(slots=True)
@@ -28,6 +33,8 @@ class _OperationContext:
28
33
  started_at: float
29
34
  source: RetrievalSource = RetrievalSource.unknown
30
35
  refresh_id: str | None = None
36
+ analytics_run_id: str | None = None
37
+ analytics_node_id: str | None = None
31
38
 
32
39
 
33
40
  class _EventDispatcher:
@@ -62,11 +69,14 @@ class _EventDispatcher:
62
69
  """Return a new safe operation context when observation is enabled."""
63
70
  if self._observer is None:
64
71
  return None
72
+ correlation = _ANALYTICS_CORRELATION.get()
65
73
  return _OperationContext(
66
74
  client_id=self._client_id,
67
75
  operation_id=uuid.uuid4().hex,
68
76
  endpoint=endpoint,
69
77
  started_at=self._monotonic(),
78
+ analytics_run_id=(correlation[0] if correlation is not None else None),
79
+ analytics_node_id=(correlation[1] if correlation is not None else None),
70
80
  )
71
81
 
72
82
  def new_refresh_id(self) -> str:
@@ -108,4 +118,19 @@ def _failure_category(error: BaseException) -> str:
108
118
  return type(error).__name__[:64]
109
119
 
110
120
 
111
- __all__ = ["_EventDispatcher", "_OperationContext", "_failure_category"]
121
+ @contextmanager
122
+ def _analytics_retrieval_context(run_id: str, node_id: str) -> Iterator[None]:
123
+ """Correlate task-local endpoint retrieval events with one analytics node."""
124
+ token = _ANALYTICS_CORRELATION.set((run_id, node_id))
125
+ try:
126
+ yield
127
+ finally:
128
+ _ANALYTICS_CORRELATION.reset(token)
129
+
130
+
131
+ __all__ = [
132
+ "_EventDispatcher",
133
+ "_OperationContext",
134
+ "_analytics_retrieval_context",
135
+ "_failure_category",
136
+ ]
@@ -0,0 +1,167 @@
1
+ """Define generic endpoint-operation ownership shared by resources and recipes."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from abc import ABC, abstractmethod
6
+ from dataclasses import dataclass
7
+ from types import GenericAlias
8
+ from typing import Literal
9
+
10
+ from pydantic import BaseModel, TypeAdapter
11
+
12
+ from cfb_data._dataframes import _DataFrameAdapter
13
+ from cfb_data._executor import _EndpointExecutor, _response_contract, _serialize_request
14
+ from cfb_data._requests import _resolve_request
15
+
16
+
17
+ class _EndpointOperation[RequestT: BaseModel, RowT: BaseModel](ABC):
18
+ """Own the common contract for one validated endpoint operation."""
19
+
20
+ id: str
21
+ revision: int
22
+ endpoint: str
23
+ request_type: type[RequestT]
24
+ row_model: type[RowT]
25
+ access_tier: Literal["free", "tier_1", "tier_2"]
26
+ documented_limit: int | None
27
+ cost: int
28
+
29
+ def resolve(
30
+ self,
31
+ request: RequestT | None,
32
+ filters: dict[str, object],
33
+ ) -> RequestT:
34
+ """Return the one authoritative validated request model."""
35
+ return _resolve_request(
36
+ endpoint=self.endpoint,
37
+ request_type=self.request_type,
38
+ request=request,
39
+ filters=filters,
40
+ )
41
+
42
+ @abstractmethod
43
+ async def fetch(
44
+ self,
45
+ executor: _EndpointExecutor,
46
+ request: RequestT,
47
+ ) -> list[RowT]:
48
+ """Return one normalized row list through the shared executor."""
49
+
50
+ @property
51
+ @abstractmethod
52
+ def rows_adapter(self) -> TypeAdapter[list[RowT]]:
53
+ """Return the adapter for the normalized analytical row list."""
54
+
55
+ @property
56
+ @abstractmethod
57
+ def response_contract(self) -> str:
58
+ """Return the actual HTTP response schema fingerprint."""
59
+
60
+ def serialized_parameters(
61
+ self, request: RequestT
62
+ ) -> dict[str, str | int | float | bool]:
63
+ """Return the exact typed upstream request parameters."""
64
+ return _serialize_request(self.endpoint, request)
65
+
66
+
67
+ @dataclass(frozen=True, slots=True)
68
+ class _ManyEndpointOperation[RequestT: BaseModel, RowT: BaseModel](
69
+ _EndpointOperation[RequestT, RowT]
70
+ ):
71
+ """Own one endpoint whose HTTP response is a model list."""
72
+
73
+ id: str
74
+ revision: int
75
+ endpoint: str
76
+ request_type: type[RequestT]
77
+ response_adapter: TypeAdapter[list[RowT]]
78
+ row_model: type[RowT]
79
+ access_tier: Literal["free", "tier_1", "tier_2"]
80
+ documented_limit: int | None = None
81
+ cost: int = 1
82
+
83
+ async def fetch(
84
+ self,
85
+ executor: _EndpointExecutor,
86
+ request: RequestT,
87
+ ) -> list[RowT]:
88
+ """Return validated rows through the shared endpoint executor."""
89
+ return await executor.fetch_many(
90
+ endpoint=self.endpoint,
91
+ request=request,
92
+ response_adapter=self.response_adapter,
93
+ )
94
+
95
+ @property
96
+ def rows_adapter(self) -> TypeAdapter[list[RowT]]:
97
+ """Return the HTTP list adapter as the analytical row adapter."""
98
+ return self.response_adapter
99
+
100
+ async def fetch_frame[FrameT](
101
+ self,
102
+ executor: _EndpointExecutor,
103
+ dataframe_adapter: _DataFrameAdapter[FrameT],
104
+ request: RequestT | None,
105
+ filters: dict[str, object],
106
+ ) -> FrameT:
107
+ """Validate, retrieve, and present rows for a public resource method."""
108
+ validated = self.resolve(request, filters)
109
+ rows = await self.fetch(executor, validated)
110
+ return dataframe_adapter.from_models(
111
+ endpoint=self.endpoint,
112
+ row_model=self.row_model,
113
+ models=rows,
114
+ )
115
+
116
+ @property
117
+ def response_contract(self) -> str:
118
+ """Return the stable response schema fingerprint used by the cache."""
119
+ return _response_contract(self.response_adapter)
120
+
121
+
122
+ @dataclass(frozen=True, slots=True)
123
+ class _OneEndpointOperation[RequestT: BaseModel, RowT: BaseModel](
124
+ _EndpointOperation[RequestT, RowT]
125
+ ):
126
+ """Own one endpoint whose HTTP response is one validated model."""
127
+
128
+ id: str
129
+ revision: int
130
+ endpoint: str
131
+ request_type: type[RequestT]
132
+ response_adapter: TypeAdapter[RowT]
133
+ row_model: type[RowT]
134
+ access_tier: Literal["free", "tier_1", "tier_2"]
135
+ documented_limit: int | None = None
136
+ cost: int = 1
137
+
138
+ async def fetch(
139
+ self,
140
+ executor: _EndpointExecutor,
141
+ request: RequestT,
142
+ ) -> list[RowT]:
143
+ """Wrap the validated HTTP object in the analytical row list."""
144
+ return [await self.fetch_one(executor, request)]
145
+
146
+ async def fetch_one(
147
+ self,
148
+ executor: _EndpointExecutor,
149
+ request: RequestT,
150
+ ) -> RowT:
151
+ """Return the validated object through the shared endpoint executor."""
152
+ return await executor.fetch_one(
153
+ endpoint=self.endpoint,
154
+ request=request,
155
+ response_adapter=self.response_adapter,
156
+ )
157
+
158
+ @property
159
+ def rows_adapter(self) -> TypeAdapter[list[RowT]]:
160
+ """Return the normalized analytical row-list adapter."""
161
+ annotation = GenericAlias(list, self.row_model)
162
+ return TypeAdapter(annotation)
163
+
164
+ @property
165
+ def response_contract(self) -> str:
166
+ """Return the stable single-object response schema fingerprint."""
167
+ return _response_contract(self.response_adapter)
@@ -1,16 +1,10 @@
1
- """Render packaged SQLite templates through one strict SQL handler."""
1
+ """Render packaged SQLite templates through one strict shared handler."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
5
  from pathlib import PurePosixPath
6
6
 
7
- from jinja2 import (
8
- BaseLoader,
9
- Environment,
10
- PackageLoader,
11
- StrictUndefined,
12
- TemplateError,
13
- )
7
+ from jinja2 import BaseLoader, Environment, StrictUndefined, TemplateError
14
8
 
15
9
 
16
10
  class SQLTemplateHandler:
@@ -60,9 +54,4 @@ class SQLTemplateHandler:
60
54
  return rendered
61
55
 
62
56
 
63
- class SQLiteSQL(SQLTemplateHandler):
64
- """Load installed SQLite templates from the cache package."""
65
-
66
- def __init__(self) -> None:
67
- """Bind the strict handler to packaged cache SQL resources."""
68
- super().__init__(PackageLoader("cfb_data.cache", "sql"))
57
+ __all__ = ["SQLTemplateHandler"]