#!/usr/bin/env python3 """Check local deployment readiness and optionally the running Space HTTP/API.""" from __future__ import annotations import argparse from datetime import datetime, timezone import json import os from pathlib import Path import sys ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT / "src")) sys.path.insert(0, str(ROOT)) def main() -> int: from dotenv import load_dotenv load_dotenv(ROOT / ".env") parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--online", action="store_true") parser.add_argument("--require-credentials", action="store_true") parser.add_argument( "--url", default=os.getenv("HF_SPACE_URL", "https://thinkcatlab-livehouse-ts.hf.space"), ) parser.add_argument("--max-age-hours", type=float, default=24) args = parser.parse_args() failures = [] from tsfm_bench.data.registry import load_data_source try: os.chdir(ROOT) source = load_data_source(ROOT / "configs/datasets/ts_bench.yaml") print(f"Local dataset tasks: {len(list(source.list_datasets()))}") except Exception as exc: failures.append(f"Data bootstrap: {exc}") for key in ("TSFM_API_KEY", "HF_TOKEN", "TABPFN_TOKEN"): present = bool(os.getenv(key)) print(f"{key}: {'configured' if present else 'missing'}") if args.require_credentials and not present: failures.append(f"{key} is required for the default full model registry") import importlib.util tabpfn_ready = importlib.util.find_spec("tabpfn_time_series") is not None if not tabpfn_ready: from space.user_models.tabpfn_ts import TabPFNTSPredictor isolated = ROOT / ".venv-tabpfn" / ("Scripts/python.exe" if os.name == "nt" else "bin/python") executable = os.getenv("TABPFN_TS_PYTHON") or str(isolated) tabpfn_ready = TabPFNTSPredictor._probe_external_python(executable) print( f"TabPFN-TS package: {'installed' if tabpfn_ready else 'optional extra not installed'}" ) if args.require_credentials and not tabpfn_ready: failures.append( "Install the enabled TabPFN adapter: python scripts/setup_tabpfn.py" ) if args.online: import httpx from gradio_client import Client try: with httpx.Client(timeout=45, follow_redirects=True) as client: response = client.get(args.url.rstrip("/") + "/config") response.raise_for_status() config = response.json() print( f"Space HTTP config: OK, Gradio {config.get('version')}, {len(config.get('components', []))} components" ) # Exercise a real refresh handler, not just cached HTML. client = Client(args.url, verbose=False) output = client.predict(api_name="/refresh_leaderboard") print(f"Live leaderboard refresh: OK ({len(output)} outputs)") from check_forecast_ui import check_forecast_ui forecasts = check_forecast_ui(client, config) print(f"Live forecast selection/plots: OK ({forecasts['datasets_checked']} datasets, " f"{len(forecasts['model_switches'])} model selections)") summary = output[0] import re match = re.search( r"(\d{4}-\d\d-\d\d \d\d:\d\d:\d\d) \(UTC\+8\)", str(summary) ) if match: from datetime import timedelta last = datetime.strptime(match.group(1), "%Y-%m-%d %H:%M:%S").replace( tzinfo=timezone(timedelta(hours=8)) ) hours = (datetime.now(timezone.utc) - last).total_seconds() / 3600 print(f"Published result age: {hours:.1f} hours") if hours > args.max_age_hours: failures.append(f"Leaderboard is stale ({hours:.1f} hours)") else: failures.append("Leaderboard freshness timestamp missing") except Exception as exc: failures.append(f"Online HTTP/refresh: {exc}") for item in failures: print(f"FAIL: {item}", file=sys.stderr) return int(bool(failures)) if __name__ == "__main__": raise SystemExit(main())