Team Ai
Datasetpublic

Mightys/Notebook_Scripts

sourceHugging Faceupdated 17h agoView on Hugging Face
0likes2.6kdownloads
gradio-tunnel.py211 linesDownload Raw Back to scripts
1import atexit2import os3import platform4import re5import stat6import subprocess7import sys8import time9from pathlib import Path10from typing import List, Optional11 12import requests13 14VERSION = "0.2"15CURRENT_TUNNELS: List["Tunnel"] = []16 17machine = platform.machine()18if machine == "x86_64":19    machine = "amd64"20 21BINARY_REMOTE_NAME = f"frpc_{platform.system().lower()}_{machine.lower()}"22EXTENSION = ".exe" if os.name == "nt" else ""23BINARY_URL = f"https://cdn-media.huggingface.co/frpc-gradio-{VERSION}/{BINARY_REMOTE_NAME}{EXTENSION}"24 25BINARY_FILENAME = f"{BINARY_REMOTE_NAME}_v{VERSION}"26BINARY_FOLDER = Path(__file__).parent.absolute()27BINARY_PATH = f"{BINARY_FOLDER / BINARY_FILENAME}"28 29TUNNEL_TIMEOUT_SECONDS = 3030TUNNEL_ERROR_MESSAGE = (31    "Could not create share URL. "32    "Please check the appended log from frpc for more information:"33)34 35GRADIO_API_SERVER = "https://api.gradio.app/v2/tunnel-request"36GRADIO_SHARE_SERVER_ADDRESS = None37 38 39class Tunnel:40    def __init__(self, remote_host, remote_port, local_host, local_port, share_token):41        self.proc = None42        self.url = None43        self.remote_host = remote_host44        self.remote_port = remote_port45        self.local_host = local_host46        self.local_port = local_port47        self.share_token = share_token48 49    @staticmethod50    def download_binary():51        if not Path(BINARY_PATH).exists():52            resp = requests.get(BINARY_URL)53 54            if resp.status_code == 403:55                raise OSError(56                    f"Cannot set up a share link as this platform is incompatible. Please "57                    f"create a GitHub issue with information about your platform: {platform.uname()}"58                )59 60            resp.raise_for_status()61 62            # Save file data to local copy63            with open(BINARY_PATH, "wb") as file:64                file.write(resp.content)65            st = os.stat(BINARY_PATH)66            os.chmod(BINARY_PATH, st.st_mode | stat.S_IEXEC)67 68    def start_tunnel(self) -> str:69        self.download_binary()70        self.url = self._start_tunnel(BINARY_PATH)71        return self.url72 73    def kill(self):74        if self.proc is not None:75            print(f"Killing tunnel {self.local_host}:{self.local_port} <> {self.url}")76            self.proc.terminate()77            self.proc = None78 79    def _start_tunnel(self, binary: str) -> str:80        CURRENT_TUNNELS.append(self)81        command = [82            binary,83            "http",84            "-n",85            self.share_token,86            "-l",87            str(self.local_port),88            "-i",89            self.local_host,90            "--uc",91            "--sd",92            "random",93            "--ue",94            "--server_addr",95            f"{self.remote_host}:{self.remote_port}",96            "--disable_log_color",97        ]98        self.proc = subprocess.Popen(99            command, stdout=subprocess.PIPE, stderr=subprocess.PIPE100        )101        atexit.register(self.kill)102        return self._read_url_from_tunnel_stream()103 104    def _read_url_from_tunnel_stream(self) -> str:105        start_timestamp = time.time()106 107        log = []108        url = ""109 110        def _raise_tunnel_error():111            log_text = "\n".join(log)112            print(log_text, file=sys.stderr)113            raise ValueError(f"{TUNNEL_ERROR_MESSAGE}\n{log_text}")114 115        while url == "":116            # check for timeout and log117            if time.time() - start_timestamp >= TUNNEL_TIMEOUT_SECONDS:118                _raise_tunnel_error()119 120            assert self.proc is not None121            if self.proc.stdout is None:122                continue123 124            line = self.proc.stdout.readline()125            line = line.decode("utf-8")126 127            if line == "":128                continue129 130            log.append(line.strip())131 132            if "start proxy success" in line:133                result = re.search("start proxy success: (.+)\n", line)134                if result is None:135                    _raise_tunnel_error()136                else:137                    url = result.group(1)138            elif "login to server failed" in line:139                _raise_tunnel_error()140 141        return url142 143 144def setup_tunnel(145    local_host: str,146    local_port: int,147    share_token: str,148    share_server_address: Optional[str],149) -> str:150    share_server_address = (151        GRADIO_SHARE_SERVER_ADDRESS152        if share_server_address is None153        else share_server_address154    )155    if share_server_address is None:156        response = requests.get(GRADIO_API_SERVER)157        if not (response and response.status_code == 200):158            raise RuntimeError("Could not get share link from Gradio API Server.")159        payload = response.json()[0]160        remote_host, remote_port = payload["host"], int(payload["port"])161    else:162        remote_host, remote_port = share_server_address.split(":")163        remote_port = int(remote_port)164    try:165        tunnel = Tunnel(remote_host, remote_port, local_host, local_port, share_token)166        address = tunnel.start_tunnel()167        return address168    except Exception as e:169        raise RuntimeError(str(e)) from e170 171 172def main():173    import argparse174    import secrets175    import time176 177    parser = argparse.ArgumentParser(description="Set up a tunnel.")178    parser.add_argument(179        "-p",180        "--port",181        type=int,182        default=8080,183        help="the port number to use for the tunnel.",184    )185    parser.add_argument(186        "port_positional",187        type=int,188        nargs="?",189        help="the port number to use for the tunnel.",190    )191    parser.add_argument(192        "--sd", "--subdomain", type=str, help="the subdomain to use for the tunnel."193    )194    args = parser.parse_args()195 196    if args.port_positional is not None:197        args.port = args.port_positional198 199    address = setup_tunnel(200        "127.0.0.1",201        args.port,202        secrets.token_urlsafe(32) if args.sd is None else args.sd,203        None,204    )205 206    print(address, flush=True)207    time.sleep(3600 * 24 * 3)208 209if __name__ == "__main__":210    main()211