✨ feat(cli): migrate build_season_schedule and compute_ratings to typer CLI
- add typer-based CLI to build_season_schedule.py for structured option handling - refactor compute_ratings.py to remove argparse and support typer CLI - improve typing and option descriptions in compute_ratings.py main function - add .gitignore entry for __pycache__ - add requirements.txt with dependencies for the project
This commit is contained in:
@@ -30,6 +30,7 @@ from urllib.parse import urlencode
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
from dateutil import parser as dtp
|
||||
import typer
|
||||
|
||||
# ----------------- logging -----------------
|
||||
logging.basicConfig(
|
||||
@@ -264,16 +265,14 @@ def fetch_game_time(game_id: str, session: requests.Session) -> Optional[str]:
|
||||
return None
|
||||
|
||||
# ----------------- build & merge -----------------
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description="Build a deduped season schedule with IDs, winners/losers, runs, and times.")
|
||||
ap.add_argument("--subseason", required=True, help="Subseason ID, e.g. 942425")
|
||||
ap.add_argument("--teams", required=True, help="Path to teams.json (array with team_id, team_slug, instance_id, teamName)")
|
||||
ap.add_argument("--out", default="season_schedule.csv", help="Output CSV path")
|
||||
ap.add_argument("--fetch-time", action="store_true", help="Fetch game time from /game/show/<id>")
|
||||
ap.add_argument("--sleep", type=float, default=0.35, help="Delay between requests (seconds)")
|
||||
args = ap.parse_args()
|
||||
|
||||
by_instance, by_slug, by_norm = load_teams(args.teams)
|
||||
def main(
|
||||
subseason: str = typer.Option(..., help="Subseason ID, e.g. 942425"),
|
||||
teams: str = typer.Option(..., help="Path to teams.json (array with team_id, team_slug, instance_id, teamName)"),
|
||||
out: str = typer.Option("season_schedule.csv", help="Output CSV path"),
|
||||
fetch_time: bool = typer.Option(False, help="Fetch game time from /game/show/<id>"),
|
||||
sleep: float = typer.Option(0.35, help="Delay between requests (seconds)")
|
||||
):
|
||||
by_instance, by_slug, by_norm = load_teams(teams)
|
||||
instance_ids = sorted(by_instance.keys())
|
||||
|
||||
session = requests.Session()
|
||||
@@ -283,8 +282,8 @@ def main():
|
||||
raw: List[dict] = []
|
||||
for i, iid in enumerate(instance_ids, 1):
|
||||
logging.info(f"[{i}/{len(instance_ids)}] Fetching schedule for instance {iid}")
|
||||
raw.extend(parse_printable(iid, args.subseason, session=session))
|
||||
time.sleep(args.sleep) # be polite
|
||||
raw.extend(parse_printable(iid, subseason, session=session))
|
||||
time.sleep(sleep) # be polite
|
||||
|
||||
def rec_from_instance(iid: str) -> Optional[TeamRec]:
|
||||
return by_instance.get(iid)
|
||||
@@ -407,7 +406,7 @@ def main():
|
||||
|
||||
# -------- NEW: fetch game start time from game page --------
|
||||
time_local = ""
|
||||
if args.fetch_time and game_id:
|
||||
if fetch_time and game_id:
|
||||
if game_id in time_cache:
|
||||
tval = time_cache[game_id]
|
||||
else:
|
||||
@@ -415,8 +414,7 @@ def main():
|
||||
tval = fetch_game_time(game_id, session=session)
|
||||
time_cache[game_id] = tval
|
||||
if tval is None:
|
||||
# small backoff to be nice if many misses
|
||||
time.sleep(min(args.sleep * 2, 1.0))
|
||||
time.sleep(min(sleep * 2, 1.0))
|
||||
if tval:
|
||||
time_local = tval
|
||||
|
||||
@@ -452,13 +450,13 @@ def main():
|
||||
"loser_slug","loser_instance","loser_id",
|
||||
"location","status","game_id","source_urls",
|
||||
]
|
||||
with open(args.out, "w", newline="", encoding="utf-8") as f:
|
||||
with open(out, "w", newline="", encoding="utf-8") as f:
|
||||
w = csv.DictWriter(f, fieldnames=fieldnames)
|
||||
w.writeheader()
|
||||
for r in out_rows:
|
||||
w.writerow(r)
|
||||
|
||||
logging.info(f"Wrote {len(out_rows)} games → {args.out}")
|
||||
logging.info(f"Wrote {len(out_rows)} games → {out}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
typer.run(main)
|
||||
|
||||
Reference in New Issue
Block a user