# swehockey-schedule (Python) The Python twin of the Go crawler in the parent directory. Same layout profiles, same invariants, same canonical order — and, on purpose, **the same bytes**. ```console $ python3 -m swehockey.cli schedule --season 20961 --format csv | head -2 season_id,game_id,event_id,date,time,home,away,home_goals,away_goals,periods,spectators,venue 20961,90001001,1109941,2026-09-19,15:15,Frölunda HC,Växjö Lakers HC,5,4,1:1-1 2:2-1 3:2-2,12044,Scandinavium $ python3 -m swehockey.cli crawl --league 20961 # every season, as NDJSON $ python3 -m swehockey.cli leagues # 119 competitions $ python3 -m unittest discover -s tests -t . # 23 offline tests $ SWEHOCKEY_LIVE=1 python3 -m unittest discover -s tests -t . # + the site ``` With `pip install -e .` the same CLI is on `$PATH` as `swehockey-schedule`. ## Why it can agree byte for byte - Same `LAYOUTS` profiles, keyed on the header row; same per-field shape checks; same dual-render agreement for the modern layout; same carry-forward for the date heading and the round number; same invariants (periods sum to the score, ids unique, played ⇔ event link). - Same canonical sort by `(date, time, game_id)`, because the site orders rows by round and puts re-scheduled games where their round says. - The output carries only page-derived data — no fetch timestamp, no unordered iteration, fixed key order — and `json.dumps(..., indent=2, ensure_ascii=False)` is byte-compatible with Go's `json.Encoder`. - The tests read the **Go golden files** in `../testdata`, so the suite doubles as a cross-implementation check. Verified on the live page, not just on fixtures: ``` $ python3 -m swehockey.cli schedule --season 20961 --out py.json $ ../swehockey schedule -season 20961 -out go.json $ cmp py.json go.json && echo identical identical # 364 games, 102536 bytes # and the same for CSV: 365 identical lines # and for the whole archive: 27 seasons, 2119 games, 1779 played ``` ## No runtime dependencies The tree is built by a ~120-line builder on `html.parser`, because the only part of the HTML5 tree construction algorithm this crawler relies on is that stray `