#!/usr/bin/env python3 """Resumable download (Range) with retries. Survives under setsid (python does; curl/wget under setsid died with the bash tool). Usage: dl.py URL DEST [RETRIES] Fix 2026-08-05: if the server answers 416 (Range past EOF), the file is already complete → exit OK after comparing against the real Content-Length (HEAD). """ from __future__ import annotations import os import sys import time import urllib.error import urllib.request URL, DEST = sys.argv[1], sys.argv[2] RETRIES = int(sys.argv[3]) if len(sys.argv) > 3 else 30 def content_length() -> int | None: """Total length of the remote file (HEAD, following redirects).""" try: req = urllib.request.Request(URL, method="HEAD") with urllib.request.urlopen(req, timeout=30) as r: return int(r.headers.get("Content-Length", 0)) or None except Exception: # noqa: BLE001 return None def download() -> bool: pos = os.path.getsize(DEST) if os.path.exists(DEST) else 0 total = content_length() if total is not None and pos >= total: return True # already complete req = urllib.request.Request(URL, headers={"Range": f"bytes={pos}-"}) with urllib.request.urlopen(req) as r, open(DEST, "ab") as f: while True: chunk = r.read(1 << 20) if not chunk: return True f.write(chunk) for attempt in range(1, RETRIES + 1): try: if download(): print(f"OK {os.path.getsize(DEST)}", flush=True) sys.exit(0) except urllib.error.HTTPError as e: if e.code == 416: # range from EOF → the file is already complete print(f"OK 416-complete {os.path.getsize(DEST)}", flush=True) sys.exit(0) print( f"attempt {attempt} failed: HTTP {e.code} (partial {os.path.getsize(DEST)})", flush=True, ) except Exception as e: # noqa: BLE001 print(f"attempt {attempt} failed: {e!r} (partial {os.path.getsize(DEST)})", flush=True) time.sleep(5) print(f"EXHAUSTED after {RETRIES} attempts", flush=True) sys.exit(1)