""" patch_port.py — Rewrites the port in main.py to 7860 (HuggingFace Spaces). Handles all common FastAPI/uvicorn port patterns: - uvicorn.run(app, host="...", port=XXXX) - uvicorn.run("main:app", host="...", port=XXXX) - port = XXXX (bare assignment) - --port XXXX (CLI string inside code) - PORT env var fallback patterns """ import re import sys import shutil from pathlib import Path TARGET_PORT = 7860 MAIN_FILE = Path(__file__).parent / "main.py" BACKUP_FILE = MAIN_FILE.with_suffix(".py.bak") # ── Regex patterns to match & replace ──────────────────────────────────────── PATTERNS = [ # uvicorn.run(..., port=11235, ...) — any existing port number (r'(port\s*=\s*)\d{4,5}', rf'\g<1>{TARGET_PORT}'), # uvicorn.run("main:app", ..., port=11235) (r'("port"\s*:\s*)\d{4,5}', rf'\g<1>{TARGET_PORT}'), # os.environ.get("PORT", "11235") (r'(os\.environ\.get\(["\']PORT["\']\s*,\s*["\'])\d{4,5}(["\'])', rf'\g<1>{TARGET_PORT}\g<2>'), # PORT = 11235 (r'^(PORT\s*=\s*)\d{4,5}', rf'\g<1>{TARGET_PORT}', re.MULTILINE), ] def patch(file: Path) -> bool: if not file.exists(): print(f"[patch_port] ERROR: {file} not found.", file=sys.stderr) sys.exit(1) original = file.read_text(encoding="utf-8") patched = original changes = 0 for entry in PATTERNS: pattern, replacement = entry[0], entry[1] flags = entry[2] if len(entry) == 3 else 0 new, n = re.subn(pattern, replacement, patched, flags=flags) if n: changes += n patched = new if changes == 0: print(f"[patch_port] No port patterns found in {file}.") print(f"[patch_port] Please verify main.py manually sets port={TARGET_PORT}.") # Don't fail — app might already be correct or uses env var return False # Write backup then patched file shutil.copy(file, BACKUP_FILE) file.write_text(patched, encoding="utf-8") print(f"[patch_port] ✅ {changes} replacement(s) made in {file}") print(f"[patch_port] Backup saved to {BACKUP_FILE}") return True if __name__ == "__main__": patch(MAIN_FILE)