adf0d17497
publish / version_or_publish (push) Waiting to run
storybook-build / changes (push) Waiting to run
storybook-build / :storybook-build (push) Blocked by required conditions
Sync Gradio Skills to Hugging Face / sync-skills (push) Waiting to run
functional / changes (push) Waiting to run
functional / build-frontend (push) Blocked by required conditions
functional / functional-test-SSR=false (push) Blocked by required conditions
functional / functional-reload (push) Blocked by required conditions
functional / functional-test-SSR=true (push) Blocked by required conditions
hygiene / hygiene-test (push) Waiting to run
python / changes (push) Waiting to run
python / build (push) Blocked by required conditions
python / test-ubuntu-latest-flaky (push) Blocked by required conditions
python / test-ubuntu-latest-not-flaky (push) Blocked by required conditions
python / test-windows-latest-flaky (push) Blocked by required conditions
python / test-windows-latest-not-flaky (push) Blocked by required conditions
js / changes (push) Waiting to run
js / js-test (push) Blocked by required conditions
docs-build / changes (push) Waiting to run
docs-build / docs-build (push) Blocked by required conditions
docs-build / website-build (push) Blocked by required conditions
179 lines
6.4 KiB
Python
179 lines
6.4 KiB
Python
import inspect
|
|
import os
|
|
|
|
import numpy as np
|
|
import pandas as pd
|
|
import pytest
|
|
from gradio_client import utils as client_utils
|
|
|
|
import gradio as gr
|
|
from gradio import processing_utils
|
|
from gradio.components.base import Component
|
|
from gradio.data_classes import GradioModel, GradioRootModel
|
|
from gradio.templates import TextArea
|
|
|
|
os.environ["GRADIO_ANALYTICS_ENABLED"] = "False"
|
|
|
|
|
|
class TestGettingComponents:
|
|
def test_component_function(self):
|
|
assert isinstance(gr.components.component("textarea", render=False), TextArea)
|
|
|
|
@pytest.mark.parametrize(
|
|
"component, render, unrender, should_be_rendered",
|
|
[
|
|
(gr.Textbox(render=True), False, True, False),
|
|
(gr.Textbox(render=False), False, False, False),
|
|
(gr.Textbox(render=False), True, False, True),
|
|
("textbox", False, False, False),
|
|
("textbox", True, False, True),
|
|
],
|
|
)
|
|
def test_get_component_instance_rendering(
|
|
self, component, render, unrender, should_be_rendered
|
|
):
|
|
with gr.Blocks():
|
|
textbox = gr.components.get_component_instance(
|
|
component, render=render, unrender=unrender
|
|
)
|
|
assert textbox.is_rendered == should_be_rendered
|
|
|
|
|
|
class TestNames:
|
|
# This test ensures that `components.get_component_instance()` works correctly when instantiating from components
|
|
def test_no_duplicate_uncased_names(self, io_components):
|
|
unique_subclasses_uncased = {s.__name__.lower() for s in io_components}
|
|
assert len(io_components) == len(unique_subclasses_uncased)
|
|
|
|
|
|
def test_dataframe_process_example_converts_dataframes():
|
|
df_comp = gr.Dataframe()
|
|
assert df_comp.process_example(
|
|
pd.DataFrame({"a": [1, 2, 3, 4], "b": [5, 6, 7, 8]})
|
|
) == [
|
|
[1, 5],
|
|
[2, 6],
|
|
[3, 7],
|
|
[4, 8],
|
|
]
|
|
assert df_comp.process_example(np.array([[1, 2], [3, 4.0]])) == [
|
|
[1.0, 2.0],
|
|
[3.0, 4.0],
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize("component", [gr.Model3D, gr.File, gr.Audio])
|
|
def test_process_example_returns_file_basename(component):
|
|
component = component()
|
|
assert (
|
|
component.process_example("/home/freddy/sources/example.ext") == "example.ext"
|
|
)
|
|
assert component.process_example(None) == ""
|
|
|
|
|
|
def test_component_class_ids():
|
|
button_id = gr.Button().component_class_id
|
|
textbox_id = gr.Textbox().component_class_id
|
|
json_id = gr.JSON().component_class_id
|
|
mic_id = gr.Mic().component_class_id
|
|
microphone_id = gr.Microphone().component_class_id
|
|
audio_id = gr.Audio().component_class_id
|
|
|
|
assert button_id == gr.Button().component_class_id
|
|
assert textbox_id == gr.Textbox().component_class_id
|
|
assert json_id == gr.JSON().component_class_id
|
|
assert mic_id == gr.Mic().component_class_id
|
|
assert microphone_id == gr.Microphone().component_class_id
|
|
assert audio_id == gr.Audio().component_class_id
|
|
assert mic_id == microphone_id
|
|
|
|
# Make sure that the ids are unique
|
|
assert len({button_id, textbox_id, json_id, microphone_id, audio_id}) == 5
|
|
|
|
|
|
def test_constructor_args():
|
|
assert gr.Textbox(max_lines=314).constructor_args == {"max_lines": 314}
|
|
assert gr.LoginButton(visible=False, value="Log in please").constructor_args == {
|
|
"visible": False,
|
|
"value": "Log in please",
|
|
}
|
|
|
|
|
|
def test_template_component_configs(io_components):
|
|
"""
|
|
This test ensures that every "template" (the classes defined in gradio/template.py)
|
|
has all of the arguments that its parent class has. E.g. the constructor of the `Sketchpad`
|
|
class should have all of the arguments that the constructor of `ImageEditor` has
|
|
"""
|
|
template_components = [c for c in io_components if getattr(c, "is_template", False)]
|
|
for component in template_components:
|
|
component_parent_class = inspect.getmro(component)[1]
|
|
template_config = component().get_config()
|
|
parent_config = component_parent_class().get_config()
|
|
parent_keys = set(parent_config.keys())
|
|
template_keys = set(template_config.keys())
|
|
missing_keys = parent_keys - template_keys
|
|
if missing_keys:
|
|
raise AssertionError(
|
|
f"Template {component.__name__} is missing keys from parent {component_parent_class.__name__}: {missing_keys}"
|
|
)
|
|
|
|
|
|
def test_component_example_values(io_components):
|
|
for component in io_components:
|
|
if component in [gr.BarPlot, gr.LinePlot, gr.ScatterPlot]:
|
|
c: Component = component(x="x", y="y")
|
|
else:
|
|
c: Component = component()
|
|
c.postprocess(c.example_value())
|
|
|
|
|
|
def test_component_example_payloads(io_components):
|
|
for component in io_components:
|
|
if issubclass(component, gr.components.NativePlot):
|
|
c: Component = component(x="x", y="y")
|
|
elif component == gr.FileExplorer:
|
|
c: Component = component(root_dir="gradio")
|
|
else:
|
|
c: Component = component()
|
|
data = c.example_payload()
|
|
data = client_utils.synchronize_async(
|
|
processing_utils.async_move_files_to_cache,
|
|
data,
|
|
c,
|
|
check_in_upload_folder=False,
|
|
)
|
|
if getattr(c, "data_model", None) and data is not None:
|
|
if issubclass(c.data_model, GradioModel): # type: ignore
|
|
data = c.data_model(**data) # type: ignore
|
|
elif issubclass(c.data_model, GradioRootModel): # type: ignore
|
|
data = c.data_model(root=data) # type: ignore
|
|
c.preprocess(data) # type: ignore
|
|
|
|
|
|
def test_all_io_components_are_pickleable(io_components):
|
|
import pickle
|
|
|
|
for component in io_components:
|
|
if component in [gr.BarPlot, gr.LinePlot, gr.ScatterPlot]:
|
|
c: Component = component(x="x", y="y")
|
|
elif component == gr.FileExplorer:
|
|
c: Component = component(root_dir="gradio")
|
|
else:
|
|
c: Component = component()
|
|
pickled = pickle.dumps(c)
|
|
unpickled = pickle.loads(pickled)
|
|
assert c.get_config() == unpickled.get_config()
|
|
|
|
|
|
def test_all_components_have_change_event(io_components):
|
|
"""
|
|
Every component has a `value` that can be set programmatically (e.g. a
|
|
Button's value is its label), so every component should expose a `.change()`
|
|
event listener that can be wired up without erroring.
|
|
See https://github.com/gradio-app/gradio/issues/5309.
|
|
"""
|
|
for component in io_components:
|
|
with gr.Blocks():
|
|
component().change(lambda: None)
|