"""Minimal Gradio REST helper (no gradio_client dependency). Implements: upload file, call endpoint, poll SSE result.""" import os, json, pathlib, requests def token(): return (os.environ.get("HF_TOKEN") or pathlib.Path("~/.cache/huggingface/token").expanduser().read_text().strip()) def _headers(): return {"Authorization": f"Bearer {token()}"} def upload(space_root, filepath): """Upload a local file, return the gradio FileData dict to reference it.""" with open(filepath, "rb") as f: r = requests.post(f"{space_root}/gradio_api/upload", headers=_headers(), files={"files": (pathlib.Path(filepath).name, f)}, timeout=300) r.raise_for_status() server_path = r.json()[0] return {"path": server_path, "meta": {"_type": "gradio.FileData"}, "orig_name": pathlib.Path(filepath).name, "url": None, "size": None, "mime_type": None, "is_stream": False} def call(space_root, api_name, data, timeout=900): """Call /gradio_api/call/{api_name} with ordered `data` list; poll SSE; return data list.""" r = requests.post(f"{space_root}/gradio_api/call/{api_name}", headers={**_headers(), "Content-Type": "application/json"}, data=json.dumps({"data": data}), timeout=60) r.raise_for_status() event_id = r.json()["event_id"] # poll the SSE stream with requests.get(f"{space_root}/gradio_api/call/{api_name}/{event_id}", headers=_headers(), stream=True, timeout=timeout) as s: s.raise_for_status() event = None for raw in s.iter_lines(decode_unicode=True): if raw is None or raw == "": continue if raw.startswith("event:"): event = raw.split(":", 1)[1].strip() elif raw.startswith("data:"): payload = raw.split(":", 1)[1].strip() if event == "complete": return json.loads(payload) if event == "error": raise RuntimeError(f"Gradio error: {payload}") raise RuntimeError("SSE stream ended without a 'complete' event") def download(url_or_data, dest, space_root=None): """Download a gradio result (url string or FileData dict) to dest.""" if isinstance(url_or_data, dict): url = url_or_data.get("url") if not url and url_or_data.get("path") and space_root: url = f"{space_root}/gradio_api/file={url_or_data['path']}" else: url = url_or_data if url and url.startswith("/") and space_root: url = space_root + url r = requests.get(url, headers=_headers(), stream=True, timeout=600) r.raise_for_status() with open(dest, "wb") as f: for chunk in r.iter_content(chunk_size=1 << 16): f.write(chunk) return dest