2
Tests for all of the components defined in components.py. Tests are divided into two types:
3
1. test_component_functions() are unit tests that check essential functions of a component, the functions that are checked are documented in the docstring.
4
2. test_in_interface() are functional tests that check a component's functionalities inside an Interface. Please do not use Interface.launch() in this file, as it slow downs the tests.
13
from copy import deepcopy
14
from difflib import SequenceMatcher
15
from pathlib import Path
16
from unittest.mock import MagicMock, patch
23
from gradio_client import media_data
24
from gradio_client import utils as client_utils
25
from gradio_pdf import PDF
26
from scipy.io import wavfile
29
from typing import cast
31
from typing import cast
34
from gradio import processing_utils, utils
35
from gradio.components.base import Component
36
from gradio.components.dataframe import DataframeData
37
from gradio.components.file_explorer import FileExplorerData
38
from gradio.components.image_editor import EditorData
39
from gradio.components.video import VideoData
40
from gradio.data_classes import FileData, GradioModel, GradioRootModel, ListFiles
42
os.environ["GRADIO_ANALYTICS_ENABLED"] = "False"
45
class TestGettingComponents:
46
def test_component_function(self):
48
gr.components.component("textarea", render=False), gr.templates.TextArea
51
@pytest.mark.parametrize(
52
"component, render, unrender, should_be_rendered",
54
(gr.Textbox(render=True), False, True, False),
55
(gr.Textbox(render=False), False, False, False),
56
(gr.Textbox(render=False), True, False, True),
57
("textbox", False, False, False),
58
("textbox", True, False, True),
61
def test_get_component_instance_rendering(
62
self, component, render, unrender, should_be_rendered
65
textbox = gr.components.get_component_instance(
66
component, render=render, unrender=unrender
68
assert textbox.is_rendered == should_be_rendered
72
def test_component_functions(self):
74
Preprocess, postprocess, serialize, tokenize, get_config
76
text_input = gr.Textbox()
77
assert text_input.preprocess("Hello World!") == "Hello World!"
78
assert text_input.postprocess("Hello World!") == "Hello World!"
79
assert text_input.postprocess(None) is None
80
assert text_input.postprocess("Ali") == "Ali"
81
assert text_input.postprocess(2) == "2"
82
assert text_input.postprocess(2.14) == "2.14"
83
assert text_input.get_config() == {
89
"show_copy_button": False,
104
"_selectable": False,
110
async def test_in_interface_as_input(self):
114
iface = gr.Interface(lambda x: x[::-1], "textbox", "textbox")
115
assert iface("Hello") == "olleH"
117
def test_in_interface_as_output(self):
122
iface = gr.Interface(lambda x: x[-1], "textbox", gr.Textbox())
123
assert iface("Hello") == "o"
124
iface = gr.Interface(lambda x: x / 2, "number", gr.Textbox())
125
assert iface(10) == "5.0"
127
def test_static(self):
131
component = gr.Textbox("abc")
132
assert component.get_config().get("value") == "abc"
134
def test_override_template(self):
138
component = gr.TextArea(value="abc")
139
assert component.get_config().get("value") == "abc"
140
assert component.get_config().get("lines") == 7
141
component = gr.TextArea(value="abc", lines=4)
142
assert component.get_config().get("value") == "abc"
143
assert component.get_config().get("lines") == 4
145
def test_faulty_type(self):
147
ValueError, match='`type` must be one of "text", "password", or "email".'
149
gr.Textbox(type="boo")
151
def test_max_lines(self):
152
assert gr.Textbox(type="password").get_config().get("max_lines") == 1
153
assert gr.Textbox(type="email").get_config().get("max_lines") == 1
154
assert gr.Textbox(type="text").get_config().get("max_lines") == 20
155
assert gr.Textbox().get_config().get("max_lines") == 20
159
def test_component_functions(self):
161
Preprocess, postprocess, serialize, get_config
164
numeric_input = gr.Number(elem_id="num", elem_classes="first")
165
assert numeric_input.preprocess(3) == 3.0
166
assert numeric_input.preprocess(None) is None
167
assert numeric_input.postprocess(3) == 3
168
assert numeric_input.postprocess(3) == 3.0
169
assert numeric_input.postprocess(2.14) == 2.14
170
assert numeric_input.postprocess(None) is None
171
assert numeric_input.get_config() == {
183
"elem_classes": ["first"],
189
"_selectable": False,
192
def test_component_functions_integer(self):
194
Preprocess, postprocess, serialize, get_template_context
197
numeric_input = gr.Number(precision=0, value=42)
198
assert numeric_input.preprocess(3) == 3
199
assert numeric_input.preprocess(None) is None
200
assert numeric_input.postprocess(3) == 3
201
assert numeric_input.postprocess(3) == 3
202
assert numeric_input.postprocess(2.85) == 3
203
assert numeric_input.postprocess(None) is None
204
assert numeric_input.get_config() == {
222
"_selectable": False,
225
def test_component_functions_precision(self):
227
Preprocess, postprocess, serialize, get_template_context
230
numeric_input = gr.Number(precision=2, value=42.3428)
231
assert numeric_input.preprocess(3.231241) == 3.23
232
assert numeric_input.preprocess(None) is None
233
assert numeric_input.postprocess(-42.1241) == -42.12
234
assert numeric_input.postprocess(5.6784) == 5.68
235
assert numeric_input.postprocess(2.1421) == 2.14
236
assert numeric_input.postprocess(None) is None
238
def test_precision_none_with_integer(self):
240
Preprocess, postprocess
242
numeric_input = gr.Number(precision=None)
243
assert numeric_input.preprocess(5) == 5
244
assert isinstance(numeric_input.preprocess(5), int)
245
assert numeric_input.postprocess(5) == 5
246
assert isinstance(numeric_input.postprocess(5), int)
248
def test_precision_none_with_float(self):
250
Preprocess, postprocess
252
numeric_input = gr.Number(value=5.5, precision=None)
253
assert numeric_input.preprocess(5.5) == 5.5
254
assert isinstance(numeric_input.preprocess(5.5), float)
255
assert numeric_input.postprocess(5.5) == 5.5
256
assert isinstance(numeric_input.postprocess(5.5), float)
258
def test_in_interface_as_input(self):
262
iface = gr.Interface(lambda x: x**2, "number", "textbox")
263
assert iface(2) == "4"
265
def test_precision_0_in_interface(self):
269
iface = gr.Interface(lambda x: x**2, gr.Number(precision=0), "textbox")
270
assert iface(2) == "4"
272
def test_in_interface_as_output(self):
276
iface = gr.Interface(lambda x: int(x) ** 2, "textbox", "number")
277
assert iface(2) == 4.0
279
def test_static(self):
283
component = gr.Number()
284
assert component.get_config().get("value") is None
285
component = gr.Number(3)
286
assert component.get_config().get("value") == 3.0
290
def test_component_functions(self):
292
Preprocess, postprocess, serialize, get_config
294
slider_input = gr.Slider()
295
assert slider_input.preprocess(3.0) == 3.0
296
assert slider_input.postprocess(3) == 3
297
assert slider_input.postprocess(3) == 3
298
assert slider_input.postprocess(None) == 0
300
slider_input = gr.Slider(10, 20, value=15, step=1, label="Slide Your Input")
301
assert slider_input.get_config() == {
308
"label": "Slide Your Input",
318
"_selectable": False,
321
def test_in_interface(self):
325
iface = gr.Interface(lambda x: x**2, "slider", "textbox")
326
assert iface(2) == "4"
328
def test_static(self):
332
component = gr.Slider(0, 100, 5)
333
assert component.get_config().get("value") == 5
334
component = gr.Slider(0, 100, None)
335
assert component.get_config().get("value") == 0
337
@patch("gradio.Slider.get_random_value", return_value=7)
338
def test_slider_get_random_value_on_load(self, mock_get_random_value):
339
slider = gr.Slider(minimum=-5, maximum=10, randomize=True)
340
assert slider.value == 7
341
assert slider.load_event_to_attach[0]() == 7
342
assert slider.load_event_to_attach[1] is None
344
@patch("random.randint", return_value=3)
345
def test_slider_rounds_when_using_default_randomizer(self, mock_randint):
346
slider = gr.Slider(minimum=0, maximum=1, randomize=True, step=0.1)
347
# If get_random_value didn't round, this test would fail
348
# because 0.30000000000000004 != 0.3
349
assert slider.get_random_value() == 0.3
350
mock_randint.assert_called()
354
def test_component_functions(self):
356
Preprocess, postprocess, serialize, get_config
358
bool_input = gr.Checkbox()
359
assert bool_input.preprocess(True)
360
assert bool_input.postprocess(True)
361
assert bool_input.postprocess(True)
362
bool_input = gr.Checkbox(value=True, label="Check Your Input")
363
assert bool_input.get_config() == {
367
"label": "Check Your Input",
376
"_selectable": False,
380
def test_in_interface(self):
384
iface = gr.Interface(lambda x: 1 if x else 0, "checkbox", "number")
385
assert iface(True) == 1
388
class TestCheckboxGroup:
389
def test_component_functions(self):
391
Preprocess, postprocess, serialize, get_config
393
checkboxes_input = gr.CheckboxGroup(["a", "b", "c"])
394
assert checkboxes_input.preprocess(["a", "c"]) == ["a", "c"]
395
assert checkboxes_input.postprocess(["a", "c"]) == ["a", "c"]
397
checkboxes_input = gr.CheckboxGroup(["a", "b"], type="index")
398
assert checkboxes_input.preprocess(["a"]) == [0]
399
assert checkboxes_input.preprocess(["a", "b"]) == [0, 1]
400
assert checkboxes_input.preprocess(["a", "b", "c"]) == [0, 1, None]
402
# When a Gradio app is loaded with gr.load, the tuples are converted to lists,
403
# so we need to test that case as well
404
checkboxgroup = gr.CheckboxGroup(["a", "b", ["c", "c full"]]) # type: ignore
405
assert checkboxgroup.choices == [("a", "a"), ("b", "b"), ("c", "c full")]
407
checkboxes_input = gr.CheckboxGroup(
409
choices=["a", "b", "c"],
410
label="Check Your Inputs",
412
assert checkboxes_input.get_config() == {
413
"choices": [("a", "a"), ("b", "b"), ("c", "c")],
415
"name": "checkboxgroup",
417
"label": "Check Your Inputs",
426
"_selectable": False,
430
with pytest.raises(ValueError):
431
gr.CheckboxGroup(["a"], type="unknown")
433
cbox = gr.CheckboxGroup(choices=["a", "b"], value="c")
434
assert cbox.get_config()["value"] == ["c"]
435
assert cbox.postprocess("a") == ["a"]
436
assert cbox.process_example("a") == ["a"]
438
def test_in_interface(self):
442
checkboxes_input = gr.CheckboxGroup(["a", "b", "c"])
443
iface = gr.Interface(lambda x: "|".join(x), checkboxes_input, "textbox")
444
assert iface(["a", "c"]) == "a|c"
445
assert iface([]) == ""
446
_ = gr.CheckboxGroup(["a", "b", "c"], type="index")
450
def test_component_functions(self):
452
Preprocess, postprocess, serialize, get_config
455
radio_input = gr.Radio(["a", "b", "c"])
456
assert radio_input.preprocess("c") == "c"
457
assert radio_input.postprocess("a") == "a"
458
radio_input = gr.Radio(
459
choices=["a", "b", "c"], value="a", label="Pick Your One Input"
461
assert radio_input.get_config() == {
462
"choices": [("a", "a"), ("b", "b"), ("c", "c")],
466
"label": "Pick Your One Input",
475
"_selectable": False,
480
radio = gr.Radio(choices=["a", "b"], type="index")
481
assert radio.preprocess("a") == 0
482
assert radio.preprocess("b") == 1
483
assert radio.preprocess("c") is None
485
# When a Gradio app is loaded with gr.load, the tuples are converted to lists,
486
# so we need to test that case as well
487
radio = gr.Radio(["a", "b", ["c", "c full"]]) # type: ignore
488
assert radio.choices == [("a", "a"), ("b", "b"), ("c", "c full")]
490
with pytest.raises(ValueError):
491
gr.Radio(["a", "b"], type="unknown")
493
def test_in_interface(self):
497
radio_input = gr.Radio(["a", "b", "c"])
498
iface = gr.Interface(lambda x: 2 * x, radio_input, "textbox")
499
assert iface("c") == "cc"
503
def test_component_functions(self):
505
Preprocess, postprocess, serialize, get_config
507
dropdown_input = gr.Dropdown(["a", "b", ("c", "c full")], multiselect=True)
508
assert dropdown_input.preprocess("a") == "a"
509
assert dropdown_input.postprocess("a") == ["a"]
510
assert dropdown_input.preprocess("c full") == "c full"
511
assert dropdown_input.postprocess("c full") == ["c full"]
513
# When a Gradio app is loaded with gr.load, the tuples are converted to lists,
514
# so we need to test that case as well
515
dropdown_input = gr.Dropdown(["a", "b", ["c", "c full"]]) # type: ignore
516
assert dropdown_input.choices == [("a", "a"), ("b", "b"), ("c", "c full")]
518
dropdown = gr.Dropdown(choices=["a", "b"], type="index")
519
assert dropdown.preprocess("a") == 0
520
assert dropdown.preprocess("b") == 1
521
assert dropdown.preprocess("c") is None
523
dropdown = gr.Dropdown(choices=["a", "b"], type="index", multiselect=True)
524
assert dropdown.preprocess(["a"]) == [0]
525
assert dropdown.preprocess(["a", "b"]) == [0, 1]
526
assert dropdown.preprocess(["a", "b", "c"]) == [0, 1, None]
528
dropdown_input_multiselect = gr.Dropdown(["a", "b", ("c", "c full")])
529
assert dropdown_input_multiselect.preprocess(["a", "c full"]) == ["a", "c full"]
530
assert dropdown_input_multiselect.postprocess(["a", "c full"]) == [
534
dropdown_input_multiselect = gr.Dropdown(
536
choices=["a", "b", ("c", "c full")],
537
label="Select Your Inputs",
541
assert dropdown_input_multiselect.get_config() == {
542
"allow_custom_value": False,
543
"choices": [("a", "a"), ("b", "b"), ("c", "c full")],
547
"label": "Select Your Inputs",
559
"_selectable": False,
563
with pytest.raises(ValueError):
564
gr.Dropdown(["a"], type="unknown")
566
dropdown = gr.Dropdown(choices=["a", "b"], value="c")
567
assert dropdown.get_config()["value"] == "c"
568
assert dropdown.postprocess("a") == "a"
570
def test_in_interface(self):
574
dropdown_input = gr.Dropdown(["a", "b", "c"])
575
iface = gr.Interface(lambda x: "|".join(x), dropdown_input, "textbox")
576
assert iface(["a", "c"]) == "a|c"
577
assert iface([]) == ""
580
class TestImageEditor:
581
def test_component_functions(self):
582
test_image_path = "test/test_files/bus.png"
583
image_data = FileData(path=test_image_path)
584
image_editor_data = EditorData(
585
background=image_data, layers=[image_data, image_data], composite=image_data
588
"background": test_image_path,
589
"layers": [test_image_path, test_image_path],
590
"composite": test_image_path,
593
image_editor_component = gr.ImageEditor()
595
assert isinstance(image_editor_component.preprocess(image_editor_data), dict)
596
assert image_editor_component.postprocess(payload) == image_editor_data
598
# Test that ImageEditor can accept just a filepath as well
599
simpler_data = EditorData(
600
background=image_data, layers=[], composite=image_data
602
assert image_editor_component.postprocess(test_image_path) == simpler_data
604
assert image_editor_component.get_config() == {
608
"image_mode": "RGBA",
609
"sources": ("upload", "webcam", "clipboard"),
613
"show_download_button": True,
621
"mirror_webcam": True,
622
"show_share_button": False,
623
"_selectable": False,
625
"transforms": ("crop",),
626
"eraser": {"default_size": "auto"},
628
"default_size": "auto",
636
"default_color": "auto",
637
"color_mode": "defaults",
640
"name": "imageeditor",
643
def test_process_example(self):
644
test_image_path = "test/test_files/bus.png"
645
image_editor = gr.ImageEditor()
646
example_value = image_editor.process_example(test_image_path)
647
assert isinstance(example_value, EditorData)
648
assert example_value.background and example_value.background.path
652
def test_component_functions(self, gradio_temp_dir):
654
Preprocess, postprocess, serialize, get_config, _segment_by_slic
655
type: pil, file, filepath, numpy
658
img = FileData(path="test/test_files/bus.png")
659
image_input = gr.Image()
661
image_input = gr.Image(type="filepath")
662
image_temp_filepath = image_input.preprocess(img)
663
assert image_temp_filepath in [
664
str(f) for f in gradio_temp_dir.glob("**/*") if f.is_file()
667
image_input = gr.Image(type="pil", label="Upload Your Image")
668
assert image_input.get_config() == {
670
"sources": ["upload", "webcam", "clipboard"],
672
"show_share_button": False,
673
"show_download_button": True,
676
"label": "Upload Your Image",
688
"mirror_webcam": True,
689
"_selectable": False,
693
assert image_input.preprocess(None) is None
694
image_input = gr.Image()
695
assert image_input.preprocess(img) is not None
696
image_input.preprocess(img)
697
file_image = gr.Image(type="filepath")
698
assert isinstance(file_image.preprocess(img), str)
699
with pytest.raises(ValueError):
700
gr.Image(type="unknown")
702
string_source = gr.Image(sources="upload")
703
assert string_source.sources == ["upload"]
704
# Output functionalities
705
image_output = gr.Image(type="pil")
706
processed_image = image_output.postprocess(
707
PIL.Image.open(img.path)
709
assert processed_image is not None
710
if processed_image is not None:
711
processed = PIL.Image.open(cast(dict, processed_image).get("path", ""))
712
source = PIL.Image.open(img.path)
713
assert processed.size == source.size
715
def test_in_interface_as_output(self):
720
def generate_noise(height, width):
721
return np.random.randint(0, 256, (height, width, 3))
723
iface = gr.Interface(generate_noise, ["slider", "slider"], "image")
724
assert iface(10, 20).endswith(".png")
726
def test_static(self):
730
component = gr.Image("test/test_files/bus.png")
731
value = component.get_config().get("value")
732
base64 = client_utils.encode_file_to_base64(value["path"])
733
assert base64 == media_data.BASE64_IMAGE
734
component = gr.Image(None)
735
assert component.get_config().get("value") is None
737
def test_images_upright_after_preprocess(self):
738
component = gr.Image(type="pil")
739
file_path = "test/test_files/rotated_image.jpeg"
740
im = PIL.Image.open(file_path)
741
assert im.getexif().get(274) != 1
742
image = component.preprocess(FileData(path=file_path))
743
assert image == PIL.ImageOps.exif_transpose(im)
748
async def test_in_interface_as_output(self):
754
import matplotlib.pyplot as plt
757
plt.plot(range(num), range(num))
760
iface = gr.Interface(plot, "slider", "plot")
761
with utils.MatplotlibBackendMananger():
762
output = await iface.process_api(fn_index=0, inputs=[10], state={})
763
assert output["data"][0]["type"] == "matplotlib"
764
assert output["data"][0]["plot"].startswith("data:image/png;base64")
766
def test_static(self):
770
with utils.MatplotlibBackendMananger():
771
import matplotlib.pyplot as plt
774
plt.plot([1, 2, 3], [1, 2, 3])
776
component = gr.Plot(fig)
777
assert component.get_config().get("value") is not None
778
component = gr.Plot(None)
779
assert component.get_config().get("value") is None
781
def test_postprocess_altair(self):
783
from vega_datasets import data
791
y="Miles_per_Gallon",
795
out = gr.Plot().postprocess(chart).model_dump()
796
assert isinstance(out["plot"], str)
797
assert out["plot"] == chart.to_json()
801
def test_component_functions(self, gradio_temp_dir):
803
Preprocess, postprocess serialize, get_config, deserialize
804
type: filepath, numpy, file
806
x_wav = FileData(path=media_data.BASE64_AUDIO["path"])
807
audio_input = gr.Audio()
808
output1 = audio_input.preprocess(x_wav)
809
assert output1[0] == 8000
810
assert output1[1].shape == (8046,)
812
x_wav = processing_utils.move_files_to_cache([x_wav], audio_input)[0]
813
audio_input = gr.Audio(type="filepath")
814
output1 = audio_input.preprocess(x_wav)
815
assert Path(output1).name.endswith("audio_sample.wav")
817
audio_input = gr.Audio(label="Upload Your Audio")
818
assert audio_input.get_config() == {
820
"sources": ["upload", "microphone"],
822
"show_download_button": None,
823
"show_share_button": False,
826
"label": "Upload Your Audio",
842
"waveform_options": {
843
"sample_rate": 44100,
844
"show_controls": False,
845
"show_recording_waveform": True,
847
"waveform_color": None,
848
"waveform_progress_color": None,
849
"trim_region_color": None,
851
"_selectable": False,
853
assert audio_input.preprocess(None) is None
855
audio_input = gr.Audio(type="filepath")
856
assert isinstance(audio_input.preprocess(x_wav), str)
857
with pytest.raises(ValueError):
858
gr.Audio(type="unknown")
860
rng = np.random.default_rng()
861
# Confirm Audio can be instantiated with a numpy array
862
gr.Audio((100, rng.random(size=(1000, 2))), label="Play your audio")
864
# Output functionalities
865
y_audio = client_utils.decode_base64_to_file(
866
deepcopy(media_data.BASE64_AUDIO)["data"]
868
audio_output = gr.Audio(type="filepath")
870
y_audio.name, audio_output.postprocess(y_audio.name).model_dump()["path"]
872
assert audio_output.get_config() == {
875
"show_download_button": None,
876
"show_share_button": False,
895
"sources": ["upload", "microphone"],
896
"waveform_options": {
897
"sample_rate": 44100,
898
"show_controls": False,
899
"show_recording_waveform": True,
901
"waveform_color": None,
902
"waveform_progress_color": None,
903
"trim_region_color": None,
905
"_selectable": False,
908
output1 = audio_output.postprocess(y_audio.name).model_dump()
909
output2 = audio_output.postprocess(Path(y_audio.name)).model_dump()
910
assert output1 == output2
912
def test_default_value_postprocess(self):
913
x_wav = deepcopy(media_data.BASE64_AUDIO)
914
audio = gr.Audio(value=x_wav["path"])
915
assert utils.is_in_or_equal(audio.value["path"], audio.GRADIO_CACHE)
917
def test_in_interface(self):
918
def reverse_audio(audio):
920
return (sr, np.flipud(data))
922
iface = gr.Interface(reverse_audio, "audio", "audio")
923
reversed_file = iface("test/test_files/audio_sample.wav")
924
reversed_reversed_file = iface(reversed_file)
925
reversed_reversed_data = client_utils.encode_url_or_file_to_base64(
926
reversed_reversed_file
928
similarity = SequenceMatcher(
929
a=reversed_reversed_data, b=media_data.BASE64_AUDIO["data"]
931
assert similarity > 0.99
933
def test_in_interface_as_output(self):
938
def generate_noise(duration):
939
return 48000, np.random.randint(-256, 256, (duration, 3)).astype(np.int16)
941
iface = gr.Interface(generate_noise, "slider", "audio")
942
assert iface(100).endswith(".wav")
944
def test_audio_preprocess_can_be_read_by_scipy(self, gradio_temp_dir):
946
path=processing_utils.save_base64_to_cache(
947
media_data.BASE64_MICROPHONE["data"], cache_dir=gradio_temp_dir
950
audio_input = gr.Audio(type="filepath")
951
output = audio_input.preprocess(x_wav)
954
def test_prepost_process_to_mp3(self, gradio_temp_dir):
956
path=processing_utils.save_base64_to_cache(
957
media_data.BASE64_MICROPHONE["data"], cache_dir=gradio_temp_dir
960
audio_input = gr.Audio(type="filepath", format="mp3")
961
output = audio_input.preprocess(x_wav)
962
assert output.endswith("mp3")
963
output = audio_input.postprocess(
964
(48000, np.random.randint(-256, 256, (5, 3)).astype(np.int16))
966
assert output["path"].endswith("mp3")
970
def test_component_functions(self):
972
Preprocess, serialize, get_config, value
974
x_file = FileData(path=media_data.BASE64_FILE["path"])
975
file_input = gr.File()
976
output = file_input.preprocess(x_file)
977
assert isinstance(output, str)
979
input1 = file_input.preprocess(x_file)
980
input2 = file_input.preprocess(x_file)
981
assert input1 == input1.name # Testing backwards compatibility
982
assert input1 == input2
983
assert Path(input1).name == "sample_file.pdf"
985
file_input = gr.File(label="Upload Your File")
986
assert file_input.get_config() == {
987
"file_count": "single",
991
"label": "Upload Your File",
1001
"_selectable": False,
1005
assert file_input.preprocess(None) is None
1006
assert file_input.preprocess(x_file) is not None
1008
zero_size_file = FileData(path="document.txt", size=0)
1009
temp_file = file_input.preprocess(zero_size_file)
1010
assert not Path(temp_file.name).exists()
1012
file_input = gr.File(type="binary")
1013
output = file_input.preprocess(x_file)
1014
assert isinstance(output, bytes)
1016
output1 = file_input.postprocess("test/test_files/sample_file.pdf")
1017
output2 = file_input.postprocess("test/test_files/sample_file.pdf")
1018
assert output1 == output2
1020
def test_preprocess_with_multiple_files(self):
1021
file_data = FileData(path=media_data.BASE64_FILE["path"])
1022
list_file_data = ListFiles(root=[file_data, file_data])
1023
file_input = gr.File(file_count="directory")
1024
output = file_input.preprocess(list_file_data)
1025
assert isinstance(output, list)
1026
assert isinstance(output[0], str)
1028
def test_file_type_must_be_list(self):
1030
ValueError, match="Parameter file_types must be a list. Received str"
1032
gr.File(file_types=".json")
1034
def test_in_interface_as_input(self):
1038
x_file = media_data.BASE64_FILE["path"]
1040
def get_size_of_file(file_obj):
1041
return os.path.getsize(file_obj.name)
1043
iface = gr.Interface(get_size_of_file, "file", "number")
1044
assert iface(x_file) == 10558
1046
def test_as_component_as_output(self):
1051
def write_file(content):
1052
with open("test.txt", "w") as f:
1056
iface = gr.Interface(write_file, "text", "file")
1057
assert iface("hello world").endswith(".txt")
1060
class TestUploadButton:
1061
def test_component_functions(self):
1065
x_file = FileData(path=media_data.BASE64_FILE["path"])
1066
upload_input = gr.UploadButton()
1067
input = upload_input.preprocess(x_file)
1068
assert isinstance(input, str)
1070
input1 = upload_input.preprocess(x_file)
1071
input2 = upload_input.preprocess(x_file)
1072
assert input1 == input1.name # Testing backwards compatibility
1073
assert input1 == input2
1075
def test_raises_if_file_types_is_not_list(self):
1077
ValueError, match="Parameter file_types must be a list. Received int"
1079
gr.UploadButton(file_types=2)
1081
def test_preprocess_with_multiple_files(self):
1082
file_data = FileData(path=media_data.BASE64_FILE["path"])
1083
list_file_data = ListFiles(root=[file_data, file_data])
1084
upload_input = gr.UploadButton(file_count="directory")
1085
output = upload_input.preprocess(list_file_data)
1086
assert isinstance(output, list)
1087
assert isinstance(output[0], str)
1091
def test_component_functions(self):
1093
Preprocess, serialize, get_config
1096
"data": [["Tim", 12, False], ["Jan", 24, True]],
1097
"headers": ["Name", "Age", "Member"],
1100
x_payload = DataframeData(**x_data)
1101
dataframe_input = gr.Dataframe(headers=["Name", "Age", "Member"])
1102
output = dataframe_input.preprocess(x_payload)
1103
assert output["Age"][1] == 24
1104
assert not output["Member"][0]
1105
assert dataframe_input.postprocess(output) == x_payload
1107
dataframe_input = gr.Dataframe(
1108
headers=["Name", "Age", "Member"], label="Dataframe Input"
1110
assert dataframe_input.get_config() == {
1112
"headers": ["Name", "Age", "Member"],
1113
"data": [["", "", ""]],
1116
"_selectable": False,
1117
"headers": ["Name", "Age", "Member"],
1118
"row_count": (1, "dynamic"),
1119
"col_count": (3, "dynamic"),
1122
"label": "Dataframe Input",
1126
"interactive": None,
1132
"name": "dataframe",
1134
"latex_delimiters": [{"display": True, "left": "$$", "right": "$$"}],
1135
"line_breaks": True,
1136
"column_widths": [],
1138
dataframe_input = gr.Dataframe()
1139
output = dataframe_input.preprocess(DataframeData(**x_data))
1140
assert output["Age"][1] == 24
1143
"data": [["Tim", 12, False], ["Jan", 24, True]],
1144
"headers": ["Name", "Age", "Member"],
1145
"metadata": {"display_value": None, "styling": None},
1147
dataframe_input.preprocess(DataframeData(**x_data))
1149
with pytest.raises(ValueError):
1150
gr.Dataframe(type="unknown")
1152
dataframe_output = gr.Dataframe()
1153
assert dataframe_output.get_config() == {
1155
"headers": ["1", "2", "3"],
1156
"data": [["", "", ""]],
1159
"_selectable": False,
1160
"headers": ["1", "2", "3"],
1161
"row_count": (1, "dynamic"),
1162
"col_count": (3, "dynamic"),
1169
"interactive": None,
1175
"name": "dataframe",
1177
"latex_delimiters": [{"display": True, "left": "$$", "right": "$$"}],
1178
"line_breaks": True,
1179
"column_widths": [],
1182
dataframe_input = gr.Dataframe(column_widths=["100px", 200, "50%"])
1183
assert dataframe_input.get_config()["column_widths"] == [
1189
def test_postprocess(self):
1193
dataframe_output = gr.Dataframe()
1194
output = dataframe_output.postprocess([]).model_dump()
1195
assert output == {"data": [[]], "headers": ["1", "2", "3"], "metadata": None}
1196
output = dataframe_output.postprocess(np.zeros((2, 2))).model_dump()
1198
"data": [[0, 0], [0, 0]],
1199
"headers": ["1", "2"],
1202
output = dataframe_output.postprocess([[1, 3, 5]]).model_dump()
1204
"data": [[1, 3, 5]],
1205
"headers": ["1", "2", "3"],
1208
output = dataframe_output.postprocess(
1209
pd.DataFrame([[2, True], [3, True], [4, False]], columns=["num", "prime"])
1212
"headers": ["num", "prime"],
1213
"data": [[2, True], [3, True], [4, False]],
1216
with pytest.raises(ValueError):
1217
gr.Dataframe(type="unknown")
1219
# When the headers don't match the data
1220
dataframe_output = gr.Dataframe(headers=["one", "two", "three"])
1221
output = dataframe_output.postprocess([[2, True], [3, True]]).model_dump()
1223
"headers": ["one", "two"],
1224
"data": [[2, True], [3, True]],
1227
dataframe_output = gr.Dataframe(headers=["one", "two", "three"])
1228
output = dataframe_output.postprocess(
1229
[[2, True, "ab", 4], [3, True, "cd", 5]]
1232
"headers": ["one", "two", "three", "4"],
1233
"data": [[2, True, "ab", 4], [3, True, "cd", 5]],
1237
def test_dataframe_postprocess_all_types(self):
1240
"date_1": pd.date_range("2021-01-01", periods=2),
1241
"date_2": pd.date_range("2022-02-15", periods=2).strftime(
1244
"number": np.array([0.2233, 0.57281]),
1245
"number_2": np.array([84, 23]).astype(np.int64),
1246
"bool": [True, False],
1247
"markdown": ["# Hello", "# Goodbye"],
1250
component = gr.Dataframe(
1251
datatype=["date", "date", "number", "number", "bool", "markdown"]
1253
output = component.postprocess(df).model_dump()
1255
"headers": list(df.columns),
1258
pd.Timestamp("2021-01-01 00:00:00"),
1259
"February 15, 2022, 12:00:00 AM",
1266
pd.Timestamp("2021-01-02 00:00:00"),
1267
"February 16, 2022, 12:00:00 AM",
1277
def test_dataframe_postprocess_only_dates(self):
1280
"date_1": pd.date_range("2021-01-01", periods=2),
1281
"date_2": pd.date_range("2022-02-15", periods=2),
1284
component = gr.Dataframe(datatype=["date", "date"])
1285
output = component.postprocess(df).model_dump()
1287
"headers": list(df.columns),
1290
pd.Timestamp("2021-01-01 00:00:00"),
1291
pd.Timestamp("2022-02-15 00:00:00"),
1294
pd.Timestamp("2021-01-02 00:00:00"),
1295
pd.Timestamp("2022-02-16 00:00:00"),
1301
def test_dataframe_postprocess_styler(self):
1302
component = gr.Dataframe()
1305
"name": ["Adam", "Mike"] * 4,
1306
"gpa": [1.1, 1.12] * 4,
1307
"sat": [800, 800] * 4,
1310
s = df.style.format(precision=1, decimal=",")
1311
output = component.postprocess(s).model_dump()
1315
["Mike", 1.12, 800],
1317
["Mike", 1.12, 800],
1319
["Mike", 1.12, 800],
1321
["Mike", 1.12, 800],
1323
"headers": ["name", "gpa", "sat"],
1326
["Adam", "1,1", "800"],
1327
["Mike", "1,1", "800"],
1328
["Adam", "1,1", "800"],
1329
["Mike", "1,1", "800"],
1330
["Adam", "1,1", "800"],
1331
["Mike", "1,1", "800"],
1332
["Adam", "1,1", "800"],
1333
["Mike", "1,1", "800"],
1350
"A": [14, 4, 5, 4, 1],
1351
"B": [5, 2, 54, 3, 2],
1352
"C": [20, 20, 7, 3, 8],
1353
"D": [14, 3, 6, 2, 6],
1354
"E": [23, 45, 64, 32, 23],
1358
t = df.style.highlight_max(color="lightgreen", axis=0)
1359
output = component.postprocess(t).model_dump()
1362
[14, 5, 20, 14, 23],
1368
"headers": ["A", "B", "C", "D", "E"],
1371
["14", "5", "20", "14", "23"],
1372
["4", "2", "20", "3", "45"],
1373
["5", "54", "7", "6", "64"],
1374
["4", "3", "3", "2", "32"],
1375
["1", "2", "8", "6", "23"],
1379
"background-color: lightgreen",
1381
"background-color: lightgreen",
1382
"background-color: lightgreen",
1385
["", "", "background-color: lightgreen", "", ""],
1388
"background-color: lightgreen",
1391
"background-color: lightgreen",
1393
["", "", "", "", ""],
1394
["", "", "", "", ""],
1401
def test_preprocessing(self):
1402
test_file_dir = Path(__file__).parent / "test_files"
1403
bus = str(Path(test_file_dir, "bus.png").resolve())
1405
dataset = gr.Dataset(
1406
components=["number", "textbox", "image", "html", "markdown"],
1408
[5, "hello", bus, "<b>Bold</b>", "**Bold**"],
1409
[15, "hi", bus, "<i>Italics</i>", "*Italics*"],
1413
row = dataset.preprocess(1)
1415
assert row[1] == "hi"
1416
assert row[2]["path"].endswith("bus.png")
1417
assert row[3] == "<i>Italics</i>"
1418
assert row[4] == "*Italics*"
1420
dataset = gr.Dataset(
1421
components=["number", "textbox", "image", "html", "markdown"],
1423
[5, "hello", bus, "<b>Bold</b>", "**Bold**"],
1424
[15, "hi", bus, "<i>Italics</i>", "*Italics*"],
1429
assert dataset.preprocess(1) == 1
1431
radio = gr.Radio(choices=[("name 1", "value 1"), ("name 2", "value 2")])
1432
dataset = gr.Dataset(samples=[["value 1"], ["value 2"]], components=[radio])
1433
assert dataset.samples == [["value 1"], ["value 2"]]
1435
def test_postprocessing(self):
1436
test_file_dir = Path(Path(__file__).parent, "test_files")
1437
bus = Path(test_file_dir, "bus.png")
1439
dataset = gr.Dataset(
1440
components=["number", "textbox", "image", "html", "markdown"], type="index"
1443
output = dataset.postprocess(
1445
[5, "hello", bus, "<b>Bold</b>", "**Bold**"],
1446
[15, "hi", bus, "<i>Italics</i>", "*Italics*"],
1452
[5, "hello", bus, "<b>Bold</b>", "**Bold**"],
1453
[15, "hi", bus, "<i>Italics</i>", "*Italics*"],
1455
"__type__": "update",
1460
def test_component_functions(self):
1462
Preprocess, serialize, deserialize, get_config
1464
x_video = VideoData(
1465
video=FileData(path=deepcopy(media_data.BASE64_VIDEO)["path"])
1467
video_input = gr.Video()
1469
x_video = processing_utils.move_files_to_cache([x_video], video_input)[0]
1471
output1 = video_input.preprocess(x_video)
1472
assert isinstance(output1, str)
1473
output2 = video_input.preprocess(x_video)
1474
assert output1 == output2
1476
video_input = gr.Video(include_audio=False)
1477
output1 = video_input.preprocess(x_video)
1478
output2 = video_input.preprocess(x_video)
1479
assert output1 == output2
1481
video_input = gr.Video(label="Upload Your Video")
1482
assert video_input.get_config() == {
1484
"sources": ["upload", "webcam"],
1486
"show_share_button": False,
1488
"label": "Upload Your Video",
1492
"show_download_button": None,
1499
"interactive": None,
1501
"mirror_webcam": True,
1502
"include_audio": True,
1506
"_selectable": False,
1508
assert video_input.preprocess(None) is None
1509
video_input = gr.Video(format="avi")
1510
output_video = video_input.preprocess(x_video)
1511
assert output_video[-3:] == "avi"
1512
assert "flip" not in output_video
1514
# Output functionalities
1515
y_vid_path = "test/test_files/video_sample.mp4"
1516
subtitles_path = "test/test_files/s1.srt"
1517
video_output = gr.Video()
1518
output1 = video_output.postprocess(y_vid_path).model_dump()["video"]["path"]
1519
assert output1.endswith("mp4")
1520
output2 = video_output.postprocess(y_vid_path).model_dump()["video"]["path"]
1521
assert output1 == output2
1523
video_output.postprocess(y_vid_path).model_dump()["video"]["orig_name"]
1524
== "video_sample.mp4"
1526
output_with_subtitles = video_output.postprocess(
1527
(y_vid_path, subtitles_path)
1529
assert output_with_subtitles["subtitles"]["path"].endswith(".vtt")
1531
p_video = gr.Video()
1532
video_with_subtitle = gr.Video()
1533
postprocessed_video = p_video.postprocess(Path(y_vid_path)).model_dump()
1534
postprocessed_video_with_subtitle = video_with_subtitle.postprocess(
1535
(Path(y_vid_path), Path(subtitles_path))
1540
"path": "video_sample.mp4",
1541
"orig_name": "video_sample.mp4",
1546
"meta": {"_type": "gradio.FileData"},
1551
processed_video_with_subtitle = {
1553
"path": "video_sample.mp4",
1554
"orig_name": "video_sample.mp4",
1559
"meta": {"_type": "gradio.FileData"},
1568
"meta": {"_type": "gradio.FileData"},
1571
postprocessed_video["video"]["path"] = os.path.basename(
1572
postprocessed_video["video"]["path"]
1574
assert processed_video == postprocessed_video
1575
postprocessed_video_with_subtitle["video"]["path"] = os.path.basename(
1576
postprocessed_video_with_subtitle["video"]["path"]
1578
if postprocessed_video_with_subtitle["subtitles"]["path"]:
1579
postprocessed_video_with_subtitle["subtitles"]["path"] = "s1.srt"
1580
assert processed_video_with_subtitle == postprocessed_video_with_subtitle
1582
def test_in_interface(self):
1586
x_video = media_data.BASE64_VIDEO["path"]
1587
iface = gr.Interface(lambda x: x, "video", "playable_video")
1588
assert iface({"video": x_video})["video"].endswith(".mp4")
1590
def test_with_waveform(self):
1594
x_audio = media_data.BASE64_AUDIO["path"]
1595
iface = gr.Interface(lambda x: gr.make_waveform(x), "audio", "video")
1596
assert iface(x_audio)["video"].endswith(".mp4")
1598
def test_video_postprocess_converts_to_playable_format(self):
1599
test_file_dir = Path(Path(__file__).parent, "test_files")
1600
# This file has a playable container but not playable codec
1601
with tempfile.NamedTemporaryFile(
1602
suffix="bad_video.mp4", delete=False
1603
) as tmp_not_playable_vid:
1604
bad_vid = str(test_file_dir / "bad_video_sample.mp4")
1605
assert not processing_utils.video_is_playable(bad_vid)
1606
shutil.copy(bad_vid, tmp_not_playable_vid.name)
1607
output = gr.Video().postprocess(tmp_not_playable_vid.name).model_dump()
1608
assert processing_utils.video_is_playable(output["video"]["path"])
1610
# This file has a playable codec but not a playable container
1611
with tempfile.NamedTemporaryFile(
1612
suffix="playable_but_bad_container.mkv", delete=False
1613
) as tmp_not_playable_vid:
1614
bad_vid = str(test_file_dir / "playable_but_bad_container.mkv")
1615
assert not processing_utils.video_is_playable(bad_vid)
1616
shutil.copy(bad_vid, tmp_not_playable_vid.name)
1617
output = gr.Video().postprocess(tmp_not_playable_vid.name).model_dump()
1618
assert processing_utils.video_is_playable(output["video"]["path"])
1620
@patch("pathlib.Path.exists", MagicMock(return_value=False))
1621
@patch("gradio.components.video.FFmpeg")
1622
def test_video_preprocessing_flips_video_for_webcam(self, mock_ffmpeg):
1623
# Ensures that the cached temp video file is not used so that ffmpeg is called for each test
1624
x_video = VideoData(video=FileData(path=media_data.BASE64_VIDEO["path"]))
1625
video_input = gr.Video(sources=["webcam"])
1626
_ = video_input.preprocess(x_video)
1628
# Dict mapping filename to FFmpeg options
1629
output_params = mock_ffmpeg.call_args_list[0][1]["outputs"]
1630
assert "hflip" in list(output_params.values())[0]
1631
assert "flip" in list(output_params.keys())[0]
1633
mock_ffmpeg.reset_mock()
1635
sources=["webcam"], mirror_webcam=False, include_audio=True
1636
).preprocess(x_video)
1637
mock_ffmpeg.assert_not_called()
1639
mock_ffmpeg.reset_mock()
1640
_ = gr.Video(sources=["upload"], format="mp4", include_audio=True).preprocess(
1643
mock_ffmpeg.assert_not_called()
1645
mock_ffmpeg.reset_mock()
1646
output_file = gr.Video(
1647
sources=["webcam"], mirror_webcam=True, format="avi"
1648
).preprocess(x_video)
1649
output_params = mock_ffmpeg.call_args_list[0][1]["outputs"]
1650
assert "hflip" in list(output_params.values())[0]
1651
assert "flip" in list(output_params.keys())[0]
1652
assert ".avi" in list(output_params.keys())[0]
1653
assert ".avi" in output_file
1655
mock_ffmpeg.reset_mock()
1656
output_file = gr.Video(
1657
sources=["webcam"], mirror_webcam=False, format="avi", include_audio=False
1658
).preprocess(x_video)
1659
output_params = mock_ffmpeg.call_args_list[0][1]["outputs"]
1660
assert list(output_params.values())[0] == ["-an"]
1661
assert "flip" not in Path(list(output_params.keys())[0]).name
1662
assert ".avi" in list(output_params.keys())[0]
1663
assert ".avi" in output_file
1667
# This test ensures that `components.get_component_instance()` works correctly when instantiating from components
1668
def test_no_duplicate_uncased_names(self, io_components):
1669
unique_subclasses_uncased = {s.__name__.lower() for s in io_components}
1670
assert len(io_components) == len(unique_subclasses_uncased)
1674
def test_component_functions(self):
1676
Process, postprocess, deserialize
1679
label_output = gr.Label()
1680
label = label_output.postprocess(y).model_dump()
1681
assert label == {"label": "happy", "confidences": None}
1683
y = {3: 0.7, 1: 0.2, 0: 0.1}
1684
label = label_output.postprocess(y).model_dump()
1688
{"label": 3, "confidence": 0.7},
1689
{"label": 1, "confidence": 0.2},
1690
{"label": 0, "confidence": 0.1},
1693
label_output = gr.Label(num_top_classes=2)
1694
label = label_output.postprocess(y).model_dump()
1699
{"label": 3, "confidence": 0.7},
1700
{"label": 1, "confidence": 0.2},
1703
with pytest.raises(ValueError):
1704
label_output.postprocess([1, 2, 3]).model_dump()
1706
test_file_dir = Path(Path(__file__).parent, "test_files")
1707
path = str(Path(test_file_dir, "test_label_json.json"))
1708
label_dict = label_output.postprocess(path).model_dump()
1709
assert label_dict["label"] == "web site"
1711
assert label_output.get_config() == {
1714
"num_top_classes": 2,
1725
"_selectable": False,
1728
def test_color_argument(self):
1729
label = gr.Label(value=-10, color="red")
1730
assert label.get_config()["color"] == "red"
1732
def test_in_interface(self):
1736
x_img = "test/test_files/bus.png"
1738
def rgb_distribution(img):
1739
rgb_dist = np.mean(img, axis=(0, 1))
1740
rgb_dist /= np.sum(rgb_dist)
1741
rgb_dist = np.round(rgb_dist, decimals=2)
1744
"green": rgb_dist[1],
1745
"blue": rgb_dist[2],
1748
iface = gr.Interface(rgb_distribution, "image", "label")
1749
output = iface(x_img)
1753
{"label": "red", "confidence": 0.44},
1754
{"label": "green", "confidence": 0.28},
1755
{"label": "blue", "confidence": 0.28},
1760
class TestHighlightedText:
1761
def test_postprocess(self):
1765
component = gr.HighlightedText()
1768
("Wolfgang", "PER"),
1769
(" lives in ", None),
1774
{"token": "", "class_or_confidence": None},
1775
{"token": "Wolfgang", "class_or_confidence": "PER"},
1776
{"token": " lives in ", "class_or_confidence": None},
1777
{"token": "Berlin", "class_or_confidence": "LOC"},
1778
{"token": "", "class_or_confidence": None},
1780
result_ = component.postprocess(value).model_dump()
1781
assert result == result_
1783
text = "Wolfgang lives in Berlin"
1785
{"entity": "PER", "start": 0, "end": 8},
1786
{"entity": "LOC", "start": 18, "end": 24},
1788
result_ = component.postprocess(
1789
{"text": text, "entities": entities}
1791
assert result == result_
1793
text = "Wolfgang lives in Berlin"
1795
{"entity_group": "PER", "start": 0, "end": 8},
1796
{"entity": "LOC", "start": 18, "end": 24},
1798
result_ = component.postprocess(
1799
{"text": text, "entities": entities}
1801
assert result == result_
1803
# Test split entity is merged when combine adjacent is set
1804
text = "Wolfgang lives in Berlin"
1806
{"entity": "PER", "start": 0, "end": 4},
1807
{"entity": "PER", "start": 4, "end": 8},
1808
{"entity": "LOC", "start": 18, "end": 24},
1810
# After a merge empty entries are stripped except the leading one
1811
result_after_merge = [
1812
{"token": "", "class_or_confidence": None},
1813
{"token": "Wolfgang", "class_or_confidence": "PER"},
1814
{"token": " lives in ", "class_or_confidence": None},
1815
{"token": "Berlin", "class_or_confidence": "LOC"},
1817
result_ = component.postprocess(
1818
{"text": text, "entities": entities}
1820
assert result != result_
1821
assert result_after_merge != result_
1823
component = gr.HighlightedText(combine_adjacent=True)
1824
result_ = component.postprocess(
1825
{"text": text, "entities": entities}
1827
assert result_after_merge == result_
1829
component = gr.HighlightedText()
1831
text = "Wolfgang lives in Berlin"
1833
{"entity": "LOC", "start": 18, "end": 24},
1834
{"entity": "PER", "start": 0, "end": 8},
1836
result_ = component.postprocess(
1837
{"text": text, "entities": entities}
1839
assert result == result_
1841
text = "I live there"
1843
result_ = component.postprocess(
1844
{"text": text, "entities": entities}
1846
assert [{"token": text, "class_or_confidence": None}] == result_
1850
{"entity": "PER", "start": 0, "end": 8},
1852
result_ = component.postprocess(
1853
{"text": text, "entities": entities}
1856
{"token": "", "class_or_confidence": None},
1857
{"token": text, "class_or_confidence": "PER"},
1858
{"token": "", "class_or_confidence": None},
1861
def test_component_functions(self):
1865
ht_output = gr.HighlightedText(color_map={"pos": "green", "neg": "red"})
1866
assert ht_output.get_config() == {
1867
"color_map": {"pos": "green", "neg": "red"},
1868
"name": "highlightedtext",
1871
"show_legend": False,
1880
"_selectable": False,
1881
"combine_adjacent": False,
1882
"adjacent_separator": "",
1883
"interactive": None,
1886
def test_in_interface(self):
1891
def highlight_vowels(sentence):
1892
phrases, cur_phrase = [], ""
1893
vowels, mode = "aeiou", None
1894
for letter in sentence:
1895
letter_mode = "vowel" if letter in vowels else "non"
1898
elif mode != letter_mode:
1899
phrases.append((cur_phrase, mode))
1902
cur_phrase += letter
1903
phrases.append((cur_phrase, mode))
1906
iface = gr.Interface(highlight_vowels, "text", "highlight")
1907
output = iface("Helloooo")
1909
{"token": "H", "class_or_confidence": "non"},
1910
{"token": "e", "class_or_confidence": "vowel"},
1911
{"token": "ll", "class_or_confidence": "non"},
1912
{"token": "oooo", "class_or_confidence": "vowel"},
1916
class TestAnnotatedImage:
1917
def test_postprocess(self):
1921
component = gr.AnnotatedImage()
1922
img = np.random.randint(0, 255, (100, 100, 3), dtype=np.uint8)
1923
mask1 = [40, 40, 50, 50]
1924
mask2 = np.zeros((100, 100), dtype=np.uint8)
1925
mask2[10:20, 10:20] = 1
1927
input = (img, [(mask1, "mask1"), (mask2, "mask2")])
1928
result = component.postprocess(input).model_dump()
1930
base_img_out = PIL.Image.open(result["image"]["path"])
1932
assert result["annotations"][0]["label"] == "mask1"
1934
mask1_img_out = PIL.Image.open(result["annotations"][0]["image"]["path"])
1935
assert mask1_img_out.size == base_img_out.size
1936
mask1_array_out = np.array(mask1_img_out)
1937
assert np.max(mask1_array_out[40:50, 40:50]) == 255
1938
assert np.max(mask1_array_out[50:60, 50:60]) == 0
1940
def test_component_functions(self):
1941
ht_output = gr.AnnotatedImage(label="sections", show_legend=False)
1942
assert ht_output.get_config() == {
1943
"name": "annotatedimage",
1945
"label": "sections",
1946
"show_legend": False,
1958
"_selectable": False,
1961
def test_in_interface(self):
1963
top_left_corner = [0, 0, 20, 20]
1964
random_mask = np.random.randint(0, 2, img.shape[:2])
1965
return (img, [(top_left_corner, "left corner"), (random_mask, "random")])
1967
iface = gr.Interface(mask, "image", gr.AnnotatedImage())
1968
output = iface("test/test_files/bus.png")
1969
output_img, (mask1, _) = output["image"], output["annotations"]
1970
input_img = PIL.Image.open("test/test_files/bus.png")
1971
output_img = PIL.Image.open(output_img)
1972
mask1_img = PIL.Image.open(mask1["image"])
1974
assert output_img.size == input_img.size
1975
assert mask1_img.size == input_img.size
1979
def test_component_functions(self):
1981
Postprocess, get_config
1983
chatbot = gr.Chatbot()
1984
assert chatbot.postprocess(
1985
[["You are **cool**\nand fun", "so are *you*"]]
1986
).model_dump() == [("You are **cool**\nand fun", "so are *you*")]
1989
[("test/test_files/video_sample.mp4",), "cool video"],
1990
[("test/test_files/audio_sample.wav",), "cool audio"],
1991
[("test/test_files/bus.png", "A bus"), "cool pic"],
1992
[(Path("test/test_files/video_sample.mp4"),), "cool video"],
1993
[(Path("test/test_files/audio_sample.wav"),), "cool audio"],
1994
[(Path("test/test_files/bus.png"), "A bus"), "cool pic"],
1996
postprocessed_multimodal_msg = chatbot.postprocess(multimodal_msg).model_dump()
1997
for msg in postprocessed_multimodal_msg:
1998
assert "file" in msg[0]
1999
assert msg[1] in {"cool video", "cool audio", "cool pic"}
2000
assert msg[0]["file"]["path"].split(".")[-1] in {"mp4", "wav", "png"}
2001
if msg[0]["alt_text"]:
2002
assert msg[0]["alt_text"] == "A bus"
2004
assert chatbot.get_config() == {
2009
"show_share_button": False,
2018
"_selectable": False,
2019
"latex_delimiters": [{"display": True, "left": "$$", "right": "$$"}],
2022
"show_copy_button": False,
2023
"avatar_images": [None, None],
2024
"sanitize_html": True,
2025
"render_markdown": True,
2026
"bubble_full_width": True,
2027
"line_breaks": True,
2031
def test_avatar_images_are_moved_to_cache(self):
2032
chatbot = gr.Chatbot(avatar_images=("test/test_files/bus.png", None))
2033
assert chatbot.avatar_images[0]
2034
assert utils.is_in_or_equal(
2035
chatbot.avatar_images[0]["path"], chatbot.GRADIO_CACHE
2037
assert chatbot.avatar_images[1] is None
2041
def test_component_functions(self):
2045
js_output = gr.JSON()
2046
assert js_output.postprocess('{"a":1, "b": 2}'), '"{\\"a\\":1, \\"b\\": 2}"'
2047
assert js_output.get_config() == {
2059
"_selectable": False,
2062
def test_chatbot_selectable_in_config(self):
2063
with gr.Blocks() as demo:
2064
cb = gr.Chatbot(label="Chatbot")
2065
cb.like(lambda: print("foo"))
2066
gr.Chatbot(label="Chatbot2")
2069
for component in demo.config["components"]:
2070
if component["props"]["label"] == "Chatbot":
2071
assertion_count += 1
2072
assert component["props"]["likeable"]
2073
elif component["props"]["label"] == "Chatbot2":
2074
assertion_count += 1
2075
assert not component["props"]["likeable"]
2077
assert assertion_count == 2
2079
@pytest.mark.asyncio
2080
async def test_in_interface(self):
2085
def get_avg_age_per_gender(data):
2087
"M": int(data[data["gender"] == "M"]["age"].mean()),
2088
"F": int(data[data["gender"] == "F"]["age"].mean()),
2089
"O": int(data[data["gender"] == "O"]["age"].mean()),
2092
iface = gr.Interface(
2093
get_avg_age_per_gender,
2094
gr.Dataframe(headers=["gender", "age"]),
2105
await iface.process_api(
2106
0, [{"data": y_data, "headers": ["gender", "age"]}], state={}
2116
def test_component_functions(self):
2120
html_component = gr.components.HTML("#Welcome onboard", label="HTML Input")
2121
assert html_component.get_config() == {
2122
"value": "#Welcome onboard",
2123
"label": "HTML Input",
2130
"_selectable": False,
2133
def test_in_interface(self):
2138
def bold_text(text):
2139
return f"<strong>{text}</strong>"
2141
iface = gr.Interface(bold_text, "text", "html")
2142
assert iface("test") == "<strong>test</strong>"
2146
def test_component_functions(self):
2147
markdown_component = gr.Markdown("# Let's learn about $x$", label="Markdown")
2148
assert markdown_component.get_config()["value"] == "# Let's learn about $x$"
2150
def test_in_interface(self):
2154
iface = gr.Interface(lambda x: x, "text", "markdown")
2155
input_data = " Here's an [image](https://gradio.app/images/gradio_logo.png)"
2156
output_data = iface(input_data)
2157
assert output_data == input_data.strip()
2161
def test_component_functions(self):
2165
model_component = gr.components.Model3D(None, label="Model")
2166
assert model_component.get_config() == {
2168
"clear_color": [0, 0, 0, 0],
2178
"interactive": None,
2180
"camera_position": (None, None, None),
2184
"_selectable": False,
2187
file = "test/test_files/Box.gltf"
2188
output1 = model_component.postprocess(file)
2189
output2 = model_component.postprocess(Path(file))
2192
assert Path(output1.path).name == Path(output2.path).name
2194
def test_in_interface(self):
2198
iface = gr.Interface(lambda x: x, "model3d", "model3d")
2199
input_data = "test/test_files/Box.gltf"
2200
output_data = iface(input_data)
2201
assert output_data.endswith(".gltf")
2204
class TestColorPicker:
2205
def test_component_functions(self):
2207
Preprocess, postprocess, serialize, tokenize, get_config
2209
color_picker_input = gr.ColorPicker()
2210
assert color_picker_input.preprocess("#000000") == "#000000"
2211
assert color_picker_input.postprocess("#000000") == "#000000"
2212
assert color_picker_input.postprocess(None) is None
2213
assert color_picker_input.postprocess("#FFFFFF") == "#FFFFFF"
2215
assert color_picker_input.get_config() == {
2225
"interactive": None,
2227
"name": "colorpicker",
2229
"_selectable": False,
2232
def test_in_interface_as_input(self):
2236
iface = gr.Interface(lambda x: x, "colorpicker", "colorpicker")
2237
assert iface("#000000") == "#000000"
2239
def test_in_interface_as_output(self):
2244
iface = gr.Interface(lambda x: x, "colorpicker", gr.ColorPicker())
2245
assert iface("#000000") == "#000000"
2247
def test_static(self):
2251
component = gr.ColorPicker("#000000")
2252
assert component.get_config().get("value") == "#000000"
2256
def test_postprocess(self):
2257
url = "https://huggingface.co/Norod78/SDXL-VintageMagStyle-Lora/resolve/main/Examples/00015-20230906102032-7778-Wonderwoman VintageMagStyle _lora_SDXL-VintageMagStyle-Lora_1_, Very detailed, clean, high quality, sharp image.jpg"
2258
gallery = gr.Gallery([url])
2259
assert gallery.get_config()["value"] == [
2263
"orig_name": "00015-20230906102032-7778-Wonderwoman VintageMagStyle _lora_SDXL-VintageMagStyle-Lora_1_, Very detailed, clean, high quality, sharp image.jpg",
2268
"meta": {"_type": "gradio.FileData"},
2274
def test_gallery(self):
2275
gallery = gr.Gallery()
2276
Path(Path(__file__).parent, "test_files")
2278
postprocessed_gallery = gallery.postprocess(
2280
(str(Path("test/test_files/foo.png")), "foo_caption"),
2281
(Path("test/test_files/bar.png"), "bar_caption"),
2282
str(Path("test/test_files/baz.png")),
2283
Path("test/test_files/qux.png"),
2287
# Using str(Path(...)) to ensure that the test passes on all platforms
2288
assert postprocessed_gallery == [
2291
"path": str(Path("test") / "test_files" / "foo.png"),
2292
"orig_name": "foo.png",
2297
"meta": {"_type": "gradio.FileData"},
2299
"caption": "foo_caption",
2303
"path": str(Path("test") / "test_files" / "bar.png"),
2304
"orig_name": "bar.png",
2309
"meta": {"_type": "gradio.FileData"},
2311
"caption": "bar_caption",
2315
"path": str(Path("test") / "test_files" / "baz.png"),
2316
"orig_name": "baz.png",
2321
"meta": {"_type": "gradio.FileData"},
2327
"path": str(Path("test") / "test_files" / "qux.png"),
2328
"orig_name": "qux.png",
2333
"meta": {"_type": "gradio.FileData"},
2339
def test_gallery_preprocess(self):
2340
from gradio.components.gallery import GalleryData, GalleryImage
2342
gallery = gr.Gallery()
2343
img = GalleryImage(image=FileData(path="test/test_files/bus.png"))
2344
data = GalleryData(root=[img])
2346
preprocess = gallery.preprocess(data)
2347
assert preprocess[0][0] == "test/test_files/bus.png"
2349
gallery = gr.Gallery(type="numpy")
2351
gallery.preprocess(data)[0][0]
2352
== np.array(PIL.Image.open("test/test_files/bus.png"))
2355
gallery = gr.Gallery(type="pil")
2356
assert gallery.preprocess(data)[0][0] == PIL.Image.open(
2357
"test/test_files/bus.png"
2360
img_captions = GalleryImage(
2361
image=FileData(path="test/test_files/bus.png"), caption="bus"
2363
data = GalleryData(root=[img_captions])
2364
preprocess = gr.Gallery().preprocess(data)
2365
assert preprocess[0] == ("test/test_files/bus.png", "bus")
2369
def test_as_component(self):
2370
state = gr.State(value=5)
2371
assert state.preprocess(10) == 10
2372
assert state.preprocess("abc") == "abc"
2373
assert state.stateful
2375
def test_initial_value_deepcopy(self):
2376
with pytest.raises(TypeError):
2377
gr.State(value=gr) # modules are not deepcopyable
2379
@pytest.mark.asyncio
2380
async def test_in_interface(self):
2381
def test(x, y=" def"):
2382
return (x + y, x + y)
2384
io = gr.Interface(test, ["text", "state"], ["text", "state"])
2385
result = await io.call_function(0, ["abc"])
2386
assert result["prediction"][0] == "abc def"
2387
result = await io.call_function(0, ["abc", result["prediction"][0]])
2388
assert result["prediction"][0] == "abcabc def"
2390
@pytest.mark.asyncio
2391
async def test_in_blocks(self):
2392
with gr.Blocks() as demo:
2395
btn.click(lambda x: x + 1, score, score)
2397
result = await demo.call_function(0, [0])
2398
assert result["prediction"] == 1
2399
result = await demo.call_function(0, [result["prediction"]])
2400
assert result["prediction"] == 2
2403
def test_dataframe_process_example_converts_dataframes():
2404
df_comp = gr.Dataframe()
2405
assert df_comp.process_example(
2406
pd.DataFrame({"a": [1, 2, 3, 4], "b": [5, 6, 7, 8]})
2413
assert df_comp.process_example(np.array([[1, 2], [3, 4.0]])) == [
2419
@pytest.mark.parametrize("component", [gr.Model3D, gr.File, gr.Audio])
2420
def test_process_example_returns_file_basename(component):
2421
component = component()
2423
component.process_example("/home/freddy/sources/example.ext") == "example.ext"
2425
assert component.process_example(None) == ""
2429
"gradio.components.Component.process_example",
2430
spec=gr.components.Component.process_example,
2432
@patch("gradio.components.Image.process_example", spec=gr.Image.process_example)
2433
@patch("gradio.components.File.process_example", spec=gr.File.process_example)
2434
@patch("gradio.components.Dataframe.process_example", spec=gr.DataFrame.process_example)
2435
@patch("gradio.components.Model3D.process_example", spec=gr.Model3D.process_example)
2436
def test_dataset_calls_process_example(*mocks):
2438
components=[gr.Dataframe(), gr.File(), gr.Image(), gr.Model3D(), gr.Textbox()],
2441
pd.DataFrame({"a": np.array([1, 2, 3])}),
2449
assert all(m.called for m in mocks)
2452
cars = vega_datasets.data.cars()
2453
stocks = vega_datasets.data.stocks()
2454
barley = vega_datasets.data.barley()
2455
simple = pd.DataFrame(
2457
"a": ["A", "B", "C", "D", "E", "F", "G", "H", "I"],
2458
"b": [28, 55, 43, 91, 81, 53, 19, 87, 52],
2463
class TestScatterPlot:
2464
@patch.dict("sys.modules", {"bokeh": MagicMock(__version__="3.0.3")})
2465
def test_get_config(self):
2466
print(gr.ScatterPlot().get_config())
2467
assert gr.ScatterPlot().get_config() == {
2471
"interactive": None,
2474
"bokeh_version": "3.0.3",
2475
"show_actions_button": False,
2492
"color_legend_title": None,
2493
"size_legend_title": None,
2494
"shape_legend_title": None,
2495
"color_legend_position": None,
2496
"size_legend_position": None,
2497
"shape_legend_position": None,
2502
"x_label_angle": None,
2503
"y_label_angle": None,
2504
"_selectable": False,
2507
def test_no_color(self):
2508
plot = gr.ScatterPlot(
2510
y="Miles_per_Gallon",
2515
output = plot.postprocess(cars).model_dump()
2516
assert sorted(output.keys()) == ["chart", "plot", "type"]
2517
config = json.loads(output["plot"])
2518
assert config["encoding"]["x"]["field"] == "Horsepower"
2519
assert config["encoding"]["x"]["title"] == "Horse"
2520
assert config["encoding"]["y"]["field"] == "Miles_per_Gallon"
2521
assert config["title"] == "Car Data"
2522
assert "height" not in config
2523
assert "width" not in config
2525
def test_no_interactive(self):
2526
plot = gr.ScatterPlot(
2527
x="Horsepower", y="Miles_per_Gallon", tooltip="Name", interactive=False
2529
output = plot.postprocess(cars).model_dump()
2530
assert sorted(output.keys()) == ["chart", "plot", "type"]
2531
config = json.loads(output["plot"])
2532
assert "selection" not in config
2534
def test_height_width(self):
2535
plot = gr.ScatterPlot(
2536
x="Horsepower", y="Miles_per_Gallon", height=100, width=200
2538
output = plot.postprocess(cars).model_dump()
2539
assert sorted(output.keys()) == ["chart", "plot", "type"]
2540
config = json.loads(output["plot"])
2541
assert config["height"] == 100
2542
assert config["width"] == 200
2544
def test_xlim_ylim(self):
2545
plot = gr.ScatterPlot(
2546
x="Horsepower", y="Miles_per_Gallon", x_lim=[200, 400], y_lim=[300, 500]
2548
output = plot.postprocess(cars).model_dump()
2549
config = json.loads(output["plot"])
2550
assert config["encoding"]["x"]["scale"] == {"domain": [200, 400]}
2551
assert config["encoding"]["y"]["scale"] == {"domain": [300, 500]}
2553
def test_color_encoding(self):
2554
plot = gr.ScatterPlot(
2556
y="Miles_per_Gallon",
2561
output = plot.postprocess(cars).model_dump()
2562
config = json.loads(output["plot"])
2563
assert config["encoding"]["color"]["field"] == "Origin"
2564
assert config["encoding"]["color"]["scale"] == {
2565
"domain": ["USA", "Europe", "Japan"],
2568
assert config["encoding"]["color"]["type"] == "nominal"
2570
def test_two_encodings(self):
2571
plot = gr.ScatterPlot(
2573
title="Two encodings",
2575
y="Miles_per_Gallon",
2576
color="Acceleration",
2579
output = plot.postprocess(cars).model_dump()
2580
config = json.loads(output["plot"])
2581
assert config["encoding"]["color"]["field"] == "Acceleration"
2582
assert config["encoding"]["color"]["scale"] == {
2583
"domain": [cars.Acceleration.min(), cars.Acceleration.max()],
2586
assert config["encoding"]["color"]["type"] == "quantitative"
2588
assert config["encoding"]["shape"]["field"] == "Origin"
2589
assert config["encoding"]["shape"]["type"] == "nominal"
2591
def test_legend_position(self):
2592
plot = gr.ScatterPlot(
2594
title="Two encodings",
2596
y="Miles_per_Gallon",
2597
color="Acceleration",
2598
color_legend_position="none",
2599
color_legend_title="Foo",
2601
shape_legend_position="none",
2602
shape_legend_title="Bar",
2603
size="Acceleration",
2604
size_legend_title="Accel",
2605
size_legend_position="none",
2607
output = plot.postprocess(cars).model_dump()
2608
config = json.loads(output["plot"])
2609
assert config["encoding"]["color"]["legend"] is None
2610
assert config["encoding"]["shape"]["legend"] is None
2611
assert config["encoding"]["size"]["legend"] is None
2613
def test_scatterplot_accepts_fn_as_value(self):
2614
plot = gr.ScatterPlot(
2615
value=lambda: cars.sample(frac=0.1, replace=False),
2617
y="Miles_per_Gallon",
2620
assert isinstance(plot.value, dict)
2621
assert isinstance(plot.value["plot"], str)
2625
@patch.dict("sys.modules", {"bokeh": MagicMock(__version__="3.0.3")})
2626
def test_get_config(self):
2627
assert gr.LinePlot().get_config() == {
2631
"interactive": None,
2634
"bokeh_version": "3.0.3",
2635
"show_actions_button": False,
2646
"stroke_dash": None,
2647
"overlay_point": None,
2652
"color_legend_title": None,
2653
"stroke_dash_legend_title": None,
2654
"color_legend_position": None,
2655
"stroke_dash_legend_position": None,
2660
"x_label_angle": None,
2661
"y_label_angle": None,
2662
"_selectable": False,
2665
def test_no_color(self):
2669
tooltip=["symbol", "price"],
2670
title="Stock Performance",
2671
x_title="Trading Day",
2673
output = plot.postprocess(stocks).model_dump()
2674
assert sorted(output.keys()) == ["chart", "plot", "type"]
2675
config = json.loads(output["plot"])
2676
for layer in config["layer"]:
2677
assert layer["mark"]["type"] in ["line", "point"]
2678
assert layer["encoding"]["x"]["field"] == "date"
2679
assert layer["encoding"]["x"]["title"] == "Trading Day"
2680
assert layer["encoding"]["y"]["field"] == "price"
2682
assert config["title"] == "Stock Performance"
2683
assert "height" not in config
2684
assert "width" not in config
2686
def test_height_width(self):
2687
plot = gr.LinePlot(x="date", y="price", height=100, width=200)
2688
output = plot.postprocess(stocks).model_dump()
2689
assert sorted(output.keys()) == ["chart", "plot", "type"]
2690
config = json.loads(output["plot"])
2691
assert config["height"] == 100
2692
assert config["width"] == 200
2694
def test_xlim_ylim(self):
2695
plot = gr.LinePlot(x="date", y="price", x_lim=[200, 400], y_lim=[300, 500])
2696
output = plot.postprocess(stocks).model_dump()
2697
config = json.loads(output["plot"])
2698
for layer in config["layer"]:
2699
assert layer["encoding"]["x"]["scale"] == {"domain": [200, 400]}
2700
assert layer["encoding"]["y"]["scale"] == {"domain": [300, 500]}
2702
def test_color_encoding(self):
2704
x="date", y="price", tooltip="symbol", color="symbol", overlay_point=True
2706
output = plot.postprocess(stocks).model_dump()
2707
config = json.loads(output["plot"])
2708
for layer in config["layer"]:
2709
assert layer["encoding"]["color"]["field"] == "symbol"
2710
assert layer["encoding"]["color"]["scale"] == {
2711
"domain": ["MSFT", "AMZN", "IBM", "GOOG", "AAPL"],
2712
"range": [0, 1, 2, 3, 4],
2714
assert layer["encoding"]["color"]["type"] == "nominal"
2715
if layer["mark"]["type"] == "point":
2716
assert layer["encoding"]["opacity"] == {}
2718
def test_lineplot_accepts_fn_as_value(self):
2720
value=lambda: stocks.sample(frac=0.1, replace=False),
2725
assert isinstance(plot.value, dict)
2726
assert isinstance(plot.value["plot"], str)
2730
@patch.dict("sys.modules", {"bokeh": MagicMock(__version__="3.0.3")})
2731
def test_get_config(self):
2732
assert gr.BarPlot().get_config() == {
2736
"interactive": None,
2739
"bokeh_version": "3.0.3",
2740
"show_actions_button": False,
2757
"color_legend_title": None,
2758
"group_title": None,
2759
"color_legend_position": None,
2763
"x_label_angle": None,
2764
"y_label_angle": None,
2766
"_selectable": False,
2769
def test_no_color(self):
2774
title="Made Up Bar Plot",
2775
x_title="Variable A",
2778
output = plot.postprocess(simple).model_dump()
2779
assert sorted(output.keys()) == ["chart", "plot", "type"]
2780
assert output["chart"] == "bar"
2781
config = json.loads(output["plot"])
2782
assert config["encoding"]["x"]["sort"] == "x"
2783
assert config["encoding"]["x"]["field"] == "a"
2784
assert config["encoding"]["x"]["title"] == "Variable A"
2785
assert config["encoding"]["y"]["field"] == "b"
2786
assert config["encoding"]["y"]["title"] == "b"
2788
assert config["title"] == "Made Up Bar Plot"
2789
assert "height" not in config
2790
assert "width" not in config
2792
def test_height_width(self):
2793
plot = gr.BarPlot(x="a", y="b", height=100, width=200)
2794
output = plot.postprocess(simple).model_dump()
2795
assert sorted(output.keys()) == ["chart", "plot", "type"]
2796
config = json.loads(output["plot"])
2797
assert config["height"] == 100
2798
assert config["width"] == 200
2800
def test_ylim(self):
2801
plot = gr.BarPlot(x="a", y="b", y_lim=[15, 100])
2802
output = plot.postprocess(simple).model_dump()
2803
config = json.loads(output["plot"])
2804
assert config["encoding"]["y"]["scale"] == {"domain": [15, 100]}
2806
def test_horizontal(self):
2807
output = gr.BarPlot(
2811
x_title="Variable A",
2812
y_title="Variable B",
2813
title="Simple Bar Plot with made up data",
2818
assert output["value"]["chart"] == "bar"
2819
config = json.loads(output["value"]["plot"])
2820
assert config["encoding"]["x"]["field"] == "b"
2821
assert config["encoding"]["x"]["scale"] == {"domain": [20, 100]}
2822
assert config["encoding"]["x"]["title"] == "Variable B"
2824
assert config["encoding"]["y"]["field"] == "a"
2825
assert config["encoding"]["y"]["title"] == "Variable A"
2827
def test_barplot_accepts_fn_as_value(self):
2829
value=lambda: barley.sample(frac=0.1, replace=False),
2833
assert isinstance(plot.value, dict)
2834
assert isinstance(plot.value["plot"], str)
2838
def test_component_functions(self):
2840
Preprocess, postprocess, serialize, get_config
2844
assert code.preprocess("# hello friends") == "# hello friends"
2845
assert code.preprocess("def fn(a):\n return a") == "def fn(a):\n return a"
2858
test_file_dir = Path(Path(__file__).parent, "test_files")
2859
path = str(Path(test_file_dir, "test_label_json.json"))
2860
with open(path) as f:
2861
assert code.postprocess(path) == path
2862
assert code.postprocess((path,)) == f.read()
2864
assert code.get_config() == {
2877
"interactive": None,
2879
"_selectable": False,
2883
class TestFileExplorer:
2884
def test_component_functions(self):
2886
Preprocess, get_config
2888
file_explorer = gr.FileExplorer(file_count="single")
2890
config = file_explorer.get_config()
2891
assert config["glob"] == "**/*"
2892
assert config["value"] is None
2893
assert config["file_count"] == "single"
2894
assert config["server_fns"] == ["ls"]
2896
input_data = FileExplorerData(root=[["test/test_files/bus.png"]])
2897
preprocessed_data = file_explorer.preprocess(input_data)
2898
assert isinstance(preprocessed_data, str)
2899
assert Path(preprocessed_data).name == "bus.png"
2901
input_data = FileExplorerData(root=[])
2902
preprocessed_data = file_explorer.preprocess(input_data)
2903
assert preprocessed_data is None
2905
file_explorer = gr.FileExplorer(file_count="multiple")
2907
config = file_explorer.get_config()
2908
assert config["glob"] == "**/*"
2909
assert config["value"] is None
2910
assert config["file_count"] == "multiple"
2911
assert config["server_fns"] == ["ls"]
2913
input_data = FileExplorerData(root=[["test/test_files/bus.png"]])
2914
preprocessed_data = file_explorer.preprocess(input_data)
2915
assert isinstance(preprocessed_data, list)
2916
assert Path(preprocessed_data[0]).name == "bus.png"
2918
input_data = FileExplorerData(root=[])
2919
preprocessed_data = file_explorer.preprocess(input_data)
2920
assert preprocessed_data == []
2922
def test_file_explorer_txt_only_glob(self, tmpdir):
2924
(Path(tmpdir) / "foo" / "bar").mkdir()
2925
(Path(tmpdir) / "foo" / "file.txt").touch()
2926
(Path(tmpdir) / "foo" / "file2.txt").touch()
2927
(Path(tmpdir) / "foo" / "file3.log").touch()
2928
(Path(tmpdir) / "foo" / "img.png").touch()
2929
(Path(tmpdir) / "foo" / "bar" / "bar.txt").touch()
2931
file_explorer = gr.FileExplorer(glob="*.txt", root=Path(tmpdir))
2932
tree = file_explorer.ls(["foo"])
2935
{"name": "bar", "type": "folder", "valid": False},
2936
{"name": "file.txt", "type": "file", "valid": True},
2937
{"name": "file2.txt", "type": "file", "valid": True},
2939
assert tree == answer
2942
def test_component_class_ids():
2943
button_id = gr.Button().component_class_id
2944
textbox_id = gr.Textbox().component_class_id
2945
json_id = gr.JSON().component_class_id
2946
mic_id = gr.Mic().component_class_id
2947
microphone_id = gr.Microphone().component_class_id
2948
audio_id = gr.Audio().component_class_id
2950
assert button_id == gr.Button().component_class_id
2951
assert textbox_id == gr.Textbox().component_class_id
2952
assert json_id == gr.JSON().component_class_id
2953
assert mic_id == gr.Mic().component_class_id
2954
assert microphone_id == gr.Microphone().component_class_id
2955
assert audio_id == gr.Audio().component_class_id
2956
assert mic_id == microphone_id
2958
# Make sure that the ids are unique
2959
assert len({button_id, textbox_id, json_id, microphone_id, audio_id}) == 5
2962
def test_constructor_args():
2963
assert gr.Textbox(max_lines=314).constructor_args == {"max_lines": 314}
2964
assert gr.LoginButton(visible=False, value="Log in please").constructor_args == {
2966
"value": "Log in please",
2970
def test_template_component_configs(io_components):
2971
template_components = [c for c in io_components if getattr(c, "is_template", False)]
2972
for component in template_components:
2973
component_parent_class = inspect.getmro(component)[1]
2974
template_config = component().get_config()
2975
parent_config = component_parent_class().get_config()
2976
assert set(parent_config.keys()).issubset(set(template_config.keys()))
2979
def test_component_example_values(io_components):
2980
for component in io_components:
2981
if component == PDF:
2983
elif component in [gr.BarPlot, gr.LinePlot, gr.ScatterPlot]:
2984
c: Component = component(x="x", y="y")
2986
c: Component = component()
2987
c.postprocess(c.example_value())
2990
def test_component_example_payloads(io_components):
2991
for component in io_components:
2992
if component == PDF:
2994
elif component in [gr.BarPlot, gr.LinePlot, gr.ScatterPlot]:
2995
c: Component = component(x="x", y="y")
2997
c: Component = component()
2998
data = c.example_payload()
2999
data = processing_utils.move_files_to_cache(
3002
check_in_upload_folder=False,
3004
if getattr(c, "data_model", None) and data is not None:
3005
if issubclass(c.data_model, GradioModel): # type: ignore
3006
data = c.data_model(**data) # type: ignore
3007
elif issubclass(c.data_model, GradioRootModel): # type: ignore
3008
data = c.data_model(root=data) # type: ignore