mirror of
https://github.com/gradio-app/gradio.git
synced 2025-03-25 12:10:31 +08:00
Remove Ruff and Uvicorn in Wasm env (#7744)
* Exclude `ruff` from the requirements list for Wasm env * Exclude `uvicorn` from the requirements list for Wasm env and fix the related modules not to try to import it when not used * add changeset * Fix tests * add changeset * Apply formatter * Remove a test case which became unnecessary in https://github.com/gradio-app/gradio/pull/5267, ref: https://github.com/gradio-app/gradio/pull/7744#issuecomment-2011332287 --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
This commit is contained in:
parent
2efb05ed99
commit
d831040032
6
.changeset/sweet-rocks-sing.md
Normal file
6
.changeset/sweet-rocks-sing.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
"@gradio/wasm": minor
|
||||
"gradio": minor
|
||||
---
|
||||
|
||||
feat:Remove Ruff and Uvicorn in Wasm env
|
@ -16,7 +16,7 @@ import huggingface_hub
|
||||
import pytest
|
||||
import uvicorn
|
||||
from fastapi import FastAPI
|
||||
from gradio.networking import Server
|
||||
from gradio.http_server import Server
|
||||
from huggingface_hub import HfFolder
|
||||
from huggingface_hub.utils import RepositoryNotFoundError
|
||||
|
||||
|
@ -2086,13 +2086,15 @@ Received outputs:
|
||||
)
|
||||
wasm_utils.register_app(app)
|
||||
else:
|
||||
from gradio import http_server
|
||||
|
||||
(
|
||||
server_name,
|
||||
server_port,
|
||||
local_url,
|
||||
app,
|
||||
server,
|
||||
) = networking.start_server(
|
||||
) = http_server.start_server(
|
||||
self,
|
||||
server_name,
|
||||
server_port,
|
||||
|
170
gradio/http_server.py
Normal file
170
gradio/http_server.py
Normal file
@ -0,0 +1,170 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import socket
|
||||
import threading
|
||||
import time
|
||||
from functools import partial
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import uvicorn
|
||||
from uvicorn.config import Config
|
||||
|
||||
from gradio.exceptions import ServerFailedToStartError
|
||||
from gradio.routes import App
|
||||
from gradio.utils import SourceFileReloader, watchfn
|
||||
|
||||
if TYPE_CHECKING: # Only import for type checking (to avoid circular imports).
|
||||
from gradio.blocks import Blocks
|
||||
|
||||
# By default, the local server will try to open on localhost, port 7860.
|
||||
# If that is not available, then it will try 7861, 7862, ... 7959.
|
||||
INITIAL_PORT_VALUE = int(os.getenv("GRADIO_SERVER_PORT", "7860"))
|
||||
TRY_NUM_PORTS = int(os.getenv("GRADIO_NUM_PORTS", "100"))
|
||||
LOCALHOST_NAME = os.getenv("GRADIO_SERVER_NAME", "127.0.0.1")
|
||||
|
||||
should_watch = bool(os.getenv("GRADIO_WATCH_DIRS", ""))
|
||||
GRADIO_WATCH_DIRS = (
|
||||
os.getenv("GRADIO_WATCH_DIRS", "").split(",") if should_watch else []
|
||||
)
|
||||
GRADIO_WATCH_MODULE_NAME = os.getenv("GRADIO_WATCH_MODULE_NAME", "app")
|
||||
GRADIO_WATCH_DEMO_NAME = os.getenv("GRADIO_WATCH_DEMO_NAME", "demo")
|
||||
GRADIO_WATCH_DEMO_PATH = os.getenv("GRADIO_WATCH_DEMO_PATH", "")
|
||||
|
||||
|
||||
class Server(uvicorn.Server):
|
||||
def __init__(
|
||||
self, config: Config, reloader: SourceFileReloader | None = None
|
||||
) -> None:
|
||||
self.running_app = config.app
|
||||
super().__init__(config)
|
||||
self.reloader = reloader
|
||||
if self.reloader:
|
||||
self.event = threading.Event()
|
||||
self.watch = partial(watchfn, self.reloader)
|
||||
|
||||
def install_signal_handlers(self):
|
||||
pass
|
||||
|
||||
def run_in_thread(self):
|
||||
self.thread = threading.Thread(target=self.run, daemon=True)
|
||||
if self.reloader:
|
||||
self.watch_thread = threading.Thread(target=self.watch, daemon=True)
|
||||
self.watch_thread.start()
|
||||
self.thread.start()
|
||||
start = time.time()
|
||||
while not self.started:
|
||||
time.sleep(1e-3)
|
||||
if time.time() - start > 5:
|
||||
raise ServerFailedToStartError(
|
||||
"Server failed to start. Please check that the port is available."
|
||||
)
|
||||
|
||||
def close(self):
|
||||
self.should_exit = True
|
||||
if self.reloader:
|
||||
self.reloader.stop()
|
||||
self.watch_thread.join()
|
||||
self.thread.join()
|
||||
|
||||
|
||||
def start_server(
|
||||
blocks: Blocks,
|
||||
server_name: str | None = None,
|
||||
server_port: int | None = None,
|
||||
ssl_keyfile: str | None = None,
|
||||
ssl_certfile: str | None = None,
|
||||
ssl_keyfile_password: str | None = None,
|
||||
app_kwargs: dict | None = None,
|
||||
) -> tuple[str, int, str, App, Server]:
|
||||
"""Launches a local server running the provided Interface
|
||||
Parameters:
|
||||
blocks: The Blocks object to run on the server
|
||||
server_name: to make app accessible on local network, set this to "0.0.0.0". Can be set by environment variable GRADIO_SERVER_NAME.
|
||||
server_port: will start gradio app on this port (if available). Can be set by environment variable GRADIO_SERVER_PORT.
|
||||
auth: If provided, username and password (or list of username-password tuples) required to access the Blocks. Can also provide function that takes username and password and returns True if valid login.
|
||||
ssl_keyfile: If a path to a file is provided, will use this as the private key file to create a local server running on https.
|
||||
ssl_certfile: If a path to a file is provided, will use this as the signed certificate for https. Needs to be provided if ssl_keyfile is provided.
|
||||
ssl_keyfile_password: If a password is provided, will use this with the ssl certificate for https.
|
||||
app_kwargs: Additional keyword arguments to pass to the gradio.routes.App constructor.
|
||||
|
||||
Returns:
|
||||
port: the port number the server is running on
|
||||
path_to_local_server: the complete address that the local server can be accessed at
|
||||
app: the FastAPI app object
|
||||
server: the server object that is a subclass of uvicorn.Server (used to close the server)
|
||||
"""
|
||||
if ssl_keyfile is not None and ssl_certfile is None:
|
||||
raise ValueError("ssl_certfile must be provided if ssl_keyfile is provided.")
|
||||
|
||||
server_name = server_name or LOCALHOST_NAME
|
||||
url_host_name = "localhost" if server_name == "0.0.0.0" else server_name
|
||||
|
||||
# Strip IPv6 brackets from the address if they exist.
|
||||
# This is needed as http://[::1]:port/ is a valid browser address,
|
||||
# but not a valid IPv6 address, so asyncio will throw an exception.
|
||||
if server_name.startswith("[") and server_name.endswith("]"):
|
||||
host = server_name[1:-1]
|
||||
else:
|
||||
host = server_name
|
||||
|
||||
app = App.create_app(blocks, app_kwargs=app_kwargs)
|
||||
|
||||
server_ports = (
|
||||
[server_port]
|
||||
if server_port is not None
|
||||
else range(INITIAL_PORT_VALUE, INITIAL_PORT_VALUE + TRY_NUM_PORTS)
|
||||
)
|
||||
|
||||
for port in server_ports:
|
||||
try:
|
||||
# The fastest way to check if a port is available is to try to bind to it with socket.
|
||||
# If the port is not available, socket will throw an OSError.
|
||||
s = socket.socket()
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
# Really, we should be checking if (server_name, server_port) is available, but
|
||||
# socket.bind() doesn't seem to throw an OSError with ipv6 addresses, based on my testing.
|
||||
# Instead, we just check if the port is available on localhost.
|
||||
s.bind((LOCALHOST_NAME, port))
|
||||
s.close()
|
||||
|
||||
# To avoid race conditions, so we also check if the port by trying to start the uvicorn server.
|
||||
# If the port is not available, this will throw a ServerFailedToStartError.
|
||||
config = uvicorn.Config(
|
||||
app=app,
|
||||
port=port,
|
||||
host=host,
|
||||
log_level="warning",
|
||||
ssl_keyfile=ssl_keyfile,
|
||||
ssl_certfile=ssl_certfile,
|
||||
ssl_keyfile_password=ssl_keyfile_password,
|
||||
)
|
||||
reloader = None
|
||||
if GRADIO_WATCH_DIRS:
|
||||
change_event = threading.Event()
|
||||
app.change_event = change_event
|
||||
reloader = SourceFileReloader(
|
||||
app=app,
|
||||
watch_dirs=GRADIO_WATCH_DIRS,
|
||||
watch_module_name=GRADIO_WATCH_MODULE_NAME,
|
||||
demo_name=GRADIO_WATCH_DEMO_NAME,
|
||||
stop_event=threading.Event(),
|
||||
change_event=change_event,
|
||||
demo_file=GRADIO_WATCH_DEMO_PATH,
|
||||
)
|
||||
server = Server(config=config, reloader=reloader)
|
||||
server.run_in_thread()
|
||||
break
|
||||
except (OSError, ServerFailedToStartError):
|
||||
pass
|
||||
else:
|
||||
raise OSError(
|
||||
f"Cannot find empty port in range: {min(server_ports)}-{max(server_ports)}. You can specify a different port by setting the GRADIO_SERVER_PORT environment variable or passing the `server_port` parameter to `launch()`."
|
||||
)
|
||||
|
||||
if ssl_keyfile is not None:
|
||||
path_to_local_server = f"https://{url_host_name}:{port}/"
|
||||
else:
|
||||
path_to_local_server = f"http://{url_host_name}:{port}/"
|
||||
|
||||
return server_name, port, path_to_local_server, app, server
|
@ -8,7 +8,7 @@ except ImportError:
|
||||
pass
|
||||
|
||||
import gradio as gr
|
||||
from gradio.networking import App
|
||||
from gradio.routes import App
|
||||
from gradio.utils import BaseReloader
|
||||
|
||||
|
||||
|
@ -5,218 +5,17 @@ creating tunnels.
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import socket
|
||||
import threading
|
||||
import time
|
||||
import warnings
|
||||
from functools import partial
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import httpx
|
||||
import uvicorn
|
||||
from uvicorn.config import Config
|
||||
|
||||
from gradio.exceptions import ServerFailedToStartError
|
||||
from gradio.routes import App
|
||||
from gradio.routes import App # HACK: to avoid circular import # noqa: F401
|
||||
from gradio.tunneling import Tunnel
|
||||
from gradio.utils import SourceFileReloader, watchfn
|
||||
|
||||
if TYPE_CHECKING: # Only import for type checking (to avoid circular imports).
|
||||
from gradio.blocks import Blocks
|
||||
|
||||
# By default, the local server will try to open on localhost, port 7860.
|
||||
# If that is not available, then it will try 7861, 7862, ... 7959.
|
||||
INITIAL_PORT_VALUE = int(os.getenv("GRADIO_SERVER_PORT", "7860"))
|
||||
TRY_NUM_PORTS = int(os.getenv("GRADIO_NUM_PORTS", "100"))
|
||||
LOCALHOST_NAME = os.getenv("GRADIO_SERVER_NAME", "127.0.0.1")
|
||||
GRADIO_API_SERVER = "https://api.gradio.app/v2/tunnel-request"
|
||||
GRADIO_SHARE_SERVER_ADDRESS = os.getenv("GRADIO_SHARE_SERVER_ADDRESS")
|
||||
|
||||
should_watch = bool(os.getenv("GRADIO_WATCH_DIRS", ""))
|
||||
GRADIO_WATCH_DIRS = (
|
||||
os.getenv("GRADIO_WATCH_DIRS", "").split(",") if should_watch else []
|
||||
)
|
||||
GRADIO_WATCH_MODULE_NAME = os.getenv("GRADIO_WATCH_MODULE_NAME", "app")
|
||||
GRADIO_WATCH_DEMO_NAME = os.getenv("GRADIO_WATCH_DEMO_NAME", "demo")
|
||||
GRADIO_WATCH_DEMO_PATH = os.getenv("GRADIO_WATCH_DEMO_PATH", "")
|
||||
|
||||
|
||||
class Server(uvicorn.Server):
|
||||
def __init__(
|
||||
self, config: Config, reloader: SourceFileReloader | None = None
|
||||
) -> None:
|
||||
self.running_app = config.app
|
||||
super().__init__(config)
|
||||
self.reloader = reloader
|
||||
if self.reloader:
|
||||
self.event = threading.Event()
|
||||
self.watch = partial(watchfn, self.reloader)
|
||||
|
||||
def install_signal_handlers(self):
|
||||
pass
|
||||
|
||||
def run_in_thread(self):
|
||||
self.thread = threading.Thread(target=self.run, daemon=True)
|
||||
if self.reloader:
|
||||
self.watch_thread = threading.Thread(target=self.watch, daemon=True)
|
||||
self.watch_thread.start()
|
||||
self.thread.start()
|
||||
start = time.time()
|
||||
while not self.started:
|
||||
time.sleep(1e-3)
|
||||
if time.time() - start > 5:
|
||||
raise ServerFailedToStartError(
|
||||
"Server failed to start. Please check that the port is available."
|
||||
)
|
||||
|
||||
def close(self):
|
||||
self.should_exit = True
|
||||
if self.reloader:
|
||||
self.reloader.stop()
|
||||
self.watch_thread.join()
|
||||
self.thread.join()
|
||||
|
||||
|
||||
def get_first_available_port(initial: int, final: int) -> int:
|
||||
"""
|
||||
Gets the first open port in a specified range of port numbers
|
||||
Parameters:
|
||||
initial: the initial value in the range of port numbers
|
||||
final: final (exclusive) value in the range of port numbers, should be greater than `initial`
|
||||
Returns:
|
||||
port: the first open port in the range
|
||||
"""
|
||||
for port in range(initial, final):
|
||||
try:
|
||||
s = socket.socket() # create a socket object
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
s.bind((LOCALHOST_NAME, port)) # Bind to the port
|
||||
s.close()
|
||||
return port
|
||||
except OSError:
|
||||
pass
|
||||
raise OSError(
|
||||
f"All ports from {initial} to {final - 1} are in use. Please close a port."
|
||||
)
|
||||
|
||||
|
||||
def configure_app(app: App, blocks: Blocks) -> App:
|
||||
auth = blocks.auth
|
||||
if auth is not None:
|
||||
if not callable(auth):
|
||||
app.auth = {account[0]: account[1] for account in auth}
|
||||
else:
|
||||
app.auth = auth
|
||||
else:
|
||||
app.auth = None
|
||||
app.blocks = blocks
|
||||
app.cwd = os.getcwd()
|
||||
app.favicon_path = blocks.favicon_path
|
||||
app.tokens = {}
|
||||
return app
|
||||
|
||||
|
||||
def start_server(
|
||||
blocks: Blocks,
|
||||
server_name: str | None = None,
|
||||
server_port: int | None = None,
|
||||
ssl_keyfile: str | None = None,
|
||||
ssl_certfile: str | None = None,
|
||||
ssl_keyfile_password: str | None = None,
|
||||
app_kwargs: dict | None = None,
|
||||
) -> tuple[str, int, str, App, Server]:
|
||||
"""Launches a local server running the provided Interface
|
||||
Parameters:
|
||||
blocks: The Blocks object to run on the server
|
||||
server_name: to make app accessible on local network, set this to "0.0.0.0". Can be set by environment variable GRADIO_SERVER_NAME.
|
||||
server_port: will start gradio app on this port (if available). Can be set by environment variable GRADIO_SERVER_PORT.
|
||||
auth: If provided, username and password (or list of username-password tuples) required to access the Blocks. Can also provide function that takes username and password and returns True if valid login.
|
||||
ssl_keyfile: If a path to a file is provided, will use this as the private key file to create a local server running on https.
|
||||
ssl_certfile: If a path to a file is provided, will use this as the signed certificate for https. Needs to be provided if ssl_keyfile is provided.
|
||||
ssl_keyfile_password: If a password is provided, will use this with the ssl certificate for https.
|
||||
app_kwargs: Additional keyword arguments to pass to the gradio.routes.App constructor.
|
||||
|
||||
Returns:
|
||||
port: the port number the server is running on
|
||||
path_to_local_server: the complete address that the local server can be accessed at
|
||||
app: the FastAPI app object
|
||||
server: the server object that is a subclass of uvicorn.Server (used to close the server)
|
||||
"""
|
||||
if ssl_keyfile is not None and ssl_certfile is None:
|
||||
raise ValueError("ssl_certfile must be provided if ssl_keyfile is provided.")
|
||||
|
||||
server_name = server_name or LOCALHOST_NAME
|
||||
url_host_name = "localhost" if server_name == "0.0.0.0" else server_name
|
||||
|
||||
# Strip IPv6 brackets from the address if they exist.
|
||||
# This is needed as http://[::1]:port/ is a valid browser address,
|
||||
# but not a valid IPv6 address, so asyncio will throw an exception.
|
||||
if server_name.startswith("[") and server_name.endswith("]"):
|
||||
host = server_name[1:-1]
|
||||
else:
|
||||
host = server_name
|
||||
|
||||
app = App.create_app(blocks, app_kwargs=app_kwargs)
|
||||
|
||||
server_ports = (
|
||||
[server_port]
|
||||
if server_port is not None
|
||||
else range(INITIAL_PORT_VALUE, INITIAL_PORT_VALUE + TRY_NUM_PORTS)
|
||||
)
|
||||
|
||||
for port in server_ports:
|
||||
try:
|
||||
# The fastest way to check if a port is available is to try to bind to it with socket.
|
||||
# If the port is not available, socket will throw an OSError.
|
||||
s = socket.socket()
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
# Really, we should be checking if (server_name, server_port) is available, but
|
||||
# socket.bind() doesn't seem to throw an OSError with ipv6 addresses, based on my testing.
|
||||
# Instead, we just check if the port is available on localhost.
|
||||
s.bind((LOCALHOST_NAME, port))
|
||||
s.close()
|
||||
|
||||
# To avoid race conditions, so we also check if the port by trying to start the uvicorn server.
|
||||
# If the port is not available, this will throw a ServerFailedToStartError.
|
||||
config = uvicorn.Config(
|
||||
app=app,
|
||||
port=port,
|
||||
host=host,
|
||||
log_level="warning",
|
||||
ssl_keyfile=ssl_keyfile,
|
||||
ssl_certfile=ssl_certfile,
|
||||
ssl_keyfile_password=ssl_keyfile_password,
|
||||
)
|
||||
reloader = None
|
||||
if GRADIO_WATCH_DIRS:
|
||||
change_event = threading.Event()
|
||||
app.change_event = change_event
|
||||
reloader = SourceFileReloader(
|
||||
app=app,
|
||||
watch_dirs=GRADIO_WATCH_DIRS,
|
||||
watch_module_name=GRADIO_WATCH_MODULE_NAME,
|
||||
demo_name=GRADIO_WATCH_DEMO_NAME,
|
||||
stop_event=threading.Event(),
|
||||
change_event=change_event,
|
||||
demo_file=GRADIO_WATCH_DEMO_PATH,
|
||||
)
|
||||
server = Server(config=config, reloader=reloader)
|
||||
server.run_in_thread()
|
||||
break
|
||||
except (OSError, ServerFailedToStartError):
|
||||
pass
|
||||
else:
|
||||
raise OSError(
|
||||
f"Cannot find empty port in range: {min(server_ports)}-{max(server_ports)}. You can specify a different port by setting the GRADIO_SERVER_PORT environment variable or passing the `server_port` parameter to `launch()`."
|
||||
)
|
||||
|
||||
if ssl_keyfile is not None:
|
||||
path_to_local_server = f"https://{url_host_name}:{port}/"
|
||||
else:
|
||||
path_to_local_server = f"http://{url_host_name}:{port}/"
|
||||
|
||||
return server_name, port, path_to_local_server, app, server
|
||||
|
||||
|
||||
def setup_tunnel(
|
||||
local_host: str, local_port: int, share_token: str, share_server_address: str | None
|
||||
|
@ -80,7 +80,6 @@ async function initializeEnvironment(
|
||||
await micropip.install(["markdown-it-py[linkify]~=2.2.0"]); // On 3rd June 2023, markdown-it-py 3.0.0 has been released. The `gradio` package depends on its `>=2.0.0` version so its 3.x will be resolved. However, it conflicts with `mdit-py-plugins`'s dependency `markdown-it-py >=1.0.0,<3.0.0` and micropip currently can't resolve it. So we explicitly install the compatible version of the library here.
|
||||
await micropip.install(["anyio==3.*"]); // `fastapi` depends on `anyio>=3.4.0,<5` so its 4.* can be installed, but it conflicts with the anyio version `httpx` depends on, `==3.*`. Seems like micropip can't resolve it for now, so we explicitly install the compatible version of the library here.
|
||||
await micropip.add_mock_package("pydantic", "2.4.2"); // PydanticV2 is not supported on Pyodide yet. Mock it here for installing the `gradio` package to pass the version check. Then, install PydanticV1 below.
|
||||
await micropip.add_mock_package("ruff", "0.2.2"); // `ruff` was added to the requirements of `gradio` for the custom components (https://github.com/gradio-app/gradio/pull/7030), but it's not working on PYodide yet. Also Lite doesn't need it, so mock it here for installing the `gradio` package to pass the version check.
|
||||
await micropip.install.callKwargs(gradioWheelUrls, {
|
||||
keep_going: true
|
||||
});
|
||||
|
@ -20,7 +20,7 @@ pydub
|
||||
pyyaml>=5.0,<7.0
|
||||
semantic_version~=2.0
|
||||
typing_extensions~=4.0
|
||||
uvicorn>=0.14.0
|
||||
uvicorn>=0.14.0; sys.platform != 'emscripten'
|
||||
typer[all]>=0.9,<1.0
|
||||
tomlkit==0.12.0
|
||||
ruff>=0.2.2
|
||||
ruff>=0.2.2; sys.platform != 'emscripten'
|
||||
|
@ -16,7 +16,6 @@ from unittest.mock import patch
|
||||
import gradio_client as grc
|
||||
import numpy as np
|
||||
import pytest
|
||||
import uvicorn
|
||||
from fastapi.testclient import TestClient
|
||||
from gradio_client import Client, media_data
|
||||
from PIL import Image
|
||||
@ -25,7 +24,6 @@ import gradio as gr
|
||||
from gradio.data_classes import GradioModel, GradioRootModel
|
||||
from gradio.events import SelectData
|
||||
from gradio.exceptions import DuplicateBlockError
|
||||
from gradio.networking import Server, get_first_available_port
|
||||
from gradio.utils import assert_configs_are_equivalent_besides_ids
|
||||
|
||||
pytest_plugins = ("pytest_asyncio",)
|
||||
@ -345,29 +343,6 @@ class TestBlocksMethods:
|
||||
if i == 2:
|
||||
assert dependency["types"] == {"continuous": True, "generator": True}
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_run_without_launching(self):
|
||||
"""Test that we can start the app and use queue without calling .launch().
|
||||
|
||||
This is essentially what the 'gradio' reload mode does
|
||||
"""
|
||||
|
||||
port = get_first_available_port(7860, 7870)
|
||||
|
||||
io = gr.Interface(lambda s: s, gr.Textbox(), gr.Textbox()).queue()
|
||||
|
||||
config = uvicorn.Config(app=io.app, port=port, log_level="warning")
|
||||
|
||||
server = Server(config=config)
|
||||
server.run_in_thread()
|
||||
|
||||
try:
|
||||
client = grc.Client(f"http://localhost:{port}")
|
||||
result = client.predict("Victor", api_name="/predict")
|
||||
assert result == "Victor"
|
||||
finally:
|
||||
server.close()
|
||||
|
||||
@patch(
|
||||
"gradio.themes.ThemeClass.from_hub",
|
||||
side_effect=ValueError("Something went wrong!"),
|
||||
|
29
test/test_http_server.py
Normal file
29
test/test_http_server.py
Normal file
@ -0,0 +1,29 @@
|
||||
import urllib.parse
|
||||
|
||||
import pytest
|
||||
|
||||
import gradio as gr
|
||||
from gradio import http_server
|
||||
|
||||
|
||||
class TestStartServer:
|
||||
# Test IPv4 and IPv6 hostnames as they would be passed from --server-name.
|
||||
@pytest.mark.parametrize("host", ["127.0.0.1", "[::1]"])
|
||||
def test_start_server(self, host):
|
||||
io = gr.Interface(lambda x: x, "number", "number")
|
||||
io.favicon_path = None
|
||||
io.config = io.get_config_file()
|
||||
io.show_error = True
|
||||
io.flagging_callback.setup(gr.Number(), io.flagging_dir)
|
||||
io.auth = None
|
||||
|
||||
_, _, local_path, _, server = http_server.start_server(io)
|
||||
url = urllib.parse.urlparse(local_path)
|
||||
assert url.scheme == "http"
|
||||
assert url.port is not None
|
||||
assert (
|
||||
http_server.INITIAL_PORT_VALUE
|
||||
<= url.port
|
||||
<= http_server.INITIAL_PORT_VALUE + http_server.TRY_NUM_PORTS
|
||||
)
|
||||
server.close()
|
@ -1,39 +1,14 @@
|
||||
"""Contains tests for networking.py and app.py"""
|
||||
|
||||
import os
|
||||
import urllib
|
||||
import warnings
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
import gradio as gr
|
||||
from gradio import Interface, networking
|
||||
|
||||
os.environ["GRADIO_ANALYTICS_ENABLED"] = "False"
|
||||
|
||||
|
||||
class TestPort:
|
||||
def test_port_is_in_range(self):
|
||||
start = 7860
|
||||
end = 7960
|
||||
try:
|
||||
port = networking.get_first_available_port(start, end)
|
||||
assert start <= port <= end
|
||||
except OSError:
|
||||
warnings.warn("Unable to test, no ports available")
|
||||
|
||||
def test_same_port_is_returned(self):
|
||||
start = 7860
|
||||
end = 7960
|
||||
try:
|
||||
port1 = networking.get_first_available_port(start, end)
|
||||
port2 = networking.get_first_available_port(start, end)
|
||||
assert port1 == port2
|
||||
except OSError:
|
||||
warnings.warn("Unable to test, no ports available")
|
||||
|
||||
|
||||
class TestInterfaceErrors:
|
||||
def test_processing_error(self):
|
||||
io = Interface(lambda x: 1 / x, "number", "number")
|
||||
@ -53,29 +28,6 @@ class TestInterfaceErrors:
|
||||
io.close()
|
||||
|
||||
|
||||
class TestStartServer:
|
||||
# Test IPv4 and IPv6 hostnames as they would be passed from --server-name.
|
||||
@pytest.mark.parametrize("host", ["127.0.0.1", "[::1]"])
|
||||
def test_start_server(self, host):
|
||||
io = Interface(lambda x: x, "number", "number")
|
||||
io.favicon_path = None
|
||||
io.config = io.get_config_file()
|
||||
io.show_error = True
|
||||
io.flagging_callback.setup(gr.Number(), io.flagging_dir)
|
||||
io.auth = None
|
||||
io.host = host
|
||||
|
||||
port = networking.get_first_available_port(
|
||||
networking.INITIAL_PORT_VALUE,
|
||||
networking.INITIAL_PORT_VALUE + networking.TRY_NUM_PORTS,
|
||||
)
|
||||
_, _, local_path, _, server = networking.start_server(io, server_port=port)
|
||||
url = urllib.parse.urlparse(local_path)
|
||||
assert url.scheme == "http"
|
||||
assert url.port == port
|
||||
server.close()
|
||||
|
||||
|
||||
class TestURLs:
|
||||
def test_url_ok(self):
|
||||
res = networking.url_ok("https://www.gradio.app")
|
||||
|
@ -7,7 +7,7 @@ import pytest
|
||||
import gradio
|
||||
import gradio as gr
|
||||
from gradio.cli.commands.reload import _setup_config
|
||||
from gradio.networking import Server
|
||||
from gradio.http_server import Server
|
||||
|
||||
|
||||
def build_demo():
|
||||
|
Loading…
x
Reference in New Issue
Block a user