File size: 3,998 Bytes
0ad74ed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
from __future__ import annotations

import shutil
import subprocess
from pathlib import Path
from typing import Annotated, Optional

import typer
from rich import print

import gradio
from gradio.analytics import custom_component_analytics
from gradio.cli.commands.components.install_component import _get_executable_path

gradio_template_path = Path(gradio.__file__).parent / "templates" / "frontend"


def _dev(
    app: Annotated[
        Path,
        typer.Argument(
            help="The path to the app. By default, looks for demo/app.py in the current directory."
        ),
    ] = Path("demo") / "app.py",
    component_directory: Annotated[
        Path,
        typer.Option(
            help="The directory with the custom component source code. By default, uses the current directory."
        ),
    ] = Path("."),
    host: Annotated[
        str,
        typer.Option(
            help="The host to run the front end server on. Defaults to localhost.",
        ),
    ] = "localhost",
    python_path: Annotated[
        Optional[str],
        typer.Option(
            help="Path to python executable. If None, will use the default path found by `which python3`. If python3 is not found, `which python` will be tried. If both fail an error will be raised."
        ),
    ] = None,
    gradio_path: Annotated[
        Optional[str],
        typer.Option(
            help="Path to gradio executable. If None, will use the default path found by `shutil.which`."
        ),
    ] = None,
):
    custom_component_analytics(
        "dev",
        None,
        None,
        None,
        None,
        python_path=python_path,
        gradio_path=gradio_path,
    )
    component_directory = component_directory.resolve()

    print(f":recycle: [green]Launching[/] {app} in reload mode\n")

    node = shutil.which("node")
    if not node:
        raise ValueError("node must be installed in order to run dev mode.")

    python_path = _get_executable_path(
        "python", python_path, cli_arg_name="--python-path", check_3=True
    )
    gradio_path = _get_executable_path(
        "gradio", gradio_path, cli_arg_name="--gradio-path"
    )

    gradio_node_path = subprocess.run(
        [node, "-e", "console.log(require.resolve('@gradio/preview'))"],
        cwd=Path(component_directory / "frontend"),
        check=False,
        capture_output=True,
    )

    if gradio_node_path.returncode != 0:
        raise ValueError(
            "Could not find `@gradio/preview`. Run `npm i -D @gradio/preview` in your frontend folder."
        )

    gradio_node_path = gradio_node_path.stdout.decode("utf-8").strip()

    proc = subprocess.Popen(
        [
            node,
            gradio_node_path,
            "--component-directory",
            component_directory,
            "--root",
            gradio_template_path,
            "--app",
            str(app),
            "--mode",
            "dev",
            "--host",
            host,
            "--python-path",
            python_path,
            "--gradio-path",
            gradio_path,
        ],
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
    )
    while True:
        proc.poll()
        text = proc.stdout.readline()  # type: ignore
        err = None
        if proc.stderr:
            err = proc.stderr.readline()

        text = (
            text.decode("utf-8")
            .replace("Changes detected in:", "[orange3]Changed detected in:[/]")
            .replace("Watching:", "[orange3]Watching:[/]")
            .replace("Running on local URL", "[orange3]Backend Server[/]")
        )

        if "[orange3]Watching:[/]" in text:
            text += f"'{str(component_directory / 'frontend').strip()}',"
        if "To create a public link" in text:
            continue
        print(text)
        if err:
            print(err.decode("utf-8"))

        if proc.returncode is not None:
            print("Backend server failed to launch. Exiting.")
            return