gradio/test/test_components.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

3137 lines
107 KiB
Python
Raw Normal View History

"""
Tests for all of the components defined in components.py. Tests are divided into two types:
1. test_component_functions() are unit tests that check essential functions of a component, the functions that are checked are documented in the docstring.
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.
"""
Cleaning up the way data is processed for components (#1967) * remove preprocess_example * removing methods * added path support for images * fixes * video * formatting * fixing preprocess * fixes * removed from audio * fixed file * formatting * serialization * foramtting * formatting * removed save flag / restore flag * formatting * removed flagging * removed * load value * fixing typing * fixes, typing * fixes * file * handling images * formatting * fixed serializing for flagging * formatting * json * temp file * removed processing * changed processing * fixed temp FINALLY * flagging works * fix examples test * formatting * async examples * working on mix * comment out failing test * fixed interface problem * fix kitchen sink deprecation warning * gallery examples * fixes * fixes to serialization * fixing label serializing * fixed file serialization * kitchen sink restored * outbreak forecast updated * formatting * formatting and api mode * fix 1 test :/ * fixing tests * fixed components tests * remvoed test files * formatting * fixed examples * fixes * formatting * restored certain files * added encryption * fixed syntax mistake * formatting * fixed 1 test * clean up interface * formatting * fixed route tests * more fixes * formatting * formatting * fixing pipeline * format frontend * format backend * tweaks * fix * fix final test? * merged * Sanitize for CSV (#2017) * sanitize for csv * added sanitization logic * fixed examples * turn cache off * fixed example caching with optional inputs * fixed review problems * fixed Interface.load * updating the tests * updating the tests * fix * fixed seriailizing * testing * rewrite run prediction * formatting * await * fixes * formatting * finally fixed mix * fixed tests * formatting * formatting * deserialize fix * formatting * fixes * fixes * fix * fix tests * fixes Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com>
2022-08-23 23:31:04 +08:00
import filecmp
import json
import os
import pathlib # noqa: F401
import shutil
import tempfile
from copy import deepcopy
from difflib import SequenceMatcher
from pathlib import Path
from unittest.mock import MagicMock, patch
import numpy as np
import pandas as pd
import PIL
import pytest
import vega_datasets
from gradio_client import media_data
from gradio_client import utils as client_utils
from scipy.io import wavfile
2022-03-30 20:34:08 +08:00
import gradio as gr
from gradio import processing_utils, utils
from gradio.deprecation import (
GradioDeprecationWarning,
GradioUnusedKwargWarning,
)
os.environ["GRADIO_ANALYTICS_ENABLED"] = "False"
class TestComponent:
2022-04-15 16:18:56 +08:00
def test_component_functions(self):
"""
component
"""
assert isinstance(gr.components.component("textarea"), gr.templates.TextArea)
2022-04-15 16:18:56 +08:00
def test_raise_warnings():
for c_type, component in zip(
["inputs", "outputs"], [gr.inputs.Textbox, gr.outputs.Label]
):
with pytest.warns(UserWarning, match=f"Usage of gradio.{c_type}"):
component()
class TestTextbox:
def test_component_functions(self):
"""
Preprocess, postprocess, serialize, tokenize, get_config
"""
text_input = gr.Textbox()
assert text_input.preprocess("Hello World!") == "Hello World!"
assert text_input.postprocess("Hello World!") == "Hello World!"
assert text_input.postprocess(None) is None
assert text_input.postprocess("Ali") == "Ali"
assert text_input.postprocess(2) == "2"
assert text_input.postprocess(2.14) == "2.14"
assert text_input.serialize("Hello World!", True) == "Hello World!"
assert text_input.tokenize("Hello World! Gradio speaking.") == (
["Hello", "World!", "Gradio", "speaking."],
[
"World! Gradio speaking.",
"Hello Gradio speaking.",
"Hello World! speaking.",
"Hello World! Gradio",
],
None,
)
text_input.interpretation_replacement = "unknown"
assert text_input.tokenize("Hello World! Gradio speaking.") == (
["Hello", "World!", "Gradio", "speaking."],
[
"unknown World! Gradio speaking.",
"Hello unknown Gradio speaking.",
"Hello World! unknown speaking.",
"Hello World! Gradio unknown",
],
None,
)
assert text_input.get_config() == {
"lines": 1,
"max_lines": 20,
"placeholder": None,
"value": "",
"name": "textbox",
"show_copy_button": False,
"show_label": True,
"type": "text",
"label": None,
"container": True,
"min_width": 160,
"scale": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"interactive": None,
"root_url": None,
"rtl": False,
"text_align": None,
"autofocus": False,
"selectable": False,
"info": None,
"autoscroll": True,
}
@pytest.mark.asyncio
async def test_in_interface_as_input(self):
"""
Interface, process, interpret,
"""
iface = gr.Interface(lambda x: x[::-1], "textbox", "textbox")
assert iface("Hello") == "olleH"
iface = gr.Interface(
lambda sentence: max([len(word) for word in sentence.split()]),
gr.Textbox(),
"number",
interpretation="default",
)
scores = await iface.interpret(
["Return the length of the longest word in this sentence"]
)
assert scores[0]["interpretation"] == [
("Return", 0.0),
(" ", 0),
("the", 0.0),
(" ", 0),
("length", 0.0),
(" ", 0),
("of", 0.0),
(" ", 0),
("the", 0.0),
(" ", 0),
("longest", 0.0),
(" ", 0),
("word", 0.0),
(" ", 0),
("in", 0.0),
(" ", 0),
("this", 0.0),
(" ", 0),
("sentence", 1.0),
(" ", 0),
]
def test_in_interface_as_output(self):
"""
Interface, process
"""
iface = gr.Interface(lambda x: x[-1], "textbox", gr.Textbox())
assert iface("Hello") == "o"
iface = gr.Interface(lambda x: x / 2, "number", gr.Textbox())
assert iface(10) == "5.0"
def test_static(self):
"""
postprocess
"""
component = gr.Textbox("abc")
assert component.get_config().get("value") == "abc"
def test_override_template(self):
"""
override template
"""
component = gr.TextArea(value="abc")
assert component.get_config().get("value") == "abc"
assert component.get_config().get("lines") == 7
component = gr.TextArea(value="abc", lines=4)
assert component.get_config().get("value") == "abc"
assert component.get_config().get("lines") == 4
def test_faulty_type(self):
with pytest.raises(
ValueError, match='`type` must be one of "text", "password", or "email".'
):
gr.Textbox(type="boo")
def test_max_lines(self):
assert gr.Textbox(type="password").get_config().get("max_lines") == 1
assert gr.Textbox(type="email").get_config().get("max_lines") == 1
assert gr.Textbox(type="text").get_config().get("max_lines") == 20
assert gr.Textbox().get_config().get("max_lines") == 20
class TestNumber:
def test_component_functions(self):
"""
Preprocess, postprocess, serialize, set_interpret_parameters, get_interpretation_neighbors, get_config
"""
numeric_input = gr.Number(elem_id="num", elem_classes="first")
assert numeric_input.preprocess(3) == 3.0
assert numeric_input.preprocess(None) is None
assert numeric_input.postprocess(3) == 3
assert numeric_input.postprocess(3) == 3.0
assert numeric_input.postprocess(2.14) == 2.14
assert numeric_input.postprocess(None) is None
assert numeric_input.serialize(3, True) == 3
numeric_input.set_interpret_parameters(steps=3, delta=1, delta_type="absolute")
assert numeric_input.get_interpretation_neighbors(1) == (
[-2.0, -1.0, 0.0, 2.0, 3.0, 4.0],
{},
)
numeric_input.set_interpret_parameters(steps=3, delta=1, delta_type="percent")
assert numeric_input.get_interpretation_neighbors(1) == (
[0.97, 0.98, 0.99, 1.01, 1.02, 1.03],
{},
)
assert numeric_input.get_config() == {
"value": None,
"name": "number",
"show_label": True,
"step": 1,
"label": None,
gr.Number() max/min limit (#3991) * Add min max handling for Number (#3871) * feat: add min max handling for Number * Update CHANGELOG.md * fix: Error when min or max is not specified * fix formatting * fix: error when nothing is specified * Just put infinity in min and max --------- Co-authored-by: Dawood Khan <dawoodkhan82@gmail.com> * number limit * Update gradio/components.py Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * New Version Docs (#4027) * [create-pull-request] automated change * Trigger Build --------- Co-authored-by: aliabd <aliabd@users.noreply.github.com> Co-authored-by: aliabd <ali.si3luwa@gmail.com> * Safer `HuggingFaceDatasetSaver` (and deprecate `HuggingFaceDatasetJsonSaver`) (#3973) * Draft for a safer HuggingFaceDatasetSaver * Rename (and replace) gr.SaferHuggingFaceDatasetSaver as gr.HuggingFaceDatasetSaver * update changelog * ruff * doc * tmp work * merge 2 classes * remove useless code * adapt tests * Update gradio/flagging.py Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Update CHANGELOG.md * fix typing * code formatting * removed print from tests * removing imports * removing imports * fix paths * formatting * wording * formating * fix tests --------- Co-authored-by: testbot <lucainp@hf.co> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * merge * Allow state to be rendered multiple times (#4030) * state render * add test * formatting * changelog * Allow decoding b64 string without header in processing utils (#4031) * allow decoding b64 string without headers * install gradio-client in edittable mode * update GH actions * add test for decoding headerless b64 * add test for decoding headerless b64 image * some linting * fix test --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Sets matplotlib backend to agg before rendering math (#4029) * matplotlib-agg * fix * context manager * Update CHANGELOG.md * update demos * linting * removed warning * fix test * fixes * fix tests * Upgrade pyright to 1.1.305 (#4042) * Fastapi Python Client Guide (#3892) * fastapi guide * changelog * writing * finish guide * fix * Update guides/06_client-libraries/fastapi-app-with-the-gradio-client.md Co-authored-by: Ali Abdalla <ali.si3luwa@gmail.com> * Update guides/06_client-libraries/fastapi-app-with-the-gradio-client.md Co-authored-by: Ali Abdalla <ali.si3luwa@gmail.com> * Update guides/06_client-libraries/fastapi-app-with-the-gradio-client.md Co-authored-by: Ali Abdalla <ali.si3luwa@gmail.com> * Update guides/06_client-libraries/fastapi-app-with-the-gradio-client.md Co-authored-by: Ali Abdalla <ali.si3luwa@gmail.com> * dependencies * html --------- Co-authored-by: Ali Abdalla <ali.si3luwa@gmail.com> * fix overflowing gutter and dark mode base color (#4051) * Add ability to blocklist filepaths, ability to specify where gradio temp files are created (#4047) * temporary file * tests * formatting * rename * added another test * guide * formatting * changelog * added custom gradio temp directory (#4053) * added custom gradio temp directory * Update 03_sharing-your-app.md * rename test * address review * remove print * Chatbot code syntax highlighting (#4048) * first pass * fixes * more fixes * remove breaks * format * version * pr fixes * changelog * test fix * background color * format * revert test fix * changes * changes * test * changes * changes * changes * changes * changes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: Ali Abid <aabid94@gmail.com> * Fixes issue with indentation in code field with streaming (#4043) * indent fix * fix * changelog * fix overflowing gutter and dark mode base color (#4051) * Add ability to blocklist filepaths, ability to specify where gradio temp files are created (#4047) * temporary file * tests * formatting * rename * added another test * guide * formatting * changelog * added custom gradio temp directory (#4053) * added custom gradio temp directory * Update 03_sharing-your-app.md * rename test * address review * remove print * Chatbot code syntax highlighting (#4048) * first pass * fixes * more fixes * remove breaks * format * version * pr fixes * changelog * test fix * background color * format * revert test fix * changes * changes * test * changes * changes * changes * changes * changes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: Ali Abid <aabid94@gmail.com> * fix * fix test --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: pngwn <hello@pngwn.io> Co-authored-by: Ali Abid <aabid94@gmail.com> * [create-pull-request] automated change (#4059) Co-authored-by: aliabid94 <aliabid94@users.noreply.github.com> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * changelog (#4064) * New Version Docs (#4069) * [create-pull-request] automated change * Trigger Build --------- Co-authored-by: aliabd <aliabd@users.noreply.github.com> Co-authored-by: aliabd <ali.si3luwa@gmail.com> * Soft theme fix (#4070) * fix * fix --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Empty gallery fix (#4072) * changes * changes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix bug where functions with type hints caused errors (#4068) * Fix + test * CHANGELOG * Update test/test_utils.py Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Update gradio/utils.py Co-authored-by: Abubakar Abid <abubakar@huggingface.co> --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * More Ruff rules (#4038) * Bump ruff to 0.0.264 * Enable Ruff Naming rules and fix most errors * Move `clean_html` to utils (to fix an N lint error) * Changelog * Clean up possibly leaking file handles * Enable and autofix Ruff SIM * Fix remaining Ruff SIMs * Enable and autofix Ruff UP issues * Fix misordered import from #4048 * Fix bare except from #4048 --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * [WIP] Language Agnostic Typing in `/info` route (#4039) * First commit * All serializers * Remove output type * Add route * Format json * Modify dropdown and slider choices * Fix impl * Lint * Add tests * Fix lint * remove breakpoint * Tests passing locally * Format code * Address comments * Use union + fix tests * handle multiple file case * Add serializer to info payload * lint * Add to CHANGELOG * grc version * requirements * fix test --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Keep hidden Accordion content in DOM (#4073) * changes * changes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Theme builder fixes (#4080) * theme-builder-fixes * theme-builder-fixes * fix expand issue * changes * Update gradio/themes/builder_app.py * changelog --------- Co-authored-by: Ali Abid <aabid94@gmail.com> * Misc file and docs fixes (#4086) * uvicorn version * uvicorn version * changes * guides * guide * changelog * typo * typo * Update guides/04_integrating-other-frameworks/01_using-hugging-face-integrations.md * chinese lang * rename * Update guides/04_integrating-other-frameworks/01_using-hugging-face-integrations.md * Update guides/03_building-with-blocks/04_custom-CSS-and-JS.md Co-authored-by: aliabid94 <aabid94@gmail.com> * address review * simplify section --------- Co-authored-by: aliabid94 <aabid94@gmail.com> * Removing "State" from view API info (#4107) * wip pr * update client version * update space fetcher * changelog, workflow * fix not flaky tests * lint * v2 * Dont send request to `/info` if version before 3.28.3 (#4109) * Add code * Lint * CHANGELOG --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Upload audio ios (#4071) * changes * changes * change * changes * changes * changes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Allow textbox / number submits to trigger Interface submit (#4090) * changes * changes * changes * changes * changes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix slider released event not triggering when released on mobile (#4098) * Fix slider released event not triggering when released on mobile * Update CHANGELOG * fix range test * retrigger --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix then logic to work after failures (#4115) * change * changes * changes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fixes to view API page (#4112) * logo * fix for new info and logo path * changelog * remove example_input from returns --------- Co-authored-by: Ali Abdalla <ali.si3luwa@gmail.com> * Add support for async generators (#3821) * Add impl + unit test * CHANGELOG * Lint * Type check * Remove print * Fix tests * revert change * Lint * formatting * Fix test * Lint --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: Ali Abid <aabid94@gmail.com> * release (#4116) * Bumpt client version (#4125) * New Version Docs (#4131) * [create-pull-request] automated change * Trigger Build --------- Co-authored-by: aliabd <aliabd@users.noreply.github.com> Co-authored-by: aliabd <ali.si3luwa@gmail.com> * Fix create version docs action (#4130) * define version instead of upgrading * add sleep --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix dev docs (#4132) * Move .config/README.md to js/README.md * Link js/README.md from CONTRIBUTING.md * Update CHANGELOG.md --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * changelog (#4136) * Fix website build issue (#4142) * upgrade pnpm * changelgo * Fix python client test (#4138) * Fix python client test * CHANGELOG --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix isssue with running with nginx (#4133) * nginx-root * fix * ability to set root path * removed root * removed root * fix * changelog * Update gradio/routes.py Co-authored-by: aliabid94 <aabid94@gmail.com> * Update gradio/routes.py Co-authored-by: aliabid94 <aabid94@gmail.com> --------- Co-authored-by: aliabid94 <aabid94@gmail.com> * Record username when flagging (#4135) * record username * fix * changelog fix * format * fix hf saver * fix deserialization * fixes * Fix api info for File component (#4153) * Fix output file type info * Fix example inputs * CHANGELOG * Update client * Add test * Bump version * Bump min client version * Update .prettierignore adding client/js/dist and .venv (#4160) * Fix the prettier.ignorePath field in the VSCode workspace settings (#4164) Co-authored-by: pngwn <hello@pngwn.io> * simplify format of changelog (#4163) * Fix the wildcard in .editorconfig to match files in nested directories (#4165) * Fix the wildcard in .editorconfig to match files in nested directories * Remove a wrong whitespace in a brace expansion notation in .editorconfig --------- Co-authored-by: pngwn <hello@pngwn.io> * Fix flaky interface test (#4168) * Fix test * Lint * Fix vs code lint * Adds missing components to gradio client serializing's component mapping (#4167) * add missing serialization * format * update release note format * update release note format * fix test * Release 3.30 (#4166) * release * requirements * [Docs] Resolve numerous typos (#4170) * Resolve numerous typos * Delete test.py * Run generate_notebooks * notebooks --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * New Version Docs (#4172) * [create-pull-request] automated change * Update v3.30.0_template.html --------- Co-authored-by: abidlabs <abidlabs@users.noreply.github.com> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Dispatch dropdown change on value change for any reason (#4128) * changes * changes * changes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * hotfix for test (#4173) * hotfix for test * removed comment * 3712 js client (#3899) * update ci (#4184) * bump client version (#4185) * bump client version * ignore spaces-test * Fix (#4186) * bump client version * ignore spaces-test * fix * update token for npm action (#4187) * change (#4189) * ci typo (#4190) * Fix npm publish again again (#4191) * ci typo * fix * Fix npm publish again again (#4192) * ci typo * fix * again * Fix npm publish again again (#4193) * ci typo * fix * again * again * Add format argument to Audio (#4178) * experimental * Add test * Rename to format * Rename * CHANGELOG * Add to docstring * Update gradio/components.py Co-authored-by: Abubakar Abid <abubakar@huggingface.co> --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * chore: update versions (#4188) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Fix npm publish again again (#4195) * ci typo * fix * again * again * again * client docs tweaks (#4196) * ci typo * fix * again * again * again * ignore workbench * small tweaks for publish + docs * Fix "TypeError: issubclass() arg 1 must be a class" When Optional args (#4200) * fix "issubclass() arg 1 must be a class" when args is Optional * Update CHANGELOG.md add fix "TypeError: issubclass() arg 1 must be a class" when use Optional args * Update gradio/helpers.py Co-authored-by: Aarni Koskela <akx@iki.fi> * changelog * formatting --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: Aarni Koskela <akx@iki.fi> * Fix semiver import (#4201) * fix token (#4208) * fix token * add label * Fix Explanation Regarding NumPy Image Component (#4204) * 20230513 swap np height and width in docs * changelog --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Correct stacklevel for check_deprecated_parameters (#4203) Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Programmatically launch reload to allow factories and arguments to be passed to the app (#4119) * Programmatically lauch reload to allow factories and arguments to be passed to the app * add warning * modify warning * guide fixes * formatting * changes * warning * import fix * fix tests * fix tests --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Update CONTRIBUTING.md (#4220) * Input listener (#4157) * changes * changes * changes * changes * changes * changes * changes * chnages * fix * changes * changes * merge * changes * restore --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Do not do any analytics requests if analytics are disabled (#4194) * Move analytics-related bits to gradio.analytics * Do not do any analytics requests if analytics are disabled * Remove unused log_feature_analytics * removed redundant analytics, rewrote * renamed * save * fixed test' --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Increase websocket messaging timeout (#4235) * increase websocket timeout * changelog * Fix for `typing.get_type_hints()` on Python 3.9 or lower (#4228) * fix * fix docstring * type hint fix * fix test * Update gradio/utils.py Co-authored-by: Aarni Koskela <akx@iki.fi> * fix indentation --------- Co-authored-by: Aarni Koskela <akx@iki.fi> * Some tweaks to the Client (#4230) * parameter names * tweaks * separate out serialize * fix * changelog * fix * fix * improve test * Only allow messaging update if analytics is enabled (#4236) * Only allow messaging update if analytics are allowed Follows up on #4194 * Remove duplicate changelog entry * remove circular import --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix client filepaths (#4202) * transform returned paths to useful URLs * changeset * update app * revert * revert * changelog * Update client/js/src/client.ts Co-authored-by: aliabid94 <aabid94@gmail.com> * format --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: aliabid94 <aabid94@gmail.com> * fix cancels (#4225) * fix cancels * changelog * refactor to make it work * chore: update versions (#4207) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Fix publish (#4240) * fix npm publish * fix npm publish * release (#4219) Co-authored-by: pngwn <hello@pngwn.io> * Fixes chatbot_dialogpt demo (#4238) * demo fix * changelog * fix * demo --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix JSONDecodeError (#4241) * Fix JSONDecodeError bug (#4237) * Remove unused import * Clean up code * Fix JSONDecodeError (#4241) * Accept all Exceptions --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * make workbench private (#4247) * Refactoring (#4223) * Replace var with const in js/app/src/main.ts * Remove unnecessary nullish coalescing in js/app/src/main.ts * Remove unnecessary white spaces in the NPM scripts in js/app/package.json * Use object key-value shorthand * changelog --------- Co-authored-by: pngwn <hello@pngwn.io> * Move mount_css() from main.ts to css.ts (#4222) * Move mount_css() from main.ts to css.ts because these is a circular dependency between main.ts and Index.svelte (and it will help the development of the Wasm ver in the future) * changelog --------- Co-authored-by: pngwn <hello@pngwn.io> * [create-pull-request] automated change (#4250) Co-authored-by: aliabd <aliabd@users.noreply.github.com> * Fix run on click (#4258) * fix run on click * changelog * Upgrade black to 23.3 (#4259) * Upgrade black * Conservatively upgrade packaging too since it's black's dependency * Using marked for chatbot markdown parsing (#4150) * fix info request in js client (#4271) * fix info request in js client * changelog * Temp file fixes (#4256) * Fix bug * Linting * CHANGELOG * Add tests * Update test * Fix remaining components + add tests * Fix tests * Fix tests * Address comments * Ensure error modal display as expected when using the queue (#4273) * Allow passing FastAPI app options (#4282) * App: don't force docs_url and redoc_url to None * App.create_app: allow passing in app_kwargs * start_server + launch: allow passing in app_kwargs * Changelog * Apply suggestions from code review Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Use .launch for tests --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Katex support in chatbot (#4285) * katex * katex support * changelog * fixes * pr fixes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Release 3.32.0 (#4293) * release 3.32.0 * changelog * New Version Docs (#4296) * [create-pull-request] automated change * Update v3.32.0_template.html --------- Co-authored-by: abidlabs <abidlabs@users.noreply.github.com> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Add overridden type annotations on `normalise_file()` to remove @ts-i… (#4315) * Add overridden type annotations on `normalise_file()` to remove @ts-ignore, and remove its unnecessary export * changeset --------- Co-authored-by: pngwn <hello@pngwn.io> * typo (minor): extra newline puts the documentation of colums to grid (#4337) * typo (minor): extra newline puts the documentation of colums to grid * edited changelog * changelog --------- Co-authored-by: thiswillbeyourgithub <github@32mail.33mail.com> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * return a Dependency instance from Blocks.load event listener (#4304) * return a Dependency instance from Blocks.load event listener * a test case for chaining then from load event * update CHANGELOG * add test for load.then with blocks re-used * fixes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix typo in client/js/README.md (#4310) Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * chore: update versions (#4283) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Optimize frontend's is_dep calls (#4334) * Optimize is_dep (36 to 12 msec) * Call is_dep less (12 msec to 9 msec) * Changelog --------- Co-authored-by: pngwn <hello@pngwn.io> * various client refactors + tweaks (#4357) * changeset * Add a type annotation on the `api` variable to which the return value of `view_config()` is assigned, and update the type annotation and exception handling on `view_config` as well (#4311) * Remove unnecessary @ts-ignore (#4314) * Remove unnecessary Promise wrapping another promise (#4313) * Remove unnecessary Promise wrapping another promise * Remove an error handeler that may remove detailed error stacks * changeset * remove changeset --------- Co-authored-by: pngwn <hello@pngwn.io> * Stop using `let` for unchanged variables in `client.ts` (#4312) * Stop using `let` for unchanged variables in `client.ts` * fixes --------- Co-authored-by: pngwn <hello@pngwn.io> --------- Co-authored-by: Yuichiro Tachibana (Tsuchiya) <t.yic.yt@gmail.com> * Remove a bunch of unused frontend code (#4275) Co-authored-by: pngwn <hello@pngwn.io> * Respect `interactive=True` in output of `gr.Interface` (#4356) * tests * changelog * lint * Update gradio/interface.py Co-authored-by: Aarni Koskela <akx@iki.fi> * format --------- Co-authored-by: Aarni Koskela <akx@iki.fi> * Don't allow dotfiles for /file= route (#4303) * Don't allow dotfiles or files in "dot directories" for /file= * update guide --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Push to spaces (#4033) * changes * first commit * Update gradio/upload.py Co-authored-by: Aarni Koskela <akx@iki.fi> * Update gradio/upload.py Co-authored-by: Aarni Koskela <akx@iki.fi> * changes * changes * changes * changes * changes * changes * changes * chnages * changes * changes * changes * changes * Update 03_sharing-your-app.md * changes * changes * change * changes * changes * changes * Update gradio/deploy_space.py Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * changes * changes * changes --------- Co-authored-by: Aarni Koskela <akx@iki.fi> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Do not send HF token to other domains via `/proxy` (#4368) * test * fix * changelog * fix, add warnings * Make chatbot input fields non-interactive while bot is streaming (#4363) * Add demo impl * trigger then if generating * remove unused value * CHANGELOG * Fix code * Update guide * Update guides/07_other-tutorials/creating-a-chatbot.md Co-authored-by: pngwn <hello@pngwn.io> --------- Co-authored-by: pngwn <hello@pngwn.io> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Prevent path traversal in `/file` routes (#4370) * add tests * add tests * file route fix * update tests * formatting * file access * cleanup * cleaning * fix tests * Favicon fix for Windows (#4369) * favicon fix * changelog * svg * remove favicon * actual fix * Add pypi classifiers to pyproject.toml (#4383) * Add pypi classifiers to pyproject.toml * Add OS classifier --------- Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com> * Use DOMPurify to sanitize html in chatbot (#4360) * dompurify * changelog * format * clean * changelog * Update run.py * update happy-dom --------- Co-authored-by: pngwn <hello@pngwn.io> * fix copy button invalid & copy button (invisible) duplication bug in chatbot (#4350) * fix a copy button duplication bug in chatbot * fix copy button invalid issue * Update CHANGELOG.md: Fixed Copy Button * fix changelog typo * switch to static HTML + event delegation for copy button * fix * format + notebooks * format + notebooks --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: pngwn <hello@pngwn.io> * release 3.33.0 (#4392) Co-authored-by: aliabid94 <aabid94@gmail.com> * Restore offline support (#4398) * changes * changes * changes * New Version Docs (#4397) * [create-pull-request] automated change * Update temporary_template.html --------- Co-authored-by: abidlabs <abidlabs@users.noreply.github.com> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix Base parent in Docs, add Group (#4391) * fix base parent * add group to docs --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Remove old versioned docs and fix repo classification (#4362) * remove old versioned docs * delete versioned docs when new one is created * ignore website dir in linguist calc * upload and download versioned docs * modify github action * remove gitattributes file --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Update message when share link binary is blocked (#4380) * update share link message * address suggestion * changelog * fix * formatting * Update utils.py for validate_url (#4388) * Update utils.py for validate_url AWS s3 presigned url cannot work for both HEAD and GET. So when HEAD the presigned url, it will return 403(Forbidden) * Update gradio/utils.py * changelog --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * v3.33.1 + Guide on setting up Gradio behind nginx... (#4379) * nginx guide * delete 3.33.0 * version * unindent * Prevent label change event from triggering itself (#4371) * Fix the Node and pnpm setup actions (#4394) * Run `pnpm i` with pnpm@8.6.0 to re-generate the lock file (#4393) * fix indent (#4404) * Throttle scroll event (#4158) * Throttle scroll event This decreases the amount of function calls when scrolling through the documentation website. * fix themes base --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: Ali Abdalla <ali.si3luwa@gmail.com> * merge * fixes * changes * more changes * notebook * changelog * error handle backend * Update gradio/components.py Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Update gradio/components.py Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Adds `variant` and `interactive` props to `gr.UploadButton` (#4436) * upload button * fix index * changelog * formatting * cleanup * fix get_continuous_fn bug when having every (#4434) * fix the bug for wrap continuous func with parameter every while origin func return generator * Update utils.py * Update CHANGELOG.md * Update test_utils.py * Update CHANGELOG.md * formatting --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix Safari video playback (#4433) * changes * changes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * test fix * test * tests * fix ui test * format * Increase version gradio-client version/changelog (#4441) * Increase version gradio-client version/changelog * req --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * fixes * notebook * fixed tests finally * format * python test fix * test fix * remove style from test * Update CHANGELOG.md * theme test fix --------- Co-authored-by: Artemy Egorov <artegoser@gmail.com> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: aliabd <aliabd@users.noreply.github.com> Co-authored-by: aliabd <ali.si3luwa@gmail.com> Co-authored-by: Lucain <lucainp@gmail.com> Co-authored-by: testbot <lucainp@hf.co> Co-authored-by: 1lint <105617163+1lint@users.noreply.github.com> Co-authored-by: Aarni Koskela <akx@iki.fi> Co-authored-by: pngwn <hello@pngwn.io> Co-authored-by: Ali Abid <aabid94@gmail.com> Co-authored-by: aliabid94 <aliabid94@users.noreply.github.com> Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com> Co-authored-by: space-nuko <24979496+space-nuko@users.noreply.github.com> Co-authored-by: Yuichiro Tachibana (Tsuchiya) <t.yic.yt@gmail.com> Co-authored-by: Tom Aarsen <37621491+tomaarsen@users.noreply.github.com> Co-authored-by: abidlabs <abidlabs@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: LingFeng.Chen.Cn <lingfeng.chen.cn@gmail.com> Co-authored-by: Der Chien <b03902015@ntu.edu.tw> Co-authored-by: Micky Brunetti <micky2be@users.noreply.github.com> Co-authored-by: David Ai <davidai2018@gmail.com> Co-authored-by: thiswillbeyourgithub <26625900+thiswillbeyourgithub@users.noreply.github.com> Co-authored-by: thiswillbeyourgithub <github@32mail.33mail.com> Co-authored-by: Paul Garner <ego@anentropic.com> Co-authored-by: WilliamRoyNelson <william.roy.nelson@gmail.com> Co-authored-by: binary-husky <96192199+binary-husky@users.noreply.github.com> Co-authored-by: Yan <alvindaiyan@gmail.com> Co-authored-by: Shavit <shavit@users.noreply.github.com> Co-authored-by: dkjshk <xie0510@126.com>
2023-06-11 09:12:11 +08:00
"minimum": None,
"maximum": None,
"container": True,
"min_width": 160,
"scale": None,
"elem_id": "num",
"elem_classes": ["first"],
"visible": True,
"interactive": None,
"root_url": None,
"info": None,
"precision": None,
}
def test_component_functions_integer(self):
"""
Preprocess, postprocess, serialize, set_interpret_parameters, get_interpretation_neighbors, get_template_context
"""
numeric_input = gr.Number(precision=0, value=42)
assert numeric_input.preprocess(3) == 3
assert numeric_input.preprocess(None) is None
assert numeric_input.postprocess(3) == 3
assert numeric_input.postprocess(3) == 3
assert numeric_input.postprocess(2.85) == 3
assert numeric_input.postprocess(None) is None
assert numeric_input.serialize(3, True) == 3
numeric_input.set_interpret_parameters(steps=3, delta=1, delta_type="absolute")
assert numeric_input.get_interpretation_neighbors(1) == (
[-2.0, -1.0, 0.0, 2.0, 3.0, 4.0],
{},
)
numeric_input.set_interpret_parameters(steps=3, delta=1, delta_type="percent")
assert numeric_input.get_interpretation_neighbors(100) == (
[97.0, 98.0, 99.0, 101.0, 102.0, 103.0],
{},
)
with pytest.raises(ValueError) as error:
numeric_input.get_interpretation_neighbors(1)
assert error.msg == "Cannot generate valid set of neighbors"
numeric_input.set_interpret_parameters(
steps=3, delta=1.24, delta_type="absolute"
)
with pytest.raises(ValueError) as error:
numeric_input.get_interpretation_neighbors(4)
assert error.msg == "Cannot generate valid set of neighbors"
assert numeric_input.get_config() == {
"value": 42,
"name": "number",
"show_label": True,
"step": 1,
"label": None,
gr.Number() max/min limit (#3991) * Add min max handling for Number (#3871) * feat: add min max handling for Number * Update CHANGELOG.md * fix: Error when min or max is not specified * fix formatting * fix: error when nothing is specified * Just put infinity in min and max --------- Co-authored-by: Dawood Khan <dawoodkhan82@gmail.com> * number limit * Update gradio/components.py Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * New Version Docs (#4027) * [create-pull-request] automated change * Trigger Build --------- Co-authored-by: aliabd <aliabd@users.noreply.github.com> Co-authored-by: aliabd <ali.si3luwa@gmail.com> * Safer `HuggingFaceDatasetSaver` (and deprecate `HuggingFaceDatasetJsonSaver`) (#3973) * Draft for a safer HuggingFaceDatasetSaver * Rename (and replace) gr.SaferHuggingFaceDatasetSaver as gr.HuggingFaceDatasetSaver * update changelog * ruff * doc * tmp work * merge 2 classes * remove useless code * adapt tests * Update gradio/flagging.py Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Update CHANGELOG.md * fix typing * code formatting * removed print from tests * removing imports * removing imports * fix paths * formatting * wording * formating * fix tests --------- Co-authored-by: testbot <lucainp@hf.co> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * merge * Allow state to be rendered multiple times (#4030) * state render * add test * formatting * changelog * Allow decoding b64 string without header in processing utils (#4031) * allow decoding b64 string without headers * install gradio-client in edittable mode * update GH actions * add test for decoding headerless b64 * add test for decoding headerless b64 image * some linting * fix test --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Sets matplotlib backend to agg before rendering math (#4029) * matplotlib-agg * fix * context manager * Update CHANGELOG.md * update demos * linting * removed warning * fix test * fixes * fix tests * Upgrade pyright to 1.1.305 (#4042) * Fastapi Python Client Guide (#3892) * fastapi guide * changelog * writing * finish guide * fix * Update guides/06_client-libraries/fastapi-app-with-the-gradio-client.md Co-authored-by: Ali Abdalla <ali.si3luwa@gmail.com> * Update guides/06_client-libraries/fastapi-app-with-the-gradio-client.md Co-authored-by: Ali Abdalla <ali.si3luwa@gmail.com> * Update guides/06_client-libraries/fastapi-app-with-the-gradio-client.md Co-authored-by: Ali Abdalla <ali.si3luwa@gmail.com> * Update guides/06_client-libraries/fastapi-app-with-the-gradio-client.md Co-authored-by: Ali Abdalla <ali.si3luwa@gmail.com> * dependencies * html --------- Co-authored-by: Ali Abdalla <ali.si3luwa@gmail.com> * fix overflowing gutter and dark mode base color (#4051) * Add ability to blocklist filepaths, ability to specify where gradio temp files are created (#4047) * temporary file * tests * formatting * rename * added another test * guide * formatting * changelog * added custom gradio temp directory (#4053) * added custom gradio temp directory * Update 03_sharing-your-app.md * rename test * address review * remove print * Chatbot code syntax highlighting (#4048) * first pass * fixes * more fixes * remove breaks * format * version * pr fixes * changelog * test fix * background color * format * revert test fix * changes * changes * test * changes * changes * changes * changes * changes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: Ali Abid <aabid94@gmail.com> * Fixes issue with indentation in code field with streaming (#4043) * indent fix * fix * changelog * fix overflowing gutter and dark mode base color (#4051) * Add ability to blocklist filepaths, ability to specify where gradio temp files are created (#4047) * temporary file * tests * formatting * rename * added another test * guide * formatting * changelog * added custom gradio temp directory (#4053) * added custom gradio temp directory * Update 03_sharing-your-app.md * rename test * address review * remove print * Chatbot code syntax highlighting (#4048) * first pass * fixes * more fixes * remove breaks * format * version * pr fixes * changelog * test fix * background color * format * revert test fix * changes * changes * test * changes * changes * changes * changes * changes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: Ali Abid <aabid94@gmail.com> * fix * fix test --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: pngwn <hello@pngwn.io> Co-authored-by: Ali Abid <aabid94@gmail.com> * [create-pull-request] automated change (#4059) Co-authored-by: aliabid94 <aliabid94@users.noreply.github.com> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * changelog (#4064) * New Version Docs (#4069) * [create-pull-request] automated change * Trigger Build --------- Co-authored-by: aliabd <aliabd@users.noreply.github.com> Co-authored-by: aliabd <ali.si3luwa@gmail.com> * Soft theme fix (#4070) * fix * fix --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Empty gallery fix (#4072) * changes * changes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix bug where functions with type hints caused errors (#4068) * Fix + test * CHANGELOG * Update test/test_utils.py Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Update gradio/utils.py Co-authored-by: Abubakar Abid <abubakar@huggingface.co> --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * More Ruff rules (#4038) * Bump ruff to 0.0.264 * Enable Ruff Naming rules and fix most errors * Move `clean_html` to utils (to fix an N lint error) * Changelog * Clean up possibly leaking file handles * Enable and autofix Ruff SIM * Fix remaining Ruff SIMs * Enable and autofix Ruff UP issues * Fix misordered import from #4048 * Fix bare except from #4048 --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * [WIP] Language Agnostic Typing in `/info` route (#4039) * First commit * All serializers * Remove output type * Add route * Format json * Modify dropdown and slider choices * Fix impl * Lint * Add tests * Fix lint * remove breakpoint * Tests passing locally * Format code * Address comments * Use union + fix tests * handle multiple file case * Add serializer to info payload * lint * Add to CHANGELOG * grc version * requirements * fix test --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Keep hidden Accordion content in DOM (#4073) * changes * changes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Theme builder fixes (#4080) * theme-builder-fixes * theme-builder-fixes * fix expand issue * changes * Update gradio/themes/builder_app.py * changelog --------- Co-authored-by: Ali Abid <aabid94@gmail.com> * Misc file and docs fixes (#4086) * uvicorn version * uvicorn version * changes * guides * guide * changelog * typo * typo * Update guides/04_integrating-other-frameworks/01_using-hugging-face-integrations.md * chinese lang * rename * Update guides/04_integrating-other-frameworks/01_using-hugging-face-integrations.md * Update guides/03_building-with-blocks/04_custom-CSS-and-JS.md Co-authored-by: aliabid94 <aabid94@gmail.com> * address review * simplify section --------- Co-authored-by: aliabid94 <aabid94@gmail.com> * Removing "State" from view API info (#4107) * wip pr * update client version * update space fetcher * changelog, workflow * fix not flaky tests * lint * v2 * Dont send request to `/info` if version before 3.28.3 (#4109) * Add code * Lint * CHANGELOG --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Upload audio ios (#4071) * changes * changes * change * changes * changes * changes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Allow textbox / number submits to trigger Interface submit (#4090) * changes * changes * changes * changes * changes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix slider released event not triggering when released on mobile (#4098) * Fix slider released event not triggering when released on mobile * Update CHANGELOG * fix range test * retrigger --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix then logic to work after failures (#4115) * change * changes * changes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fixes to view API page (#4112) * logo * fix for new info and logo path * changelog * remove example_input from returns --------- Co-authored-by: Ali Abdalla <ali.si3luwa@gmail.com> * Add support for async generators (#3821) * Add impl + unit test * CHANGELOG * Lint * Type check * Remove print * Fix tests * revert change * Lint * formatting * Fix test * Lint --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: Ali Abid <aabid94@gmail.com> * release (#4116) * Bumpt client version (#4125) * New Version Docs (#4131) * [create-pull-request] automated change * Trigger Build --------- Co-authored-by: aliabd <aliabd@users.noreply.github.com> Co-authored-by: aliabd <ali.si3luwa@gmail.com> * Fix create version docs action (#4130) * define version instead of upgrading * add sleep --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix dev docs (#4132) * Move .config/README.md to js/README.md * Link js/README.md from CONTRIBUTING.md * Update CHANGELOG.md --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * changelog (#4136) * Fix website build issue (#4142) * upgrade pnpm * changelgo * Fix python client test (#4138) * Fix python client test * CHANGELOG --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix isssue with running with nginx (#4133) * nginx-root * fix * ability to set root path * removed root * removed root * fix * changelog * Update gradio/routes.py Co-authored-by: aliabid94 <aabid94@gmail.com> * Update gradio/routes.py Co-authored-by: aliabid94 <aabid94@gmail.com> --------- Co-authored-by: aliabid94 <aabid94@gmail.com> * Record username when flagging (#4135) * record username * fix * changelog fix * format * fix hf saver * fix deserialization * fixes * Fix api info for File component (#4153) * Fix output file type info * Fix example inputs * CHANGELOG * Update client * Add test * Bump version * Bump min client version * Update .prettierignore adding client/js/dist and .venv (#4160) * Fix the prettier.ignorePath field in the VSCode workspace settings (#4164) Co-authored-by: pngwn <hello@pngwn.io> * simplify format of changelog (#4163) * Fix the wildcard in .editorconfig to match files in nested directories (#4165) * Fix the wildcard in .editorconfig to match files in nested directories * Remove a wrong whitespace in a brace expansion notation in .editorconfig --------- Co-authored-by: pngwn <hello@pngwn.io> * Fix flaky interface test (#4168) * Fix test * Lint * Fix vs code lint * Adds missing components to gradio client serializing's component mapping (#4167) * add missing serialization * format * update release note format * update release note format * fix test * Release 3.30 (#4166) * release * requirements * [Docs] Resolve numerous typos (#4170) * Resolve numerous typos * Delete test.py * Run generate_notebooks * notebooks --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * New Version Docs (#4172) * [create-pull-request] automated change * Update v3.30.0_template.html --------- Co-authored-by: abidlabs <abidlabs@users.noreply.github.com> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Dispatch dropdown change on value change for any reason (#4128) * changes * changes * changes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * hotfix for test (#4173) * hotfix for test * removed comment * 3712 js client (#3899) * update ci (#4184) * bump client version (#4185) * bump client version * ignore spaces-test * Fix (#4186) * bump client version * ignore spaces-test * fix * update token for npm action (#4187) * change (#4189) * ci typo (#4190) * Fix npm publish again again (#4191) * ci typo * fix * Fix npm publish again again (#4192) * ci typo * fix * again * Fix npm publish again again (#4193) * ci typo * fix * again * again * Add format argument to Audio (#4178) * experimental * Add test * Rename to format * Rename * CHANGELOG * Add to docstring * Update gradio/components.py Co-authored-by: Abubakar Abid <abubakar@huggingface.co> --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * chore: update versions (#4188) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Fix npm publish again again (#4195) * ci typo * fix * again * again * again * client docs tweaks (#4196) * ci typo * fix * again * again * again * ignore workbench * small tweaks for publish + docs * Fix "TypeError: issubclass() arg 1 must be a class" When Optional args (#4200) * fix "issubclass() arg 1 must be a class" when args is Optional * Update CHANGELOG.md add fix "TypeError: issubclass() arg 1 must be a class" when use Optional args * Update gradio/helpers.py Co-authored-by: Aarni Koskela <akx@iki.fi> * changelog * formatting --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: Aarni Koskela <akx@iki.fi> * Fix semiver import (#4201) * fix token (#4208) * fix token * add label * Fix Explanation Regarding NumPy Image Component (#4204) * 20230513 swap np height and width in docs * changelog --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Correct stacklevel for check_deprecated_parameters (#4203) Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Programmatically launch reload to allow factories and arguments to be passed to the app (#4119) * Programmatically lauch reload to allow factories and arguments to be passed to the app * add warning * modify warning * guide fixes * formatting * changes * warning * import fix * fix tests * fix tests --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Update CONTRIBUTING.md (#4220) * Input listener (#4157) * changes * changes * changes * changes * changes * changes * changes * chnages * fix * changes * changes * merge * changes * restore --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Do not do any analytics requests if analytics are disabled (#4194) * Move analytics-related bits to gradio.analytics * Do not do any analytics requests if analytics are disabled * Remove unused log_feature_analytics * removed redundant analytics, rewrote * renamed * save * fixed test' --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Increase websocket messaging timeout (#4235) * increase websocket timeout * changelog * Fix for `typing.get_type_hints()` on Python 3.9 or lower (#4228) * fix * fix docstring * type hint fix * fix test * Update gradio/utils.py Co-authored-by: Aarni Koskela <akx@iki.fi> * fix indentation --------- Co-authored-by: Aarni Koskela <akx@iki.fi> * Some tweaks to the Client (#4230) * parameter names * tweaks * separate out serialize * fix * changelog * fix * fix * improve test * Only allow messaging update if analytics is enabled (#4236) * Only allow messaging update if analytics are allowed Follows up on #4194 * Remove duplicate changelog entry * remove circular import --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix client filepaths (#4202) * transform returned paths to useful URLs * changeset * update app * revert * revert * changelog * Update client/js/src/client.ts Co-authored-by: aliabid94 <aabid94@gmail.com> * format --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: aliabid94 <aabid94@gmail.com> * fix cancels (#4225) * fix cancels * changelog * refactor to make it work * chore: update versions (#4207) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Fix publish (#4240) * fix npm publish * fix npm publish * release (#4219) Co-authored-by: pngwn <hello@pngwn.io> * Fixes chatbot_dialogpt demo (#4238) * demo fix * changelog * fix * demo --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix JSONDecodeError (#4241) * Fix JSONDecodeError bug (#4237) * Remove unused import * Clean up code * Fix JSONDecodeError (#4241) * Accept all Exceptions --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * make workbench private (#4247) * Refactoring (#4223) * Replace var with const in js/app/src/main.ts * Remove unnecessary nullish coalescing in js/app/src/main.ts * Remove unnecessary white spaces in the NPM scripts in js/app/package.json * Use object key-value shorthand * changelog --------- Co-authored-by: pngwn <hello@pngwn.io> * Move mount_css() from main.ts to css.ts (#4222) * Move mount_css() from main.ts to css.ts because these is a circular dependency between main.ts and Index.svelte (and it will help the development of the Wasm ver in the future) * changelog --------- Co-authored-by: pngwn <hello@pngwn.io> * [create-pull-request] automated change (#4250) Co-authored-by: aliabd <aliabd@users.noreply.github.com> * Fix run on click (#4258) * fix run on click * changelog * Upgrade black to 23.3 (#4259) * Upgrade black * Conservatively upgrade packaging too since it's black's dependency * Using marked for chatbot markdown parsing (#4150) * fix info request in js client (#4271) * fix info request in js client * changelog * Temp file fixes (#4256) * Fix bug * Linting * CHANGELOG * Add tests * Update test * Fix remaining components + add tests * Fix tests * Fix tests * Address comments * Ensure error modal display as expected when using the queue (#4273) * Allow passing FastAPI app options (#4282) * App: don't force docs_url and redoc_url to None * App.create_app: allow passing in app_kwargs * start_server + launch: allow passing in app_kwargs * Changelog * Apply suggestions from code review Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Use .launch for tests --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Katex support in chatbot (#4285) * katex * katex support * changelog * fixes * pr fixes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Release 3.32.0 (#4293) * release 3.32.0 * changelog * New Version Docs (#4296) * [create-pull-request] automated change * Update v3.32.0_template.html --------- Co-authored-by: abidlabs <abidlabs@users.noreply.github.com> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Add overridden type annotations on `normalise_file()` to remove @ts-i… (#4315) * Add overridden type annotations on `normalise_file()` to remove @ts-ignore, and remove its unnecessary export * changeset --------- Co-authored-by: pngwn <hello@pngwn.io> * typo (minor): extra newline puts the documentation of colums to grid (#4337) * typo (minor): extra newline puts the documentation of colums to grid * edited changelog * changelog --------- Co-authored-by: thiswillbeyourgithub <github@32mail.33mail.com> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * return a Dependency instance from Blocks.load event listener (#4304) * return a Dependency instance from Blocks.load event listener * a test case for chaining then from load event * update CHANGELOG * add test for load.then with blocks re-used * fixes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix typo in client/js/README.md (#4310) Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * chore: update versions (#4283) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Optimize frontend's is_dep calls (#4334) * Optimize is_dep (36 to 12 msec) * Call is_dep less (12 msec to 9 msec) * Changelog --------- Co-authored-by: pngwn <hello@pngwn.io> * various client refactors + tweaks (#4357) * changeset * Add a type annotation on the `api` variable to which the return value of `view_config()` is assigned, and update the type annotation and exception handling on `view_config` as well (#4311) * Remove unnecessary @ts-ignore (#4314) * Remove unnecessary Promise wrapping another promise (#4313) * Remove unnecessary Promise wrapping another promise * Remove an error handeler that may remove detailed error stacks * changeset * remove changeset --------- Co-authored-by: pngwn <hello@pngwn.io> * Stop using `let` for unchanged variables in `client.ts` (#4312) * Stop using `let` for unchanged variables in `client.ts` * fixes --------- Co-authored-by: pngwn <hello@pngwn.io> --------- Co-authored-by: Yuichiro Tachibana (Tsuchiya) <t.yic.yt@gmail.com> * Remove a bunch of unused frontend code (#4275) Co-authored-by: pngwn <hello@pngwn.io> * Respect `interactive=True` in output of `gr.Interface` (#4356) * tests * changelog * lint * Update gradio/interface.py Co-authored-by: Aarni Koskela <akx@iki.fi> * format --------- Co-authored-by: Aarni Koskela <akx@iki.fi> * Don't allow dotfiles for /file= route (#4303) * Don't allow dotfiles or files in "dot directories" for /file= * update guide --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Push to spaces (#4033) * changes * first commit * Update gradio/upload.py Co-authored-by: Aarni Koskela <akx@iki.fi> * Update gradio/upload.py Co-authored-by: Aarni Koskela <akx@iki.fi> * changes * changes * changes * changes * changes * changes * changes * chnages * changes * changes * changes * changes * Update 03_sharing-your-app.md * changes * changes * change * changes * changes * changes * Update gradio/deploy_space.py Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * changes * changes * changes --------- Co-authored-by: Aarni Koskela <akx@iki.fi> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Do not send HF token to other domains via `/proxy` (#4368) * test * fix * changelog * fix, add warnings * Make chatbot input fields non-interactive while bot is streaming (#4363) * Add demo impl * trigger then if generating * remove unused value * CHANGELOG * Fix code * Update guide * Update guides/07_other-tutorials/creating-a-chatbot.md Co-authored-by: pngwn <hello@pngwn.io> --------- Co-authored-by: pngwn <hello@pngwn.io> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Prevent path traversal in `/file` routes (#4370) * add tests * add tests * file route fix * update tests * formatting * file access * cleanup * cleaning * fix tests * Favicon fix for Windows (#4369) * favicon fix * changelog * svg * remove favicon * actual fix * Add pypi classifiers to pyproject.toml (#4383) * Add pypi classifiers to pyproject.toml * Add OS classifier --------- Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com> * Use DOMPurify to sanitize html in chatbot (#4360) * dompurify * changelog * format * clean * changelog * Update run.py * update happy-dom --------- Co-authored-by: pngwn <hello@pngwn.io> * fix copy button invalid & copy button (invisible) duplication bug in chatbot (#4350) * fix a copy button duplication bug in chatbot * fix copy button invalid issue * Update CHANGELOG.md: Fixed Copy Button * fix changelog typo * switch to static HTML + event delegation for copy button * fix * format + notebooks * format + notebooks --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: pngwn <hello@pngwn.io> * release 3.33.0 (#4392) Co-authored-by: aliabid94 <aabid94@gmail.com> * Restore offline support (#4398) * changes * changes * changes * New Version Docs (#4397) * [create-pull-request] automated change * Update temporary_template.html --------- Co-authored-by: abidlabs <abidlabs@users.noreply.github.com> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix Base parent in Docs, add Group (#4391) * fix base parent * add group to docs --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Remove old versioned docs and fix repo classification (#4362) * remove old versioned docs * delete versioned docs when new one is created * ignore website dir in linguist calc * upload and download versioned docs * modify github action * remove gitattributes file --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Update message when share link binary is blocked (#4380) * update share link message * address suggestion * changelog * fix * formatting * Update utils.py for validate_url (#4388) * Update utils.py for validate_url AWS s3 presigned url cannot work for both HEAD and GET. So when HEAD the presigned url, it will return 403(Forbidden) * Update gradio/utils.py * changelog --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * v3.33.1 + Guide on setting up Gradio behind nginx... (#4379) * nginx guide * delete 3.33.0 * version * unindent * Prevent label change event from triggering itself (#4371) * Fix the Node and pnpm setup actions (#4394) * Run `pnpm i` with pnpm@8.6.0 to re-generate the lock file (#4393) * fix indent (#4404) * Throttle scroll event (#4158) * Throttle scroll event This decreases the amount of function calls when scrolling through the documentation website. * fix themes base --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: Ali Abdalla <ali.si3luwa@gmail.com> * merge * fixes * changes * more changes * notebook * changelog * error handle backend * Update gradio/components.py Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Update gradio/components.py Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Adds `variant` and `interactive` props to `gr.UploadButton` (#4436) * upload button * fix index * changelog * formatting * cleanup * fix get_continuous_fn bug when having every (#4434) * fix the bug for wrap continuous func with parameter every while origin func return generator * Update utils.py * Update CHANGELOG.md * Update test_utils.py * Update CHANGELOG.md * formatting --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix Safari video playback (#4433) * changes * changes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * test fix * test * tests * fix ui test * format * Increase version gradio-client version/changelog (#4441) * Increase version gradio-client version/changelog * req --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * fixes * notebook * fixed tests finally * format * python test fix * test fix * remove style from test * Update CHANGELOG.md * theme test fix --------- Co-authored-by: Artemy Egorov <artegoser@gmail.com> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: aliabd <aliabd@users.noreply.github.com> Co-authored-by: aliabd <ali.si3luwa@gmail.com> Co-authored-by: Lucain <lucainp@gmail.com> Co-authored-by: testbot <lucainp@hf.co> Co-authored-by: 1lint <105617163+1lint@users.noreply.github.com> Co-authored-by: Aarni Koskela <akx@iki.fi> Co-authored-by: pngwn <hello@pngwn.io> Co-authored-by: Ali Abid <aabid94@gmail.com> Co-authored-by: aliabid94 <aliabid94@users.noreply.github.com> Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com> Co-authored-by: space-nuko <24979496+space-nuko@users.noreply.github.com> Co-authored-by: Yuichiro Tachibana (Tsuchiya) <t.yic.yt@gmail.com> Co-authored-by: Tom Aarsen <37621491+tomaarsen@users.noreply.github.com> Co-authored-by: abidlabs <abidlabs@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: LingFeng.Chen.Cn <lingfeng.chen.cn@gmail.com> Co-authored-by: Der Chien <b03902015@ntu.edu.tw> Co-authored-by: Micky Brunetti <micky2be@users.noreply.github.com> Co-authored-by: David Ai <davidai2018@gmail.com> Co-authored-by: thiswillbeyourgithub <26625900+thiswillbeyourgithub@users.noreply.github.com> Co-authored-by: thiswillbeyourgithub <github@32mail.33mail.com> Co-authored-by: Paul Garner <ego@anentropic.com> Co-authored-by: WilliamRoyNelson <william.roy.nelson@gmail.com> Co-authored-by: binary-husky <96192199+binary-husky@users.noreply.github.com> Co-authored-by: Yan <alvindaiyan@gmail.com> Co-authored-by: Shavit <shavit@users.noreply.github.com> Co-authored-by: dkjshk <xie0510@126.com>
2023-06-11 09:12:11 +08:00
"minimum": None,
"maximum": None,
"container": True,
"min_width": 160,
"scale": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"interactive": None,
"root_url": None,
"info": None,
"precision": 0,
}
def test_component_functions_precision(self):
"""
Preprocess, postprocess, serialize, set_interpret_parameters, get_interpretation_neighbors, get_template_context
"""
numeric_input = gr.Number(precision=2, value=42.3428)
assert numeric_input.preprocess(3.231241) == 3.23
assert numeric_input.preprocess(None) is None
assert numeric_input.postprocess(-42.1241) == -42.12
assert numeric_input.postprocess(5.6784) == 5.68
assert numeric_input.postprocess(2.1421) == 2.14
assert numeric_input.postprocess(None) is None
@pytest.mark.asyncio
async def test_in_interface_as_input(self):
"""
Interface, process, interpret
"""
iface = gr.Interface(lambda x: x**2, "number", "textbox")
assert iface(2) == "4.0"
iface = gr.Interface(
lambda x: x**2, "number", "number", interpretation="default"
)
scores = (await iface.interpret([2]))[0]["interpretation"]
assert scores == [
(1.94, -0.23640000000000017),
(1.96, -0.15840000000000032),
(1.98, -0.07960000000000012),
(2, None),
(2.02, 0.08040000000000003),
(2.04, 0.16159999999999997),
(2.06, 0.24359999999999982),
]
@pytest.mark.asyncio
async def test_precision_0_in_interface(self):
"""
Interface, process, interpret
"""
iface = gr.Interface(lambda x: x**2, gr.Number(precision=0), "textbox")
assert iface(2) == "4"
iface = gr.Interface(
lambda x: x**2, "number", gr.Number(precision=0), interpretation="default"
)
# Output gets rounded to 4 for all input so no change
scores = (await iface.interpret([2]))[0]["interpretation"]
assert scores == [
(1.94, 0.0),
(1.96, 0.0),
(1.98, 0.0),
(2, None),
(2.02, 0.0),
(2.04, 0.0),
(2.06, 0.0),
]
@pytest.mark.asyncio
async def test_in_interface_as_output(self):
"""
Interface, process, interpret
"""
iface = gr.Interface(lambda x: int(x) ** 2, "textbox", "number")
assert iface(2) == 4.0
iface = gr.Interface(
lambda x: x**2, "number", "number", interpretation="default"
)
scores = (await iface.interpret([2]))[0]["interpretation"]
assert scores == [
(1.94, -0.23640000000000017),
(1.96, -0.15840000000000032),
(1.98, -0.07960000000000012),
(2, None),
(2.02, 0.08040000000000003),
(2.04, 0.16159999999999997),
(2.06, 0.24359999999999982),
]
def test_static(self):
"""
postprocess
"""
component = gr.Number()
assert component.get_config().get("value") is None
component = gr.Number(3)
assert component.get_config().get("value") == 3.0
class TestSlider:
def test_component_functions(self):
"""
Preprocess, postprocess, serialize, get_config
"""
slider_input = gr.Slider()
assert slider_input.preprocess(3.0) == 3.0
assert slider_input.postprocess(3) == 3
assert slider_input.postprocess(3) == 3
assert slider_input.postprocess(None) == 0
assert slider_input.serialize(3, True) == 3
2022-05-16 14:55:35 +08:00
slider_input = gr.Slider(10, 20, value=15, step=1, label="Slide Your Input")
assert slider_input.get_config() == {
"minimum": 10,
"maximum": 20,
"step": 1,
"value": 15,
"name": "slider",
"show_label": True,
"label": "Slide Your Input",
"container": True,
"min_width": 160,
"scale": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"interactive": None,
"root_url": None,
"info": None,
}
@pytest.mark.asyncio
async def test_in_interface(self):
""" "
Interface, process, interpret
"""
iface = gr.Interface(lambda x: x**2, "slider", "textbox")
assert iface(2) == "4"
iface = gr.Interface(
lambda x: x**2, "slider", "number", interpretation="default"
)
scores = (await iface.interpret([2]))[0]["interpretation"]
assert scores == [
-4.0,
200.08163265306123,
812.3265306122449,
1832.7346938775513,
3261.3061224489797,
5098.040816326531,
7342.938775510205,
9996.0,
]
def test_static(self):
"""
postprocess
"""
component = gr.Slider(0, 100, 5)
assert component.get_config().get("value") == 5
component = gr.Slider(0, 100, None)
assert component.get_config().get("value") == 0
@patch("gradio.Slider.get_random_value", return_value=7)
def test_slider_get_random_value_on_load(self, mock_get_random_value):
slider = gr.Slider(minimum=-5, maximum=10, randomize=True)
assert slider.value == 7
assert slider.load_event_to_attach[0]() == 7
assert slider.load_event_to_attach[1] is None
@patch("random.randint", return_value=3)
def test_slider_rounds_when_using_default_randomizer(self, mock_randint):
slider = gr.Slider(minimum=0, maximum=1, randomize=True, step=0.1)
# If get_random_value didn't round, this test would fail
# because 0.30000000000000004 != 0.3
assert slider.get_random_value() == 0.3
mock_randint.assert_called()
class TestCheckbox:
def test_component_functions(self):
"""
Preprocess, postprocess, serialize, get_config
"""
bool_input = gr.Checkbox()
assert bool_input.preprocess(True)
assert bool_input.postprocess(True)
assert bool_input.postprocess(True)
assert bool_input.serialize(True, True)
bool_input = gr.Checkbox(value=True, label="Check Your Input")
assert bool_input.get_config() == {
"value": True,
"name": "checkbox",
"show_label": True,
"label": "Check Your Input",
"container": True,
"min_width": 160,
"scale": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"interactive": None,
"root_url": None,
"selectable": False,
"info": None,
}
@pytest.mark.asyncio
async def test_in_interface(self):
"""
Interface, process, interpret
"""
iface = gr.Interface(lambda x: 1 if x else 0, "checkbox", "number")
assert iface(True) == 1
iface = gr.Interface(
lambda x: 1 if x else 0, "checkbox", "number", interpretation="default"
)
scores = (await iface.interpret([False]))[0]["interpretation"]
assert scores == (None, 1.0)
scores = (await iface.interpret([True]))[0]["interpretation"]
assert scores == (-1.0, None)
class TestCheckboxGroup:
def test_component_functions(self):
"""
Preprocess, postprocess, serialize, get_config
"""
checkboxes_input = gr.CheckboxGroup(["a", "b", "c"])
assert checkboxes_input.preprocess(["a", "c"]) == ["a", "c"]
assert checkboxes_input.postprocess(["a", "c"]) == ["a", "c"]
assert checkboxes_input.serialize(["a", "c"]) == ["a", "c"]
checkboxes_input = gr.CheckboxGroup(["a", "b"], type="index")
assert checkboxes_input.preprocess(["a"]) == [0]
assert checkboxes_input.preprocess(["a", "b"]) == [0, 1]
assert checkboxes_input.preprocess(["a", "b", "c"]) == [0, 1, None]
# When a Gradio app is loaded with gr.load, the tuples are converted to lists,
# so we need to test that case as well
checkboxgroup = gr.CheckboxGroup(["a", "b", ["c", "c full"]]) # type: ignore
assert checkboxgroup.choices == [("a", "a"), ("b", "b"), ("c", "c full")]
checkboxes_input = gr.CheckboxGroup(
value=["a", "c"],
choices=["a", "b", "c"],
label="Check Your Inputs",
)
assert checkboxes_input.get_config() == {
"choices": [("a", "a"), ("b", "b"), ("c", "c")],
"value": ["a", "c"],
"name": "checkboxgroup",
"show_label": True,
"label": "Check Your Inputs",
"container": True,
"min_width": 160,
"scale": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"interactive": None,
"root_url": None,
"selectable": False,
"type": "value",
"info": None,
}
with pytest.raises(ValueError):
gr.CheckboxGroup(["a"], type="unknown")
cbox = gr.CheckboxGroup(choices=["a", "b"], value="c")
assert cbox.get_config()["value"] == ["c"]
assert cbox.postprocess("a") == ["a"]
with pytest.raises(ValueError):
gr.CheckboxGroup().as_example("a")
def test_in_interface(self):
"""
Interface, process
"""
checkboxes_input = gr.CheckboxGroup(["a", "b", "c"])
iface = gr.Interface(lambda x: "|".join(x), checkboxes_input, "textbox")
assert iface(["a", "c"]) == "a|c"
assert iface([]) == ""
_ = gr.CheckboxGroup(["a", "b", "c"], type="index")
class TestRadio:
def test_component_functions(self):
"""
Preprocess, postprocess, serialize, get_config
"""
radio_input = gr.Radio(["a", "b", "c"])
assert radio_input.preprocess("c") == "c"
assert radio_input.postprocess("a") == "a"
assert radio_input.serialize("a", True) == "a"
radio_input = gr.Radio(
choices=["a", "b", "c"], default="a", label="Pick Your One Input"
)
assert radio_input.get_config() == {
"choices": [("a", "a"), ("b", "b"), ("c", "c")],
"value": None,
"name": "radio",
"show_label": True,
"label": "Pick Your One Input",
"container": True,
"min_width": 160,
"scale": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"interactive": None,
"root_url": None,
"selectable": False,
"type": "value",
"info": None,
}
radio = gr.Radio(choices=["a", "b"], type="index")
assert radio.preprocess("a") == 0
assert radio.preprocess("b") == 1
assert radio.preprocess("c") is None
# When a Gradio app is loaded with gr.load, the tuples are converted to lists,
# so we need to test that case as well
radio = gr.Radio(["a", "b", ["c", "c full"]]) # type: ignore
assert radio.choices == [("a", "a"), ("b", "b"), ("c", "c full")]
with pytest.raises(ValueError):
gr.Radio(["a", "b"], type="unknown")
@pytest.mark.asyncio
async def test_in_interface(self):
"""
Interface, process, interpret
"""
radio_input = gr.Radio(["a", "b", "c"])
iface = gr.Interface(lambda x: 2 * x, radio_input, "textbox")
assert iface("c") == "cc"
radio_input = gr.Radio(["a", "b", "c"], type="index")
iface = gr.Interface(
lambda x: 2 * x, radio_input, "number", interpretation="default"
)
assert iface("c") == 4
scores = (await iface.interpret(["b"]))[0]["interpretation"]
assert scores == [-2.0, None, 2.0]
def test_update(self):
update = gr.Radio.update(
choices=[("zeroth", ""), "first", "second"], label="ordinal"
)
assert update["choices"] == [
("zeroth", ""),
("first", "first"),
("second", "second"),
]
class TestDropdown:
def test_component_functions(self):
"""
Preprocess, postprocess, serialize, get_config
"""
dropdown_input = gr.Dropdown(["a", "b", ("c", "c full")], multiselect=True)
assert dropdown_input.preprocess("a") == "a"
assert dropdown_input.postprocess("a") == "a"
assert dropdown_input.preprocess("c full") == "c full"
assert dropdown_input.postprocess("c full") == "c full"
# When a Gradio app is loaded with gr.load, the tuples are converted to lists,
# so we need to test that case as well
dropdown_input = gr.Dropdown(["a", "b", ["c", "c full"]]) # type: ignore
assert dropdown_input.choices == [("a", "a"), ("b", "b"), ("c", "c full")]
dropdown = gr.Dropdown(choices=["a", "b"], type="index")
assert dropdown.preprocess("a") == 0
assert dropdown.preprocess("b") == 1
assert dropdown.preprocess("c") is None
dropdown = gr.Dropdown(choices=["a", "b"], type="index", multiselect=True)
assert dropdown.preprocess(["a"]) == [0]
assert dropdown.preprocess(["a", "b"]) == [0, 1]
assert dropdown.preprocess(["a", "b", "c"]) == [0, 1, None]
dropdown_input_multiselect = gr.Dropdown(["a", "b", ("c", "c full")])
assert dropdown_input_multiselect.preprocess(["a", "c full"]) == ["a", "c full"]
assert dropdown_input_multiselect.postprocess(["a", "c full"]) == [
"a",
"c full",
]
assert dropdown_input_multiselect.serialize(["a", "c full"]) == ["a", "c full"]
dropdown_input_multiselect = gr.Dropdown(
value=["a", "c"],
choices=["a", "b", ("c", "c full")],
label="Select Your Inputs",
Dropdown Component Updates (#3211) * dropdown * more dropdown updates * dropdown styling + option visibility * changelog * notebook * fix test * Allow more image formats (#3225) * add wildcard to image input * simplify mime types * changelog * regen noteboks --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: pngwn <hello@pngwn.io> * fix webcam mirroring (#3245) * fix webcam * changelog * fix changelog * fix changelog * fix changelog --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Add `interactive=False` mode to `gr.Button` (#3266) * add interactive=False to button * add interactive=True by default * changelog * fix frontend * fix backend test * formatting * review changes * LaTeX height fix (#3258) * latex height fix * changelog * formatting * em * em * accidentally added script (#3273) * Adding a script to benchmark the queue (#3272) * added benchmark queue script * changelg * fix instructions * Fix matplotlib image size (#3274) * Fix matplotlib css * CHANGELOG * Undo lockfile * Add timeouts to queue messages (#3196) * Fix + test * Remove print statements + fix import for 3.7 * CHANGELOG * Remove more print statements * Add 60 second timeout for uploading data * Fix test --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * icons * separate options into component * formatting * changelog * changelog * fix ui tests * formatting again... * backend test fix * format * doc fixes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: fienestar <fienestar@gmail.com> Co-authored-by: pngwn <hello@pngwn.io> Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com>
2023-02-24 05:32:18 +08:00
multiselect=True,
max_choices=2,
)
assert dropdown_input_multiselect.get_config() == {
"allow_custom_value": False,
"choices": [("a", "a"), ("b", "b"), ("c", "c full")],
"value": ["a", "c"],
"name": "dropdown",
"show_label": True,
"label": "Select Your Inputs",
"container": True,
"min_width": 160,
"scale": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"interactive": None,
"root_url": None,
Dropdown Component Updates (#3211) * dropdown * more dropdown updates * dropdown styling + option visibility * changelog * notebook * fix test * Allow more image formats (#3225) * add wildcard to image input * simplify mime types * changelog * regen noteboks --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: pngwn <hello@pngwn.io> * fix webcam mirroring (#3245) * fix webcam * changelog * fix changelog * fix changelog * fix changelog --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Add `interactive=False` mode to `gr.Button` (#3266) * add interactive=False to button * add interactive=True by default * changelog * fix frontend * fix backend test * formatting * review changes * LaTeX height fix (#3258) * latex height fix * changelog * formatting * em * em * accidentally added script (#3273) * Adding a script to benchmark the queue (#3272) * added benchmark queue script * changelg * fix instructions * Fix matplotlib image size (#3274) * Fix matplotlib css * CHANGELOG * Undo lockfile * Add timeouts to queue messages (#3196) * Fix + test * Remove print statements + fix import for 3.7 * CHANGELOG * Remove more print statements * Add 60 second timeout for uploading data * Fix test --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * icons * separate options into component * formatting * changelog * changelog * fix ui tests * formatting again... * backend test fix * format * doc fixes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: fienestar <fienestar@gmail.com> Co-authored-by: pngwn <hello@pngwn.io> Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com>
2023-02-24 05:32:18 +08:00
"multiselect": True,
"filterable": True,
Dropdown Component Updates (#3211) * dropdown * more dropdown updates * dropdown styling + option visibility * changelog * notebook * fix test * Allow more image formats (#3225) * add wildcard to image input * simplify mime types * changelog * regen noteboks --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: pngwn <hello@pngwn.io> * fix webcam mirroring (#3245) * fix webcam * changelog * fix changelog * fix changelog * fix changelog --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Add `interactive=False` mode to `gr.Button` (#3266) * add interactive=False to button * add interactive=True by default * changelog * fix frontend * fix backend test * formatting * review changes * LaTeX height fix (#3258) * latex height fix * changelog * formatting * em * em * accidentally added script (#3273) * Adding a script to benchmark the queue (#3272) * added benchmark queue script * changelg * fix instructions * Fix matplotlib image size (#3274) * Fix matplotlib css * CHANGELOG * Undo lockfile * Add timeouts to queue messages (#3196) * Fix + test * Remove print statements + fix import for 3.7 * CHANGELOG * Remove more print statements * Add 60 second timeout for uploading data * Fix test --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * icons * separate options into component * formatting * changelog * changelog * fix ui tests * formatting again... * backend test fix * format * doc fixes --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: fienestar <fienestar@gmail.com> Co-authored-by: pngwn <hello@pngwn.io> Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com>
2023-02-24 05:32:18 +08:00
"max_choices": 2,
"selectable": False,
"type": "value",
"info": None,
}
with pytest.raises(ValueError):
gr.Dropdown(["a"], type="unknown")
dropdown = gr.Dropdown(choices=["a", "b"], value="c")
assert dropdown.get_config()["value"] == "c"
assert dropdown.postprocess("a") == "a"
def test_in_interface(self):
"""
Interface, process
"""
dropdown_input = gr.Dropdown(["a", "b", "c"])
iface = gr.Interface(lambda x: "|".join(x), dropdown_input, "textbox")
assert iface(["a", "c"]) == "a|c"
assert iface([]) == ""
def test_update(self):
update = gr.Dropdown.update(
choices=[("zeroth", ""), "first", "second"], label="ordinal"
)
assert update["choices"] == [
("zeroth", ""),
("first", "first"),
("second", "second"),
]
class TestImage:
def test_component_functions(self):
"""
Preprocess, postprocess, serialize, get_config, _segment_by_slic
type: pil, file, filepath, numpy
"""
img = deepcopy(media_data.BASE64_IMAGE)
image_input = gr.Image()
assert image_input.preprocess(img).shape == (68, 61, 3)
image_input = gr.Image(shape=(25, 25), image_mode="L")
assert image_input.preprocess(img).shape == (25, 25)
image_input = gr.Image(shape=(30, 10), type="pil")
assert image_input.preprocess(img).size == (30, 10)
assert image_input.postprocess("test/test_files/bus.png") == img
assert image_input.serialize("test/test_files/bus.png") == img
image_input = gr.Image(type="filepath")
image_temp_filepath = image_input.preprocess(img)
assert image_temp_filepath in image_input.temp_files
image_input = gr.Image(
source="upload", tool="editor", type="pil", label="Upload Your Image"
)
assert image_input.get_config() == {
2023-02-23 16:46:44 +08:00
"brush_radius": None,
"brush_color": "#000000",
"mask_opacity": 0.7,
"image_mode": "RGB",
"shape": None,
"source": "upload",
"tool": "editor",
"name": "image",
"show_share_button": False,
"show_download_button": True,
"streaming": False,
"show_label": True,
"label": "Upload Your Image",
"container": True,
"min_width": 160,
"scale": None,
"height": None,
"width": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"value": None,
"interactive": None,
"root_url": None,
"mirror_webcam": True,
"selectable": False,
"invert_colors": False,
"type": "pil",
}
assert image_input.preprocess(None) is None
image_input = gr.Image(invert_colors=True)
assert image_input.preprocess(img) is not None
image_input.preprocess(img)
file_image = gr.Image(type="filepath")
assert isinstance(file_image.preprocess(img), str)
with pytest.raises(ValueError):
gr.Image(type="unknown")
image_input.shape = (30, 10)
# Output functionalities
y_img = gr.processing_utils.decode_base64_to_image(
deepcopy(media_data.BASE64_IMAGE)
)
image_output = gr.Image()
assert image_output.postprocess(y_img).startswith(
"data:image/png;base64,iVBORw0KGgoAAA"
)
assert image_output.postprocess(np.array(y_img)).startswith(
"data:image/png;base64,iVBORw0KGgoAAA"
)
with pytest.raises(ValueError):
image_output.postprocess([1, 2, 3])
image_output = gr.Image(type="numpy")
assert image_output.postprocess(y_img).startswith("data:image/png;base64,")
@pytest.mark.flaky
def test_serialize_url(self):
img = "https://gradio-builds.s3.amazonaws.com/demo-files/cheetah-002.jpg"
expected = client_utils.encode_url_or_file_to_base64(img)
assert gr.Image().serialize(img) == expected
def test_in_interface_as_input(self):
"""
Interface, process, interpret
type: file
interpretation: default, shap,
"""
img = "test/test_files/bus.png"
image_input = gr.Image()
iface = gr.Interface(
lambda x: PIL.Image.open(x).rotate(90, expand=True),
gr.Image(shape=(30, 10), type="filepath"),
"image",
)
output = iface(img)
assert PIL.Image.open(output).size == (10, 30)
iface = gr.Interface(
lambda x: np.sum(x), image_input, "number", interpretation="default"
)
def test_as_example(self):
# test that URLs are not converted to an absolute path
url = "https://gradio-static-files.s3.us-west-2.amazonaws.com/header-image.jpg"
assert gr.Image().as_example(url) == url
def test_in_interface_as_output(self):
"""
Interface, process
"""
def generate_noise(height, width):
return np.random.randint(0, 256, (height, width, 3))
iface = gr.Interface(generate_noise, ["slider", "slider"], "image")
assert iface(10, 20).endswith(".png")
def test_static(self):
"""
postprocess
"""
component = gr.Image("test/test_files/bus.png")
assert component.get_config().get("value") == media_data.BASE64_IMAGE
component = gr.Image(None)
assert component.get_config().get("value") is None
class TestPlot:
@pytest.mark.asyncio
async def test_in_interface_as_output(self):
"""
Interface, process
"""
def plot(num):
import matplotlib.pyplot as plt
fig = plt.figure()
plt.plot(range(num), range(num))
return fig
iface = gr.Interface(plot, "slider", "plot")
with utils.MatplotlibBackendMananger():
output = await iface.process_api(fn_index=0, inputs=[10], state={})
assert output["data"][0]["type"] == "matplotlib"
assert output["data"][0]["plot"].startswith("data:image/png;base64")
def test_static(self):
"""
postprocess
"""
with utils.MatplotlibBackendMananger():
import matplotlib.pyplot as plt
fig = plt.figure()
plt.plot([1, 2, 3], [1, 2, 3])
component = gr.Plot(fig)
assert component.get_config().get("value") is not None
component = gr.Plot(None)
assert component.get_config().get("value") is None
def test_postprocess_altair(self):
import altair as alt
from vega_datasets import data
cars = data.cars()
chart = (
alt.Chart(cars)
.mark_point()
.encode(
x="Horsepower",
y="Miles_per_Gallon",
color="Origin",
)
)
out = gr.Plot().postprocess(chart)
assert isinstance(out["plot"], str)
assert out["plot"] == chart.to_json()
class TestAudio:
def test_component_functions(self):
"""
Preprocess, postprocess serialize, get_config, deserialize
type: filepath, numpy, file
"""
x_wav = deepcopy(media_data.BASE64_AUDIO)
audio_input = gr.Audio()
output1 = audio_input.preprocess(x_wav)
assert output1[0] == 8000
assert output1[1].shape == (8046,)
x_wav["is_file"] = True
audio_input = gr.Audio(type="filepath")
output1 = audio_input.preprocess(x_wav)
assert Path(output1).name == "audio_sample-0-100.wav"
Cleaning up the way data is processed for components (#1967) * remove preprocess_example * removing methods * added path support for images * fixes * video * formatting * fixing preprocess * fixes * removed from audio * fixed file * formatting * serialization * foramtting * formatting * removed save flag / restore flag * formatting * removed flagging * removed * load value * fixing typing * fixes, typing * fixes * file * handling images * formatting * fixed serializing for flagging * formatting * json * temp file * removed processing * changed processing * fixed temp FINALLY * flagging works * fix examples test * formatting * async examples * working on mix * comment out failing test * fixed interface problem * fix kitchen sink deprecation warning * gallery examples * fixes * fixes to serialization * fixing label serializing * fixed file serialization * kitchen sink restored * outbreak forecast updated * formatting * formatting and api mode * fix 1 test :/ * fixing tests * fixed components tests * remvoed test files * formatting * fixed examples * fixes * formatting * restored certain files * added encryption * fixed syntax mistake * formatting * fixed 1 test * clean up interface * formatting * fixed route tests * more fixes * formatting * formatting * fixing pipeline * format frontend * format backend * tweaks * fix * fix final test? * merged * Sanitize for CSV (#2017) * sanitize for csv * added sanitization logic * fixed examples * turn cache off * fixed example caching with optional inputs * fixed review problems * fixed Interface.load * updating the tests * updating the tests * fix * fixed seriailizing * testing * rewrite run prediction * formatting * await * fixes * formatting * finally fixed mix * fixed tests * formatting * formatting * deserialize fix * formatting * fixes * fixes * fix * fix tests * fixes Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com>
2022-08-23 23:31:04 +08:00
assert filecmp.cmp(
"test/test_files/audio_sample.wav",
audio_input.serialize("test/test_files/audio_sample.wav")["name"],
)
audio_input = gr.Audio(label="Upload Your Audio")
assert audio_input.get_config() == {
"autoplay": False,
"source": "upload",
"name": "audio",
"show_download_button": True,
"show_share_button": False,
"show_edit_button": True,
"streaming": False,
"show_label": True,
"label": "Upload Your Audio",
"container": True,
"min_width": 160,
"scale": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"value": None,
"interactive": None,
"root_url": None,
"type": "numpy",
"format": "wav",
}
assert audio_input.preprocess(None) is None
x_wav["is_example"] = True
x_wav["crop_min"], x_wav["crop_max"] = 1, 4
output2 = audio_input.preprocess(x_wav)
assert output2 is not None
assert output1 != output2
Cleaning up the way data is processed for components (#1967) * remove preprocess_example * removing methods * added path support for images * fixes * video * formatting * fixing preprocess * fixes * removed from audio * fixed file * formatting * serialization * foramtting * formatting * removed save flag / restore flag * formatting * removed flagging * removed * load value * fixing typing * fixes, typing * fixes * file * handling images * formatting * fixed serializing for flagging * formatting * json * temp file * removed processing * changed processing * fixed temp FINALLY * flagging works * fix examples test * formatting * async examples * working on mix * comment out failing test * fixed interface problem * fix kitchen sink deprecation warning * gallery examples * fixes * fixes to serialization * fixing label serializing * fixed file serialization * kitchen sink restored * outbreak forecast updated * formatting * formatting and api mode * fix 1 test :/ * fixing tests * fixed components tests * remvoed test files * formatting * fixed examples * fixes * formatting * restored certain files * added encryption * fixed syntax mistake * formatting * fixed 1 test * clean up interface * formatting * fixed route tests * more fixes * formatting * formatting * fixing pipeline * format frontend * format backend * tweaks * fix * fix final test? * merged * Sanitize for CSV (#2017) * sanitize for csv * added sanitization logic * fixed examples * turn cache off * fixed example caching with optional inputs * fixed review problems * fixed Interface.load * updating the tests * updating the tests * fix * fixed seriailizing * testing * rewrite run prediction * formatting * await * fixes * formatting * finally fixed mix * fixed tests * formatting * formatting * deserialize fix * formatting * fixes * fixes * fix * fix tests * fixes Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com>
2022-08-23 23:31:04 +08:00
audio_input = gr.Audio(type="filepath")
assert isinstance(audio_input.preprocess(x_wav), str)
with pytest.raises(ValueError):
gr.Audio(type="unknown")
# Confirm Audio can be instantiated with a numpy array
gr.Audio((100, np.random.random(size=(1000, 2))), label="Play your audio")
# Output functionalities
y_audio = client_utils.decode_base64_to_file(
deepcopy(media_data.BASE64_AUDIO)["data"]
)
audio_output = gr.Audio(type="filepath")
assert filecmp.cmp(y_audio.name, audio_output.postprocess(y_audio.name)["name"])
assert audio_output.get_config() == {
"autoplay": False,
"name": "audio",
"show_download_button": True,
"show_share_button": False,
"show_edit_button": True,
"streaming": False,
"show_label": True,
"label": None,
"source": "upload",
"container": True,
"min_width": 160,
"scale": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"value": None,
"interactive": None,
"root_url": None,
"type": "filepath",
"format": "wav",
}
assert audio_output.deserialize(
{
"name": None,
"data": deepcopy(media_data.BASE64_AUDIO)["data"],
"is_file": False,
}
).endswith(".wav")
output1 = audio_output.postprocess(y_audio.name)
output2 = audio_output.postprocess(Path(y_audio.name))
assert output1 == output2
def test_serialize(self):
audio_input = gr.Audio()
serialized_input = audio_input.serialize("test/test_files/audio_sample.wav")
assert serialized_input["data"] == media_data.BASE64_AUDIO["data"]
assert os.path.basename(serialized_input["name"]) == "audio_sample.wav"
assert serialized_input["orig_name"] == "audio_sample.wav"
assert not serialized_input["is_file"]
def test_tokenize(self):
"""
Tokenize, get_masked_inputs
"""
x_wav = deepcopy(media_data.BASE64_AUDIO)
audio_input = gr.Audio()
tokens, _, _ = audio_input.tokenize(x_wav)
assert len(tokens) == audio_input.interpretation_segments
x_new = audio_input.get_masked_inputs(tokens, [[1] * len(tokens)])[0]
similarity = SequenceMatcher(a=x_wav["data"], b=x_new).ratio()
assert similarity > 0.9
def test_in_interface(self):
2022-04-07 06:40:28 +08:00
def reverse_audio(audio):
sr, data = audio
return (sr, np.flipud(data))
iface = gr.Interface(reverse_audio, "audio", "audio")
reversed_file = iface("test/test_files/audio_sample.wav")
reversed_reversed_file = iface(reversed_file)
reversed_reversed_data = client_utils.encode_url_or_file_to_base64(
reversed_reversed_file
2022-04-07 06:40:28 +08:00
)
similarity = SequenceMatcher(
a=reversed_reversed_data, b=media_data.BASE64_AUDIO["data"]
).ratio()
assert similarity > 0.99
2022-04-07 06:40:28 +08:00
def test_in_interface_as_output(self):
"""
Interface, process
"""
def generate_noise(duration):
return 48000, np.random.randint(-256, 256, (duration, 3)).astype(np.int16)
iface = gr.Interface(generate_noise, "slider", "audio")
assert iface(100).endswith(".wav")
def test_audio_preprocess_can_be_read_by_scipy(self):
x_wav = deepcopy(media_data.BASE64_MICROPHONE)
audio_input = gr.Audio(type="filepath")
output = audio_input.preprocess(x_wav)
wavfile.read(output)
def test_prepost_process_to_mp3(self):
x_wav = deepcopy(media_data.BASE64_MICROPHONE)
audio_input = gr.Audio(type="filepath", format="mp3")
output = audio_input.preprocess(x_wav)
assert output.endswith("mp3")
output = audio_input.postprocess(
(48000, np.random.randint(-256, 256, (5, 3)).astype(np.int16))
)
assert output["name"].endswith("mp3")
class TestFile:
def test_component_functions(self):
"""
Preprocess, serialize, get_config, value
"""
x_file = deepcopy(media_data.BASE64_FILE)
file_input = gr.File()
output = file_input.preprocess(x_file)
assert isinstance(output, tempfile._TemporaryFileWrapper)
serialized = file_input.serialize("test/test_files/sample_file.pdf")
Cleaning up the way data is processed for components (#1967) * remove preprocess_example * removing methods * added path support for images * fixes * video * formatting * fixing preprocess * fixes * removed from audio * fixed file * formatting * serialization * foramtting * formatting * removed save flag / restore flag * formatting * removed flagging * removed * load value * fixing typing * fixes, typing * fixes * file * handling images * formatting * fixed serializing for flagging * formatting * json * temp file * removed processing * changed processing * fixed temp FINALLY * flagging works * fix examples test * formatting * async examples * working on mix * comment out failing test * fixed interface problem * fix kitchen sink deprecation warning * gallery examples * fixes * fixes to serialization * fixing label serializing * fixed file serialization * kitchen sink restored * outbreak forecast updated * formatting * formatting and api mode * fix 1 test :/ * fixing tests * fixed components tests * remvoed test files * formatting * fixed examples * fixes * formatting * restored certain files * added encryption * fixed syntax mistake * formatting * fixed 1 test * clean up interface * formatting * fixed route tests * more fixes * formatting * formatting * fixing pipeline * format frontend * format backend * tweaks * fix * fix final test? * merged * Sanitize for CSV (#2017) * sanitize for csv * added sanitization logic * fixed examples * turn cache off * fixed example caching with optional inputs * fixed review problems * fixed Interface.load * updating the tests * updating the tests * fix * fixed seriailizing * testing * rewrite run prediction * formatting * await * fixes * formatting * finally fixed mix * fixed tests * formatting * formatting * deserialize fix * formatting * fixes * fixes * fix * fix tests * fixes Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com>
2022-08-23 23:31:04 +08:00
assert filecmp.cmp(
serialized["name"],
"test/test_files/sample_file.pdf",
)
assert serialized["orig_name"] == "sample_file.pdf"
assert output.orig_name == "test/test_files/sample_file.pdf"
x_file["is_file"] = True
input1 = file_input.preprocess(x_file)
input2 = file_input.preprocess(x_file)
assert input1.name == input2.name
assert Path(input1.name).name == "sample_file.pdf"
file_input = gr.File(label="Upload Your File")
assert file_input.get_config() == {
"file_count": "single",
"file_types": None,
"name": "file",
"show_label": True,
"label": "Upload Your File",
"container": True,
"min_width": 160,
"scale": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"value": None,
"interactive": None,
"root_url": None,
"selectable": False,
"height": None,
"type": "file",
}
assert file_input.preprocess(None) is None
x_file["is_example"] = True
assert file_input.preprocess(x_file) is not None
zero_size_file = {"name": "document.txt", "size": 0, "data": ""}
temp_file = file_input.preprocess(zero_size_file)
assert os.stat(temp_file.name).st_size == 0
file_input = gr.File(type="binary")
output = file_input.preprocess(x_file)
assert type(output) == bytes
output1 = file_input.postprocess("test/test_files/sample_file.pdf")
output2 = file_input.postprocess("test/test_files/sample_file.pdf")
assert output1 == output2
def test_file_type_must_be_list(self):
with pytest.raises(
ValueError, match="Parameter file_types must be a list. Received str"
):
gr.File(file_types=".json")
def test_in_interface_as_input(self):
"""
Interface, process
"""
x_file = media_data.BASE64_FILE["name"]
def get_size_of_file(file_obj):
return os.path.getsize(file_obj.name)
iface = gr.Interface(get_size_of_file, "file", "number")
assert iface(x_file) == 10558
def test_as_component_as_output(self):
"""
Cleaning up the way data is processed for components (#1967) * remove preprocess_example * removing methods * added path support for images * fixes * video * formatting * fixing preprocess * fixes * removed from audio * fixed file * formatting * serialization * foramtting * formatting * removed save flag / restore flag * formatting * removed flagging * removed * load value * fixing typing * fixes, typing * fixes * file * handling images * formatting * fixed serializing for flagging * formatting * json * temp file * removed processing * changed processing * fixed temp FINALLY * flagging works * fix examples test * formatting * async examples * working on mix * comment out failing test * fixed interface problem * fix kitchen sink deprecation warning * gallery examples * fixes * fixes to serialization * fixing label serializing * fixed file serialization * kitchen sink restored * outbreak forecast updated * formatting * formatting and api mode * fix 1 test :/ * fixing tests * fixed components tests * remvoed test files * formatting * fixed examples * fixes * formatting * restored certain files * added encryption * fixed syntax mistake * formatting * fixed 1 test * clean up interface * formatting * fixed route tests * more fixes * formatting * formatting * fixing pipeline * format frontend * format backend * tweaks * fix * fix final test? * merged * Sanitize for CSV (#2017) * sanitize for csv * added sanitization logic * fixed examples * turn cache off * fixed example caching with optional inputs * fixed review problems * fixed Interface.load * updating the tests * updating the tests * fix * fixed seriailizing * testing * rewrite run prediction * formatting * await * fixes * formatting * finally fixed mix * fixed tests * formatting * formatting * deserialize fix * formatting * fixes * fixes * fix * fix tests * fixes Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com>
2022-08-23 23:31:04 +08:00
Interface, process
"""
def write_file(content):
with open("test.txt", "w") as f:
f.write(content)
return "test.txt"
iface = gr.Interface(write_file, "text", "file")
assert iface("hello world").endswith(".txt")
class TestUploadButton:
def test_component_functions(self):
"""
preprocess
"""
x_file = deepcopy(media_data.BASE64_FILE)
upload_input = gr.UploadButton()
input = upload_input.preprocess(x_file)
assert isinstance(input, tempfile._TemporaryFileWrapper)
x_file["is_file"] = True
input1 = upload_input.preprocess(x_file)
input2 = upload_input.preprocess(x_file)
assert input1.name == input2.name
def test_raises_if_file_types_is_not_list(self):
with pytest.raises(
ValueError, match="Parameter file_types must be a list. Received int"
):
gr.UploadButton(file_types=2)
class TestDataframe:
def test_component_functions(self):
"""
Preprocess, serialize, get_config
"""
x_data = {
"data": [["Tim", 12, False], ["Jan", 24, True]],
"headers": ["Name", "Age", "Member"],
}
dataframe_input = gr.Dataframe(headers=["Name", "Age", "Member"])
output = dataframe_input.preprocess(x_data)
assert output["Age"][1] == 24
assert not output["Member"][0]
assert dataframe_input.postprocess(x_data) == x_data
dataframe_input = gr.Dataframe(
headers=["Name", "Age", "Member"], label="Dataframe Input"
)
assert dataframe_input.get_config() == {
"value": {"headers": ["Name", "Age", "Member"], "data": [["", "", ""]]},
"selectable": False,
"headers": ["Name", "Age", "Member"],
"row_count": (1, "dynamic"),
"col_count": (3, "dynamic"),
"datatype": ["str", "str", "str"],
"type": "pandas",
"max_rows": 20,
"max_cols": None,
"overflow_row_behaviour": "paginate",
"label": "Dataframe Input",
"show_label": True,
"scale": None,
"min_width": 160,
"interactive": None,
"visible": True,
"elem_id": None,
"elem_classes": None,
"wrap": False,
"root_url": None,
"name": "dataframe",
"height": 500,
"latex_delimiters": [{"display": False, "left": "$", "right": "$"}],
}
dataframe_input = gr.Dataframe()
output = dataframe_input.preprocess(x_data)
assert output["Age"][1] == 24
with pytest.raises(ValueError):
gr.Dataframe(type="unknown")
dataframe_output = gr.Dataframe()
assert dataframe_output.get_config() == {
"value": {"headers": [1, 2, 3], "data": [["", "", ""]]},
"selectable": False,
"headers": [1, 2, 3],
"row_count": (1, "dynamic"),
"col_count": (3, "dynamic"),
"datatype": ["str", "str", "str"],
"type": "pandas",
"max_rows": 20,
"max_cols": None,
"overflow_row_behaviour": "paginate",
"label": None,
"show_label": True,
"scale": None,
"min_width": 160,
"interactive": None,
"visible": True,
"elem_id": None,
"elem_classes": None,
"wrap": False,
"root_url": None,
"name": "dataframe",
"height": 500,
"latex_delimiters": [{"display": False, "left": "$", "right": "$"}],
}
def test_postprocess(self):
"""
postprocess
"""
dataframe_output = gr.Dataframe()
output = dataframe_output.postprocess([])
assert output == {"data": [[]], "headers": []}
output = dataframe_output.postprocess(np.zeros((2, 2)))
assert output == {"data": [[0, 0], [0, 0]], "headers": [1, 2]}
output = dataframe_output.postprocess([[1, 3, 5]])
assert output == {"data": [[1, 3, 5]], "headers": [1, 2, 3]}
output = dataframe_output.postprocess(
pd.DataFrame([[2, True], [3, True], [4, False]], columns=["num", "prime"])
)
assert output == {
"headers": ["num", "prime"],
"data": [[2, True], [3, True], [4, False]],
}
with pytest.raises(ValueError):
gr.Dataframe(type="unknown")
# When the headers don't match the data
dataframe_output = gr.Dataframe(headers=["one", "two", "three"])
output = dataframe_output.postprocess([[2, True], [3, True]])
assert output == {
"headers": ["one", "two"],
"data": [[2, True], [3, True]],
}
dataframe_output = gr.Dataframe(headers=["one", "two", "three"])
output = dataframe_output.postprocess([[2, True, "ab", 4], [3, True, "cd", 5]])
assert output == {
"headers": ["one", "two", "three", 4],
"data": [[2, True, "ab", 4], [3, True, "cd", 5]],
}
def test_dataframe_postprocess_all_types(self):
df = pd.DataFrame(
{
"date_1": pd.date_range("2021-01-01", periods=2),
"date_2": pd.date_range("2022-02-15", periods=2).strftime(
"%B %d, %Y, %r"
),
"number": np.array([0.2233, 0.57281]),
"number_2": np.array([84, 23]).astype(np.int64),
"bool": [True, False],
"markdown": ["# Hello", "# Goodbye"],
}
)
component = gr.Dataframe(
datatype=["date", "date", "number", "number", "bool", "markdown"]
)
output = component.postprocess(df)
assert output == {
"headers": list(df.columns),
"data": [
[
pd.Timestamp("2021-01-01 00:00:00"),
"February 15, 2022, 12:00:00 AM",
0.2233,
84,
True,
"# Hello",
],
[
pd.Timestamp("2021-01-02 00:00:00"),
"February 16, 2022, 12:00:00 AM",
0.57281,
23,
False,
"# Goodbye",
],
],
}
def test_dataframe_postprocess_only_dates(self):
df = pd.DataFrame(
{
"date_1": pd.date_range("2021-01-01", periods=2),
"date_2": pd.date_range("2022-02-15", periods=2),
}
)
component = gr.Dataframe(datatype=["date", "date"])
output = component.postprocess(df)
assert output == {
"headers": list(df.columns),
"data": [
[
pd.Timestamp("2021-01-01 00:00:00"),
pd.Timestamp("2022-02-15 00:00:00"),
],
[
pd.Timestamp("2021-01-02 00:00:00"),
pd.Timestamp("2022-02-16 00:00:00"),
],
],
}
class TestDataset:
def test_preprocessing(self):
test_file_dir = Path(__file__).parent / "test_files"
bus = str(Path(test_file_dir, "bus.png").resolve())
dataset = gr.Dataset(
components=["number", "textbox", "image", "html", "markdown"],
samples=[
[5, "hello", bus, "<b>Bold</b>", "**Bold**"],
[15, "hi", bus, "<i>Italics</i>", "*Italics*"],
],
)
assert dataset.preprocess(1) == [
15,
"hi",
bus,
"<i>Italics</i>",
"*Italics*",
]
dataset = gr.Dataset(
components=["number", "textbox", "image", "html", "markdown"],
samples=[
[5, "hello", bus, "<b>Bold</b>", "**Bold**"],
[15, "hi", bus, "<i>Italics</i>", "*Italics*"],
],
type="index",
)
assert dataset.preprocess(1) == 1
def test_postprocessing(self):
test_file_dir = Path(Path(__file__).parent, "test_files")
bus = Path(test_file_dir, "bus.png")
dataset = gr.Dataset(
components=["number", "textbox", "image", "html", "markdown"], type="index"
)
output = dataset.postprocess(
samples=[
[5, "hello", bus, "<b>Bold</b>", "**Bold**"],
[15, "hi", bus, "<i>Italics</i>", "*Italics*"],
],
)
assert output == {
"samples": [
[5, "hello", bus, "<b>Bold</b>", "**Bold**"],
[15, "hi", bus, "<i>Italics</i>", "*Italics*"],
],
"__type__": "update",
}
class TestVideo:
def test_component_functions(self):
"""
Preprocess, serialize, deserialize, get_config
"""
x_video = deepcopy(media_data.BASE64_VIDEO)
video_input = gr.Video()
output1 = video_input.preprocess(x_video)
assert isinstance(output1, str)
output2 = video_input.preprocess(x_video)
assert output1 == output2
video_input = gr.Video(include_audio=False)
output1 = video_input.preprocess(x_video)
output2 = video_input.preprocess(x_video)
assert output1 == output2
video_input = gr.Video(label="Upload Your Video")
assert video_input.get_config() == {
"autoplay": False,
"source": "upload",
"name": "video",
"show_share_button": False,
"show_label": True,
"label": "Upload Your Video",
"container": True,
"min_width": 160,
"scale": None,
"height": None,
"width": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"value": None,
"interactive": None,
"root_url": None,
"mirror_webcam": True,
"include_audio": True,
"format": None,
}
assert video_input.preprocess(None) is None
x_video["is_example"] = True
assert video_input.preprocess(x_video) is not None
Website Design Changes (#1015) * adding gallery * added netlify files * new navbar design * header section new design * used by section new design * cards section new design * integrates with section new design * customer stories section new design * footer and gradient * demos section new design * docs fixes * docs reorg * docs reorg * upgrading to tailwind 3 * tailwind config changes * navbar new design * fixing body on all pages * Updating Guides (#1012) * updating getting started * updated codecov version * tweaks to gs * added netlify file * added netlify file * website prebuild script * increased code size * blocks * edits * blocks_hello * hello world * guide * merge main * added flipper demo * guide * guide * add guides * tweak to refresh website * header section new design * demos section new design * cards design * used by section * tweets section * footer on all pages * mobile responsive fixes * mobile responsive fixes * https fonts * completed blocks guide * unify components * minor tweaks * docs headers styling and navigation pane * parameter code blocks * styling description and input type * parameter tables and other styling * only documenting interactive components when possible * guides * embedding not working * demos not working * fixing demo code * fixing demos * demo fix * updated demos * updated demos * ui update * updated docstrings * updated code snippets so they run * updating docs * Interface docs * updating interface * fixing parameters in interface.py * required and defaults for interface, and styling * fixing up interface (#1207) * fixing up interface * fixed interface methods * formatting * updating interface docs * updating interface docs * formatting * docstring to load from docstrings * fixed colors * finalize interface content * interface examples * fixed examples * added some blocks docs * blocks * component fixes * reorganized some files (#1210) * formatting * added info for every component * fixes * blocks docs * added blocks demos * adding combined interfaces * added parallel, series * Doc: layout update (#1216) * doc layout * home spacing Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * adding layouts * layouts done * added events for components * formatting and https * brings back dropdown and other components * fix header ids * moved ids and fixed nav * added parameters for remaining component * docstring fixes * landing page demos * demo window placeholder * demo nav * fixed test * formatting * demo code * correctly importing gradio css/js * remove keyvalues * modify launch script to move gradio assetS * components embedded test * correct demo name * hide try demo and embedding * local devserver changes * create embedding json with configs * changes * fixes * comment out layout docs * demo work * demo fixes * demo embedding fixes * typo * jinja fix * demo nav fix * hide demo button * formatting * removed whitespace * remove newline from parameter * reverting comments Co-authored-by: aliabd <ali.si3luwa@gmail.com> Co-authored-by: Victor Muštar <victor.mustar@gmail.com> Co-authored-by: Ali Abid <aabid94@gmail.com>
2022-05-14 10:48:46 +08:00
video_input = gr.Video(format="avi")
output_video = video_input.preprocess(x_video)
assert output_video[-3:] == "avi"
assert "flip" not in output_video
Cleaning up the way data is processed for components (#1967) * remove preprocess_example * removing methods * added path support for images * fixes * video * formatting * fixing preprocess * fixes * removed from audio * fixed file * formatting * serialization * foramtting * formatting * removed save flag / restore flag * formatting * removed flagging * removed * load value * fixing typing * fixes, typing * fixes * file * handling images * formatting * fixed serializing for flagging * formatting * json * temp file * removed processing * changed processing * fixed temp FINALLY * flagging works * fix examples test * formatting * async examples * working on mix * comment out failing test * fixed interface problem * fix kitchen sink deprecation warning * gallery examples * fixes * fixes to serialization * fixing label serializing * fixed file serialization * kitchen sink restored * outbreak forecast updated * formatting * formatting and api mode * fix 1 test :/ * fixing tests * fixed components tests * remvoed test files * formatting * fixed examples * fixes * formatting * restored certain files * added encryption * fixed syntax mistake * formatting * fixed 1 test * clean up interface * formatting * fixed route tests * more fixes * formatting * formatting * fixing pipeline * format frontend * format backend * tweaks * fix * fix final test? * merged * Sanitize for CSV (#2017) * sanitize for csv * added sanitization logic * fixed examples * turn cache off * fixed example caching with optional inputs * fixed review problems * fixed Interface.load * updating the tests * updating the tests * fix * fixed seriailizing * testing * rewrite run prediction * formatting * await * fixes * formatting * finally fixed mix * fixed tests * formatting * formatting * deserialize fix * formatting * fixes * fixes * fix * fix tests * fixes Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com>
2022-08-23 23:31:04 +08:00
assert filecmp.cmp(
video_input.serialize(x_video["name"])[0]["name"], x_video["name"]
)
# Output functionalities
y_vid_path = "test/test_files/video_sample.mp4"
subtitles_path = "test/test_files/s1.srt"
video_output = gr.Video()
output1 = video_output.postprocess(y_vid_path)[0]["name"]
assert output1.endswith("mp4")
output2 = video_output.postprocess(y_vid_path)[0]["name"]
assert output1 == output2
assert (
video_output.postprocess(y_vid_path)[0]["orig_name"] == "video_sample.mp4"
)
output_with_subtitles = video_output.postprocess((y_vid_path, subtitles_path))
assert output_with_subtitles[1]["data"].startswith("data")
assert video_output.deserialize(
(
{
"name": None,
"data": deepcopy(media_data.BASE64_VIDEO)["data"],
"is_file": False,
},
None,
)
).endswith(".mp4")
p_video = gr.Video()
video_with_subtitle = gr.Video()
postprocessed_video = p_video.postprocess(Path(y_vid_path))
postprocessed_video_with_subtitle = video_with_subtitle.postprocess(
(Path(y_vid_path), Path(subtitles_path))
)
processed_video = (
{
"name": "video_sample.mp4",
"data": None,
"is_file": True,
"orig_name": "video_sample.mp4",
},
None,
)
processed_video_with_subtitle = (
{
"name": "video_sample.mp4",
"data": None,
"is_file": True,
"orig_name": "video_sample.mp4",
},
{"name": None, "data": True, "is_file": False},
)
postprocessed_video[0]["name"] = os.path.basename(
postprocessed_video[0]["name"]
)
assert processed_video == postprocessed_video
postprocessed_video_with_subtitle[0]["name"] = os.path.basename(
postprocessed_video_with_subtitle[0]["name"]
)
if postprocessed_video_with_subtitle[1]["data"]:
postprocessed_video_with_subtitle[1]["data"] = True
assert processed_video_with_subtitle == postprocessed_video_with_subtitle
def test_in_interface(self):
"""
Interface, process
"""
x_video = media_data.BASE64_VIDEO["name"]
iface = gr.Interface(lambda x: x, "video", "playable_video")
assert iface(x_video).endswith(".mp4")
def test_with_waveform(self):
"""
Interface, process
"""
x_audio = media_data.BASE64_AUDIO["name"]
iface = gr.Interface(lambda x: gr.make_waveform(x), "audio", "video")
assert iface(x_audio).endswith(".mp4")
def test_video_postprocess_converts_to_playable_format(self):
test_file_dir = Path(Path(__file__).parent, "test_files")
# This file has a playable container but not playable codec
with tempfile.NamedTemporaryFile(
suffix="bad_video.mp4", delete=False
) as tmp_not_playable_vid:
bad_vid = str(test_file_dir / "bad_video_sample.mp4")
assert not processing_utils.video_is_playable(bad_vid)
shutil.copy(bad_vid, tmp_not_playable_vid.name)
output = gr.Video().postprocess(tmp_not_playable_vid.name)
assert processing_utils.video_is_playable(output[0]["name"])
# This file has a playable codec but not a playable container
with tempfile.NamedTemporaryFile(
suffix="playable_but_bad_container.mkv", delete=False
) as tmp_not_playable_vid:
bad_vid = str(test_file_dir / "playable_but_bad_container.mkv")
assert not processing_utils.video_is_playable(bad_vid)
shutil.copy(bad_vid, tmp_not_playable_vid.name)
output = gr.Video().postprocess(tmp_not_playable_vid.name)
assert processing_utils.video_is_playable(output[0]["name"])
@patch("pathlib.Path.exists", MagicMock(return_value=False))
@patch("gradio.components.video.FFmpeg")
def test_video_preprocessing_flips_video_for_webcam(self, mock_ffmpeg):
# Ensures that the cached temp video file is not used so that ffmpeg is called for each test
x_video = deepcopy(media_data.BASE64_VIDEO)
video_input = gr.Video(source="webcam")
_ = video_input.preprocess(x_video)
# Dict mapping filename to FFmpeg options
output_params = mock_ffmpeg.call_args_list[0][1]["outputs"]
assert "hflip" in list(output_params.values())[0]
assert "flip" in list(output_params.keys())[0]
mock_ffmpeg.reset_mock()
_ = gr.Video(
source="webcam", mirror_webcam=False, include_audio=True
).preprocess(x_video)
mock_ffmpeg.assert_not_called()
mock_ffmpeg.reset_mock()
_ = gr.Video(source="upload", format="mp4", include_audio=True).preprocess(
x_video
)
mock_ffmpeg.assert_not_called()
mock_ffmpeg.reset_mock()
output_file = gr.Video(
source="webcam", mirror_webcam=True, format="avi"
).preprocess(x_video)
output_params = mock_ffmpeg.call_args_list[0][1]["outputs"]
assert "hflip" in list(output_params.values())[0]
assert "flip" in list(output_params.keys())[0]
assert ".avi" in list(output_params.keys())[0]
assert ".avi" in output_file
mock_ffmpeg.reset_mock()
output_file = gr.Video(
source="webcam", mirror_webcam=False, format="avi", include_audio=False
).preprocess(x_video)
output_params = mock_ffmpeg.call_args_list[0][1]["outputs"]
assert list(output_params.values())[0] == ["-an"]
assert "flip" not in Path(list(output_params.keys())[0]).name
assert ".avi" in list(output_params.keys())[0]
assert ".avi" in output_file
@pytest.mark.flaky
def test_preprocess_url(self):
output = gr.Video().preprocess(
{
"name": "https://gradio-builds.s3.amazonaws.com/demo-files/a.mp4",
"is_file": True,
"data": None,
"size": None,
"orig_name": "https://gradio-builds.s3.amazonaws.com/demo-files/a.mp4",
}
)
assert Path(output).name == "a.mp4" and not client_utils.probe_url(output)
class TestTimeseries:
def test_component_functions(self):
"""
Preprocess, postprocess, get_config,
"""
timeseries_input = gr.Timeseries(x="time", y=["retail", "food", "other"])
x_timeseries = {
"data": [[1] + [2] * len(timeseries_input.y)] * 4,
"headers": [timeseries_input.x] + timeseries_input.y,
}
output = timeseries_input.preprocess(x_timeseries)
assert isinstance(output, pd.core.frame.DataFrame)
timeseries_input = gr.Timeseries(
x="time", y="retail", label="Upload Your Timeseries"
)
assert timeseries_input.get_config() == {
"x": "time",
"y": ["retail"],
"name": "timeseries",
"show_label": True,
"label": "Upload Your Timeseries",
"colors": None,
"container": True,
"min_width": 160,
"scale": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"value": None,
"interactive": None,
"root_url": None,
}
assert timeseries_input.preprocess(None) is None
x_timeseries["range"] = (0, 1)
assert timeseries_input.preprocess(x_timeseries) is not None
# Output functionalities
timeseries_output = gr.Timeseries(label="Disease")
assert timeseries_output.get_config() == {
"x": None,
"y": None,
"name": "timeseries",
"show_label": True,
"label": "Disease",
"colors": None,
"container": True,
"min_width": 160,
"scale": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"value": None,
"interactive": None,
"root_url": None,
}
data = {"Name": ["Tom", "nick", "krish", "jack"], "Age": [20, 21, 19, 18]}
df = pd.DataFrame(data)
assert timeseries_output.postprocess(df) == {
"headers": ["Name", "Age"],
"data": [["Tom", 20], ["nick", 21], ["krish", 19], ["jack", 18]],
}
timeseries_output = gr.Timeseries(y="Age", label="Disease")
output = timeseries_output.postprocess(df)
assert output == {
"headers": ["Name", "Age"],
"data": [["Tom", 20], ["nick", 21], ["krish", 19], ["jack", 18]],
}
2022-04-07 06:40:28 +08:00
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)
class TestLabel:
def test_component_functions(self):
"""
Cleaning up the way data is processed for components (#1967) * remove preprocess_example * removing methods * added path support for images * fixes * video * formatting * fixing preprocess * fixes * removed from audio * fixed file * formatting * serialization * foramtting * formatting * removed save flag / restore flag * formatting * removed flagging * removed * load value * fixing typing * fixes, typing * fixes * file * handling images * formatting * fixed serializing for flagging * formatting * json * temp file * removed processing * changed processing * fixed temp FINALLY * flagging works * fix examples test * formatting * async examples * working on mix * comment out failing test * fixed interface problem * fix kitchen sink deprecation warning * gallery examples * fixes * fixes to serialization * fixing label serializing * fixed file serialization * kitchen sink restored * outbreak forecast updated * formatting * formatting and api mode * fix 1 test :/ * fixing tests * fixed components tests * remvoed test files * formatting * fixed examples * fixes * formatting * restored certain files * added encryption * fixed syntax mistake * formatting * fixed 1 test * clean up interface * formatting * fixed route tests * more fixes * formatting * formatting * fixing pipeline * format frontend * format backend * tweaks * fix * fix final test? * merged * Sanitize for CSV (#2017) * sanitize for csv * added sanitization logic * fixed examples * turn cache off * fixed example caching with optional inputs * fixed review problems * fixed Interface.load * updating the tests * updating the tests * fix * fixed seriailizing * testing * rewrite run prediction * formatting * await * fixes * formatting * finally fixed mix * fixed tests * formatting * formatting * deserialize fix * formatting * fixes * fixes * fix * fix tests * fixes Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com>
2022-08-23 23:31:04 +08:00
Process, postprocess, deserialize
"""
y = "happy"
label_output = gr.Label()
label = label_output.postprocess(y)
assert label == {"label": "happy"}
with open(label_output.deserialize(label)) as f:
assert json.load(f) == label
Cleaning up the way data is processed for components (#1967) * remove preprocess_example * removing methods * added path support for images * fixes * video * formatting * fixing preprocess * fixes * removed from audio * fixed file * formatting * serialization * foramtting * formatting * removed save flag / restore flag * formatting * removed flagging * removed * load value * fixing typing * fixes, typing * fixes * file * handling images * formatting * fixed serializing for flagging * formatting * json * temp file * removed processing * changed processing * fixed temp FINALLY * flagging works * fix examples test * formatting * async examples * working on mix * comment out failing test * fixed interface problem * fix kitchen sink deprecation warning * gallery examples * fixes * fixes to serialization * fixing label serializing * fixed file serialization * kitchen sink restored * outbreak forecast updated * formatting * formatting and api mode * fix 1 test :/ * fixing tests * fixed components tests * remvoed test files * formatting * fixed examples * fixes * formatting * restored certain files * added encryption * fixed syntax mistake * formatting * fixed 1 test * clean up interface * formatting * fixed route tests * more fixes * formatting * formatting * fixing pipeline * format frontend * format backend * tweaks * fix * fix final test? * merged * Sanitize for CSV (#2017) * sanitize for csv * added sanitization logic * fixed examples * turn cache off * fixed example caching with optional inputs * fixed review problems * fixed Interface.load * updating the tests * updating the tests * fix * fixed seriailizing * testing * rewrite run prediction * formatting * await * fixes * formatting * finally fixed mix * fixed tests * formatting * formatting * deserialize fix * formatting * fixes * fixes * fix * fix tests * fixes Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com>
2022-08-23 23:31:04 +08:00
y = {3: 0.7, 1: 0.2, 0: 0.1}
label = label_output.postprocess(y)
assert label == {
"label": 3,
"confidences": [
{"label": 3, "confidence": 0.7},
{"label": 1, "confidence": 0.2},
{"label": 0, "confidence": 0.1},
],
}
label_output = gr.Label(num_top_classes=2)
label = label_output.postprocess(y)
assert label == {
"label": 3,
"confidences": [
{"label": 3, "confidence": 0.7},
{"label": 1, "confidence": 0.2},
],
}
with pytest.raises(ValueError):
label_output.postprocess([1, 2, 3])
test_file_dir = Path(Path(__file__).parent, "test_files")
path = str(Path(test_file_dir, "test_label_json.json"))
label_dict = label_output.postprocess(path)
assert label_dict["label"] == "web site"
assert label_output.get_config() == {
"name": "label",
"show_label": True,
"num_top_classes": 2,
"value": {},
"label": None,
"container": True,
"min_width": 160,
"scale": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"root_url": None,
"color": None,
"selectable": False,
}
def test_color_argument(self):
label = gr.Label(value=-10, color="red")
assert label.get_config()["color"] == "red"
update_1 = gr.Label.update(value="bad", color="brown")
assert update_1["color"] == "brown"
update_2 = gr.Label.update(value="bad", color="#ff9966")
assert update_2["color"] == "#ff9966"
update_3 = gr.Label.update(
value={"bad": 0.9, "good": 0.09, "so-so": 0.01}, color="green"
)
assert update_3["color"] == "green"
update_4 = gr.Label.update(value={"bad": 0.8, "good": 0.18, "so-so": 0.02})
assert update_4["color"] is None
update_5 = gr.Label.update(
value={"bad": 0.8, "good": 0.18, "so-so": 0.02}, color=None
)
assert update_5["color"] == "transparent"
def test_in_interface(self):
"""
Interface, process
"""
x_img = "test/test_files/bus.png"
def rgb_distribution(img):
rgb_dist = np.mean(img, axis=(0, 1))
rgb_dist /= np.sum(rgb_dist)
rgb_dist = np.round(rgb_dist, decimals=2)
return {
"red": rgb_dist[0],
"green": rgb_dist[1],
"blue": rgb_dist[2],
}
iface = gr.Interface(rgb_distribution, "image", "label")
output_filepath = iface(x_img)
with open(output_filepath) as fp:
assert json.load(fp) == {
"label": "red",
"confidences": [
{"label": "red", "confidence": 0.44},
{"label": "green", "confidence": 0.28},
{"label": "blue", "confidence": 0.28},
],
}
class TestHighlightedText:
def test_postprocess(self):
"""
postprocess
"""
component = gr.HighlightedText()
result = [
("", None),
("Wolfgang", "PER"),
(" lives in ", None),
("Berlin", "LOC"),
("", None),
]
result_ = component.postprocess(result)
assert result == result_
text = "Wolfgang lives in Berlin"
entities = [
{"entity": "PER", "start": 0, "end": 8},
{"entity": "LOC", "start": 18, "end": 24},
]
result_ = component.postprocess({"text": text, "entities": entities})
assert result == result_
text = "Wolfgang lives in Berlin"
entities = [
{"entity_group": "PER", "start": 0, "end": 8},
{"entity": "LOC", "start": 18, "end": 24},
]
result_ = component.postprocess({"text": text, "entities": entities})
assert result == result_
# Test split entity is merged when combine adjacent is set
text = "Wolfgang lives in Berlin"
entities = [
{"entity": "PER", "start": 0, "end": 4},
{"entity": "PER", "start": 4, "end": 8},
{"entity": "LOC", "start": 18, "end": 24},
]
# After a merge empty entries are stripped except the leading one
result_after_merge = [
("", None),
("Wolfgang", "PER"),
(" lives in ", None),
("Berlin", "LOC"),
]
result_ = component.postprocess({"text": text, "entities": entities})
assert result != result_
assert result_after_merge != result_
component = gr.HighlightedText(combine_adjacent=True)
result_ = component.postprocess({"text": text, "entities": entities})
assert result_after_merge == result_
component = gr.HighlightedText()
text = "Wolfgang lives in Berlin"
entities = [
{"entity": "LOC", "start": 18, "end": 24},
{"entity": "PER", "start": 0, "end": 8},
]
result_ = component.postprocess({"text": text, "entities": entities})
assert result == result_
text = "I live there"
entities = []
result_ = component.postprocess({"text": text, "entities": entities})
assert [(text, None)] == result_
text = "Wolfgang"
entities = [
{"entity": "PER", "start": 0, "end": 8},
]
result_ = component.postprocess({"text": text, "entities": entities})
assert [("", None), (text, "PER"), ("", None)] == result_
def test_component_functions(self):
"""
Cleaning up the way data is processed for components (#1967) * remove preprocess_example * removing methods * added path support for images * fixes * video * formatting * fixing preprocess * fixes * removed from audio * fixed file * formatting * serialization * foramtting * formatting * removed save flag / restore flag * formatting * removed flagging * removed * load value * fixing typing * fixes, typing * fixes * file * handling images * formatting * fixed serializing for flagging * formatting * json * temp file * removed processing * changed processing * fixed temp FINALLY * flagging works * fix examples test * formatting * async examples * working on mix * comment out failing test * fixed interface problem * fix kitchen sink deprecation warning * gallery examples * fixes * fixes to serialization * fixing label serializing * fixed file serialization * kitchen sink restored * outbreak forecast updated * formatting * formatting and api mode * fix 1 test :/ * fixing tests * fixed components tests * remvoed test files * formatting * fixed examples * fixes * formatting * restored certain files * added encryption * fixed syntax mistake * formatting * fixed 1 test * clean up interface * formatting * fixed route tests * more fixes * formatting * formatting * fixing pipeline * format frontend * format backend * tweaks * fix * fix final test? * merged * Sanitize for CSV (#2017) * sanitize for csv * added sanitization logic * fixed examples * turn cache off * fixed example caching with optional inputs * fixed review problems * fixed Interface.load * updating the tests * updating the tests * fix * fixed seriailizing * testing * rewrite run prediction * formatting * await * fixes * formatting * finally fixed mix * fixed tests * formatting * formatting * deserialize fix * formatting * fixes * fixes * fix * fix tests * fixes Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com>
2022-08-23 23:31:04 +08:00
get_config
"""
ht_output = gr.HighlightedText(color_map={"pos": "green", "neg": "red"})
assert ht_output.get_config() == {
"color_map": {"pos": "green", "neg": "red"},
"name": "highlightedtext",
"show_label": True,
"label": None,
"show_legend": False,
"container": True,
"min_width": 160,
"scale": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"value": None,
"root_url": None,
"selectable": False,
"combine_adjacent": False,
"adjacent_separator": "",
"interactive": None,
}
def test_in_interface(self):
"""
Interface, process
"""
def highlight_vowels(sentence):
phrases, cur_phrase = [], ""
vowels, mode = "aeiou", None
for letter in sentence:
letter_mode = "vowel" if letter in vowels else "non"
if mode is None:
mode = letter_mode
elif mode != letter_mode:
phrases.append((cur_phrase, mode))
cur_phrase = ""
mode = letter_mode
cur_phrase += letter
phrases.append((cur_phrase, mode))
return phrases
iface = gr.Interface(highlight_vowels, "text", "highlight")
output_filepath = iface("Helloooo")
with open(output_filepath) as fp:
output = json.load(fp)
assert output == [
["H", "non"],
["e", "vowel"],
["ll", "non"],
["oooo", "vowel"],
]
class TestAnnotatedImage:
def test_postprocess(self):
"""
postprocess
"""
component = gr.AnnotatedImage()
img = np.random.randint(0, 255, (100, 100, 3), dtype=np.uint8)
mask1 = [40, 40, 50, 50]
mask2 = np.zeros((100, 100), dtype=np.uint8)
mask2[10:20, 10:20] = 1
input = (img, [(mask1, "mask1"), (mask2, "mask2")])
result = component.postprocess(input)
base_img_out, (mask1_out, mask2_out) = result
base_img_out = PIL.Image.open(base_img_out["name"])
assert mask1_out[1] == "mask1"
mask1_img_out = PIL.Image.open(mask1_out[0]["name"])
assert mask1_img_out.size == base_img_out.size
mask1_array_out = np.array(mask1_img_out)
assert np.max(mask1_array_out[40:50, 40:50]) == 255
assert np.max(mask1_array_out[50:60, 50:60]) == 0
def test_component_functions(self):
ht_output = gr.AnnotatedImage(label="sections", show_legend=False)
assert ht_output.get_config() == {
"name": "annotatedimage",
"show_label": True,
"label": "sections",
"show_legend": False,
"container": True,
"min_width": 160,
"scale": None,
"color_map": None,
"height": None,
"width": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"value": None,
"root_url": None,
"selectable": False,
}
def test_in_interface(self):
def mask(img):
top_left_corner = [0, 0, 20, 20]
random_mask = np.random.randint(0, 2, img.shape[:2])
return (img, [(top_left_corner, "left corner"), (random_mask, "random")])
iface = gr.Interface(mask, "image", gr.AnnotatedImage())
output_json = iface("test/test_files/bus.png")
with open(output_json) as fp:
output = json.load(fp)
output_img, (mask1, mask1) = output
input_img = PIL.Image.open("test/test_files/bus.png")
output_img = PIL.Image.open(output_img["name"])
mask1_img = PIL.Image.open(mask1[0]["name"])
assert output_img.size == input_img.size
assert mask1_img.size == input_img.size
class TestChatbot:
def test_component_functions(self):
"""
Postprocess, get_config
"""
chatbot = gr.Chatbot()
assert chatbot.postprocess([["You are **cool**\nand fun", "so are *you*"]]) == [
["You are **cool**\nand fun", "so are *you*"]
]
multimodal_msg = [
[("test/test_files/video_sample.mp4",), "cool video"],
[("test/test_files/audio_sample.wav",), "cool audio"],
[("test/test_files/bus.png", "A bus"), "cool pic"],
[(Path("test/test_files/video_sample.mp4"),), "cool video"],
[(Path("test/test_files/audio_sample.wav"),), "cool audio"],
[(Path("test/test_files/bus.png"), "A bus"), "cool pic"],
]
processed_multimodal_msg = [
[
{
"name": "video_sample.mp4",
"mime_type": "video/mp4",
"alt_text": None,
"data": None,
"is_file": True,
},
"cool video",
],
[
{
"name": "audio_sample.wav",
"mime_type": "audio/wav",
"alt_text": None,
"data": None,
"is_file": True,
},
"cool audio",
],
[
{
"name": "bus.png",
"mime_type": "image/png",
"alt_text": "A bus",
"data": None,
"is_file": True,
},
"cool pic",
],
] * 2
postprocessed_multimodal_msg = chatbot.postprocess(multimodal_msg)
postprocessed_multimodal_msg_base_names = []
for x, y in postprocessed_multimodal_msg:
if isinstance(x, dict):
x["name"] = os.path.basename(x["name"])
postprocessed_multimodal_msg_base_names.append([x, y])
assert postprocessed_multimodal_msg_base_names == processed_multimodal_msg
preprocessed_multimodal_msg = chatbot.preprocess(processed_multimodal_msg)
multimodal_msg_base_names = []
for x, y in multimodal_msg:
if isinstance(x, tuple):
if len(x) > 1:
new_x = (os.path.basename(x[0]), x[1])
else:
new_x = (os.path.basename(x[0]),)
multimodal_msg_base_names.append([new_x, y])
assert multimodal_msg_base_names == preprocessed_multimodal_msg
assert chatbot.get_config() == {
"value": [],
"label": None,
"show_label": True,
"name": "chatbot",
"show_share_button": False,
"visible": True,
"elem_id": None,
"elem_classes": None,
"container": True,
"min_width": 160,
"scale": None,
"height": None,
"root_url": None,
"selectable": False,
"latex_delimiters": [{"display": True, "left": "$$", "right": "$$"}],
"likeable": False,
"rtl": False,
"show_copy_button": False,
"avatar_images": (None, None),
Adds kwarg to disable html sanitization in `gr.Chatbot()` (#5304) * disable sanitize * add changeset * Fix devcontainer postCreateCommand (#5289) * add chmod commands to grant execute permissions to each script before running them * increase the memory limit * Increase memory requirement to 8 * Setting a minimum specification for codespace machines * Rotate axes labels on LinePlot, BarPlot, and ScatterPlot (#5305) * add chmod commands to grant execute permissions to each script before running them * increase the memory limit * Increase memory requirement to 8 * Setting a minimum specification for codespace machines * Added label_angle parameter to LinePlot * add the x_label_angle and y_label_angle to the postprocess * Add x_label_angle and y_label_angle to ScatterPlot * Add x_label_angle and y_label_angle to BarPlot * Remove postCreateCommand update from this PR, it is in its own PR * Remove custumization on the devcontainer, it is on another PR * Remove extra line on the devcontainer, it is on another PR * add changeset * update the parameter definition in the docstring --------- Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> * `make_waveform()` twitter video resolution fix (#5296) * waveform res fix * add changeset * add changeset * Improve audio streaming (#5238) * changes * changes * add changeset * add changeset * chages * Update silver-clowns-brush.md * changes * chagers * changes * Update silver-clowns-brush.md * change * change --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> Co-authored-by: pngwn <hello@pngwn.io> * Tweaks to `icon` parameter in `gr.Button()` (#5285) * button * add changeset * fix * add changeset * add changeset * types * type fix * formatting * fix based on review * fix unit tests * stories --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> * test * test --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> Co-authored-by: aliabid94 <aabid94@gmail.com> Co-authored-by: pngwn <hello@pngwn.io> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Allow caching examples with streamed output (#5295) * changes * changes * add changeset * add changeset * chages * Update silver-clowns-brush.md * changes * chagers * changes * Update silver-clowns-brush.md * change * change * change * changes * chages * changes * add changeset * changes * changes * changes --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> Co-authored-by: pngwn <hello@pngwn.io> * Create event listener table for components on docs (#5298) * changes * changes * remove languages from code docs * fix img path in guide * rework event listeners * add changeset * remove console log * name it event arguments * Update js/_website/src/lib/components/EventListeners.svelte Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Update js/_website/src/lib/components/EventListeners.svelte Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * requested changes --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * merge * fix (#5308) * only start listening for events after the components are mounted (#5312) * only start listening for events after the components are mounted * add changeset --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> * Restores missing part of bottom border on file component (#5313) * removes missing part of bottom border on file component * add changeset * add changeset --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> * chore: update versions (#5177) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Test Blocks.svelte footer copy (#5307) * test test * fix test * tweak * tweak test name * ensure login form has correct styles (#5324) * fix changelog generation (#5328) * Add ignore scripts to pnpm i in pypi action (#5316) * add json generation to prepare * add changeset * remove pnpm prepare * add changeset * bring back prepare, add ignore scripts * delete changeset * add to right commadn * add frozen lockfile to gh_action_pypi * remove unused gh_action_pypi script * remove unused scripts --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> * ensure dropdown stays open when identical data is passed in (#5323) * ensure dropwdown stays open when new data is passed in * add changeset * add changeset --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> * Fix ci again again again (#5329) * fix changelog generation * fix changelog generation * fix * chore: update versions (#5326) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Fix ci again again again (#5330) * fix changelog generation * fix changelog generation * fix * fix script * Fix ci again again again (#5331) * fix changelog generation * fix changelog generation * fix * fix script * fix script * Fix ci again again again (#5332) * fix changelog generation * fix changelog generation * fix * fix script * fix script * fix vars * Fix ci again again again (#5333) * fix changelog generation * fix changelog generation * fix * fix script * fix script * fix vars * fix vars * Fix Checkbox select dispatch (#5340) * Fix bug * add changeset --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> * Minor bug fix sweep (#5284) * changes * changes * add changeset * changes * changes * fix box changes on website * add changeset * changes * changes * Revert "changes" This reverts commit 189b4e844a9d30a45f4d4fb855397ae592a9b725. * chanegs * changes * changes * changes * changes * add changeset * Update fancy-bats-deny.md --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> Co-authored-by: aliabd <ali.si3luwa@gmail.com> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Fix: wrap avatar-image in a div to clip its shape (#5319) * fix: wrap avatar-image in a div to clip its shape and add data url support * add changeset * revert get file from data url * add changeset --------- Co-authored-by: Dawood Khan <dawoodkhan82@gmail.com> Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> * chore: update versions (#5341) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * add kwarg to markdown * add changeset * config --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> Co-authored-by: Faiga Alawad <faiga.alawd91@gmail.com> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: aliabid94 <aabid94@gmail.com> Co-authored-by: pngwn <hello@pngwn.io> Co-authored-by: Ali Abdalla <ali.si3luwa@gmail.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Hannah <hannahblair@users.noreply.github.com> Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com> Co-authored-by: Keldos <Keldos.ljw@gmail.com>
2023-08-29 12:26:29 +08:00
"sanitize_html": True,
"render_markdown": True,
"bubble_full_width": True,
}
class TestJSON:
def test_component_functions(self):
"""
Cleaning up the way data is processed for components (#1967) * remove preprocess_example * removing methods * added path support for images * fixes * video * formatting * fixing preprocess * fixes * removed from audio * fixed file * formatting * serialization * foramtting * formatting * removed save flag / restore flag * formatting * removed flagging * removed * load value * fixing typing * fixes, typing * fixes * file * handling images * formatting * fixed serializing for flagging * formatting * json * temp file * removed processing * changed processing * fixed temp FINALLY * flagging works * fix examples test * formatting * async examples * working on mix * comment out failing test * fixed interface problem * fix kitchen sink deprecation warning * gallery examples * fixes * fixes to serialization * fixing label serializing * fixed file serialization * kitchen sink restored * outbreak forecast updated * formatting * formatting and api mode * fix 1 test :/ * fixing tests * fixed components tests * remvoed test files * formatting * fixed examples * fixes * formatting * restored certain files * added encryption * fixed syntax mistake * formatting * fixed 1 test * clean up interface * formatting * fixed route tests * more fixes * formatting * formatting * fixing pipeline * format frontend * format backend * tweaks * fix * fix final test? * merged * Sanitize for CSV (#2017) * sanitize for csv * added sanitization logic * fixed examples * turn cache off * fixed example caching with optional inputs * fixed review problems * fixed Interface.load * updating the tests * updating the tests * fix * fixed seriailizing * testing * rewrite run prediction * formatting * await * fixes * formatting * finally fixed mix * fixed tests * formatting * formatting * deserialize fix * formatting * fixes * fixes * fix * fix tests * fixes Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com>
2022-08-23 23:31:04 +08:00
Postprocess
"""
js_output = gr.JSON()
assert js_output.postprocess('{"a":1, "b": 2}'), '"{\\"a\\":1, \\"b\\": 2}"'
assert js_output.get_config() == {
"container": True,
"min_width": 160,
"scale": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"value": None,
"show_label": True,
"label": None,
"name": "json",
"root_url": None,
}
@pytest.mark.asyncio
async def test_in_interface(self):
"""
Interface, process
"""
def get_avg_age_per_gender(data):
return {
"M": int(data[data["gender"] == "M"]["age"].mean()),
"F": int(data[data["gender"] == "F"]["age"].mean()),
"O": int(data[data["gender"] == "O"]["age"].mean()),
}
iface = gr.Interface(
get_avg_age_per_gender,
gr.Dataframe(headers=["gender", "age"]),
"json",
)
y_data = [
["M", 30],
["F", 20],
["M", 40],
["O", 20],
["F", 30],
]
assert (
await iface.process_api(
0, [{"data": y_data, "headers": ["gender", "age"]}], state={}
)
)["data"][0] == {
"M": 35,
"F": 25,
"O": 20,
}
class TestHTML:
def test_component_functions(self):
"""
get_config
"""
html_component = gr.components.HTML("#Welcome onboard", label="HTML Input")
assert html_component.get_config() == {
"value": "#Welcome onboard",
"label": "HTML Input",
"show_label": True,
"visible": True,
"elem_id": None,
"elem_classes": None,
"root_url": None,
"name": "html",
}
def test_in_interface(self):
"""
Interface, process
"""
def bold_text(text):
return f"<strong>{text}</strong>"
iface = gr.Interface(bold_text, "text", "html")
assert iface("test") == "<strong>test</strong>"
class TestMarkdown:
def test_component_functions(self):
markdown_component = gr.Markdown("# Let's learn about $x$", label="Markdown")
assert markdown_component.get_config()["value"] == "# Let's learn about $x$"
def test_in_interface(self):
"""
Interface, process
"""
iface = gr.Interface(lambda x: x, "text", "markdown")
input_data = " Here's an [image](https://gradio.app/images/gradio_logo.png)"
output_data = iface(input_data)
assert output_data == input_data.strip()
class TestModel3D:
def test_component_functions(self):
"""
get_config
"""
model_component = gr.components.Model3D(None, label="Model")
assert model_component.get_config() == {
"value": None,
"clear_color": [0, 0, 0, 0],
"label": "Model",
"show_label": True,
"container": True,
"scale": None,
"min_width": 160,
"visible": True,
"elem_id": None,
"elem_classes": None,
"root_url": None,
"name": "model3d",
"camera_position": (None, None, None),
"height": None,
"zoom_speed": 1,
}
file = "test/test_files/Box.gltf"
output1 = model_component.postprocess(file)
output2 = model_component.postprocess(Path(file))
assert output1 == output2
def test_in_interface(self):
"""
Interface, process
"""
iface = gr.Interface(lambda x: x, "model3d", "model3d")
input_data = "test/test_files/Box.gltf"
output_data = iface(input_data)
assert output_data.endswith(".gltf")
class TestColorPicker:
def test_component_functions(self):
"""
Preprocess, postprocess, serialize, tokenize, get_config
"""
color_picker_input = gr.ColorPicker()
assert color_picker_input.preprocess("#000000") == "#000000"
assert color_picker_input.postprocess("#000000") == "#000000"
assert color_picker_input.postprocess(None) is None
assert color_picker_input.postprocess("#FFFFFF") == "#FFFFFF"
assert color_picker_input.serialize("#000000", True) == "#000000"
color_picker_input.interpretation_replacement = "unknown"
assert color_picker_input.get_config() == {
"value": None,
"show_label": True,
"label": None,
"container": True,
"min_width": 160,
"scale": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"interactive": None,
"root_url": None,
"name": "colorpicker",
"info": None,
}
def test_in_interface_as_input(self):
"""
Interface, process, interpret,
"""
iface = gr.Interface(lambda x: x, "colorpicker", "colorpicker")
assert iface("#000000") == "#000000"
def test_in_interface_as_output(self):
"""
Interface, process
"""
iface = gr.Interface(lambda x: x, "colorpicker", gr.ColorPicker())
assert iface("#000000") == "#000000"
def test_static(self):
"""
postprocess
"""
component = gr.ColorPicker("#000000")
assert component.get_config().get("value") == "#000000"
class TestCarousel:
def test_deprecation(self):
test_file_dir = Path(Path(__file__).parent, "test_files")
with pytest.raises(DeprecationWarning):
gr.Carousel([Path(test_file_dir, "bus.png")])
def test_deprecation_in_interface(self):
with pytest.raises(DeprecationWarning):
gr.Interface(lambda x: ["lion.jpg"], "textbox", "carousel")
def test_deprecation_in_blocks(self):
with pytest.raises(DeprecationWarning):
with gr.Blocks():
gr.Textbox()
gr.Carousel()
class TestGallery:
@patch("uuid.uuid4", return_value="my-uuid")
def test_gallery(self, mock_uuid):
gallery = gr.Gallery()
test_file_dir = Path(Path(__file__).parent, "test_files")
data = [
client_utils.encode_file_to_base64(Path(test_file_dir, "bus.png")),
client_utils.encode_file_to_base64(Path(test_file_dir, "cheetah1.jpg")),
]
with tempfile.TemporaryDirectory() as tmpdir:
path = gallery.deserialize(data, tmpdir)
assert path.endswith("my-uuid")
data_restored = gallery.serialize(path)
data_restored = [d[0]["data"] for d in data_restored]
assert sorted(data) == sorted(data_restored)
postprocessed_gallery = gallery.postprocess([Path("test/test_files/bus.png")])
processed_gallery = [{"name": "bus.png", "data": None, "is_file": True}]
postprocessed_gallery[0]["name"] = os.path.basename(
postprocessed_gallery[0]["name"]
)
assert processed_gallery == postprocessed_gallery
class TestState:
def test_as_component(self):
state = gr.State(value=5)
assert state.preprocess(10) == 10
assert state.preprocess("abc") == "abc"
assert state.stateful
@pytest.mark.asyncio
async def test_in_interface(self):
def test(x, y=" def"):
return (x + y, x + y)
io = gr.Interface(test, ["text", "state"], ["text", "state"])
result = await io.call_function(0, ["abc"])
assert result["prediction"][0] == "abc def"
result = await io.call_function(0, ["abc", result["prediction"][0]])
assert result["prediction"][0] == "abcabc def"
@pytest.mark.asyncio
async def test_in_blocks(self):
with gr.Blocks() as demo:
score = gr.State()
btn = gr.Button()
btn.click(lambda x: x + 1, score, score)
result = await demo.call_function(0, [0])
assert result["prediction"] == 1
result = await demo.call_function(0, [result["prediction"]])
assert result["prediction"] == 2
@pytest.mark.asyncio
async def test_variable_for_backwards_compatibility(self):
with gr.Blocks() as demo:
score = gr.Variable()
btn = gr.Button()
btn.click(lambda x: x + 1, score, score)
result = await demo.call_function(0, [0])
assert result["prediction"] == 1
result = await demo.call_function(0, [result["prediction"]])
assert result["prediction"] == 2
def test_dataframe_as_example_converts_dataframes():
df_comp = gr.Dataframe()
assert df_comp.as_example(pd.DataFrame({"a": [1, 2, 3, 4], "b": [5, 6, 7, 8]})) == [
[1, 5],
[2, 6],
[3, 7],
[4, 8],
]
assert df_comp.as_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_as_example_returns_file_basename(component):
component = component()
assert component.as_example("/home/freddy/sources/example.ext") == "example.ext"
assert component.as_example(None) == ""
@patch("gradio.components.IOComponent.as_example")
@patch("gradio.components.Image.as_example")
@patch("gradio.components.File.as_example")
@patch("gradio.components.Dataframe.as_example")
@patch("gradio.components.Model3D.as_example")
def test_dataset_calls_as_example(*mocks):
gr.Dataset(
components=[gr.Dataframe(), gr.File(), gr.Image(), gr.Model3D(), gr.Textbox()],
samples=[
[
pd.DataFrame({"a": np.array([1, 2, 3])}),
"foo.png",
"bar.jpeg",
"duck.obj",
"hello",
]
],
)
assert all(m.called for m in mocks)
cars = vega_datasets.data.cars()
stocks = vega_datasets.data.stocks()
barley = vega_datasets.data.barley()
simple = pd.DataFrame(
{
"a": ["A", "B", "C", "D", "E", "F", "G", "H", "I"],
"b": [28, 55, 43, 91, 81, 53, 19, 87, 52],
}
)
class TestScatterPlot:
@patch.dict("sys.modules", {"bokeh": MagicMock(__version__="3.0.3")})
def test_get_config(self):
print(gr.ScatterPlot().get_config())
assert gr.ScatterPlot().get_config() == {
"caption": None,
"elem_id": None,
"elem_classes": None,
"interactive": None,
"label": None,
"name": "plot",
"bokeh_version": "3.0.3",
"show_actions_button": False,
"root_url": None,
"show_label": True,
"container": True,
"min_width": 160,
"scale": None,
"value": None,
"visible": True,
"x": None,
"y": None,
"color": None,
"size": None,
"shape": None,
"title": None,
"tooltip": None,
"x_title": None,
"y_title": None,
"color_legend_title": None,
"size_legend_title": None,
"shape_legend_title": None,
"color_legend_position": None,
"size_legend_position": None,
"shape_legend_position": None,
"height": None,
"width": None,
"x_lim": None,
"y_lim": None,
"x_label_angle": None,
"y_label_angle": None,
}
def test_no_color(self):
plot = gr.ScatterPlot(
x="Horsepower",
y="Miles_per_Gallon",
tooltip="Name",
title="Car Data",
x_title="Horse",
)
output = plot.postprocess(cars)
assert sorted(output.keys()) == ["chart", "plot", "type"]
config = json.loads(output["plot"])
assert config["encoding"]["x"]["field"] == "Horsepower"
assert config["encoding"]["x"]["title"] == "Horse"
assert config["encoding"]["y"]["field"] == "Miles_per_Gallon"
assert config["title"] == "Car Data"
assert "height" not in config
assert "width" not in config
def test_no_interactive(self):
plot = gr.ScatterPlot(
x="Horsepower", y="Miles_per_Gallon", tooltip="Name", interactive=False
)
output = plot.postprocess(cars)
assert sorted(output.keys()) == ["chart", "plot", "type"]
config = json.loads(output["plot"])
assert "selection" not in config
def test_height_width(self):
plot = gr.ScatterPlot(
x="Horsepower", y="Miles_per_Gallon", height=100, width=200
)
output = plot.postprocess(cars)
assert sorted(output.keys()) == ["chart", "plot", "type"]
config = json.loads(output["plot"])
assert config["height"] == 100
assert config["width"] == 200
def test_xlim_ylim(self):
plot = gr.ScatterPlot(
x="Horsepower", y="Miles_per_Gallon", x_lim=[200, 400], y_lim=[300, 500]
)
output = plot.postprocess(cars)
config = json.loads(output["plot"])
assert config["encoding"]["x"]["scale"] == {"domain": [200, 400]}
assert config["encoding"]["y"]["scale"] == {"domain": [300, 500]}
def test_color_encoding(self):
plot = gr.ScatterPlot(
x="Horsepower",
y="Miles_per_Gallon",
tooltip="Name",
title="Car Data",
color="Origin",
)
output = plot.postprocess(cars)
config = json.loads(output["plot"])
assert config["encoding"]["color"]["field"] == "Origin"
assert config["encoding"]["color"]["scale"] == {
"domain": ["USA", "Europe", "Japan"],
"range": [0, 1, 2],
}
assert config["encoding"]["color"]["type"] == "nominal"
def test_two_encodings(self):
plot = gr.ScatterPlot(
show_label=False,
title="Two encodings",
x="Horsepower",
y="Miles_per_Gallon",
color="Acceleration",
shape="Origin",
)
output = plot.postprocess(cars)
config = json.loads(output["plot"])
assert config["encoding"]["color"]["field"] == "Acceleration"
assert config["encoding"]["color"]["scale"] == {
"domain": [cars.Acceleration.min(), cars.Acceleration.max()],
"range": [0, 1],
}
assert config["encoding"]["color"]["type"] == "quantitative"
assert config["encoding"]["shape"]["field"] == "Origin"
assert config["encoding"]["shape"]["type"] == "nominal"
def test_legend_position(self):
plot = gr.ScatterPlot(
show_label=False,
title="Two encodings",
x="Horsepower",
y="Miles_per_Gallon",
color="Acceleration",
color_legend_position="none",
color_legend_title="Foo",
shape="Origin",
shape_legend_position="none",
shape_legend_title="Bar",
size="Acceleration",
size_legend_title="Accel",
size_legend_position="none",
)
output = plot.postprocess(cars)
config = json.loads(output["plot"])
assert config["encoding"]["color"]["legend"] is None
assert config["encoding"]["shape"]["legend"] is None
assert config["encoding"]["size"]["legend"] is None
output = gr.ScatterPlot.update(
value=cars,
title="Two encodings",
x="Horsepower",
y="Miles_per_Gallon",
color="Acceleration",
color_legend_position="top",
color_legend_title="Foo",
shape="Origin",
shape_legend_position="bottom",
shape_legend_title="Bar",
size="Acceleration",
size_legend_title="Accel",
size_legend_position="left",
)
config = json.loads(output["value"]["plot"])
assert config["encoding"]["color"]["legend"]["orient"] == "top"
assert config["encoding"]["shape"]["legend"]["orient"] == "bottom"
assert config["encoding"]["size"]["legend"]["orient"] == "left"
def test_update(self):
output = gr.ScatterPlot.update(value=cars, x="Horsepower", y="Miles_per_Gallon")
postprocessed = gr.ScatterPlot().postprocess(output["value"])
assert postprocessed == output["value"]
def test_update_visibility(self):
output = gr.ScatterPlot.update(visible=False)
assert not output["visible"]
assert output["value"] is gr.components._Keywords.NO_VALUE
def test_update_errors(self):
with pytest.raises(
ValueError, match="In order to update plot properties the value parameter"
):
gr.ScatterPlot.update(x="foo", y="bar")
with pytest.raises(
ValueError,
match="In order to update plot properties, the x and y axis data",
):
gr.ScatterPlot.update(value=cars, x="foo")
def test_scatterplot_accepts_fn_as_value(self):
plot = gr.ScatterPlot(
value=lambda: cars.sample(frac=0.1, replace=False),
x="Horsepower",
y="Miles_per_Gallon",
color="Origin",
)
assert isinstance(plot.value, dict)
assert isinstance(plot.value["plot"], str)
class TestLinePlot:
@patch.dict("sys.modules", {"bokeh": MagicMock(__version__="3.0.3")})
def test_get_config(self):
assert gr.LinePlot().get_config() == {
"caption": None,
"elem_id": None,
"elem_classes": None,
"interactive": None,
"label": None,
"name": "plot",
"bokeh_version": "3.0.3",
"show_actions_button": False,
"root_url": None,
"show_label": True,
"container": True,
"min_width": 160,
"scale": None,
"value": None,
"visible": True,
"x": None,
"y": None,
"color": None,
"stroke_dash": None,
"overlay_point": None,
"title": None,
"tooltip": None,
"x_title": None,
"y_title": None,
"color_legend_title": None,
"stroke_dash_legend_title": None,
"color_legend_position": None,
"stroke_dash_legend_position": None,
"height": None,
"width": None,
"x_lim": None,
"y_lim": None,
"x_label_angle": None,
"y_label_angle": None,
}
def test_no_color(self):
plot = gr.LinePlot(
x="date",
y="price",
tooltip=["symbol", "price"],
title="Stock Performance",
x_title="Trading Day",
)
output = plot.postprocess(stocks)
assert sorted(output.keys()) == ["chart", "plot", "type"]
config = json.loads(output["plot"])
for layer in config["layer"]:
assert layer["mark"]["type"] in ["line", "point"]
assert layer["encoding"]["x"]["field"] == "date"
assert layer["encoding"]["x"]["title"] == "Trading Day"
assert layer["encoding"]["y"]["field"] == "price"
assert config["title"] == "Stock Performance"
assert "height" not in config
assert "width" not in config
def test_height_width(self):
plot = gr.LinePlot(x="date", y="price", height=100, width=200)
output = plot.postprocess(stocks)
assert sorted(output.keys()) == ["chart", "plot", "type"]
config = json.loads(output["plot"])
assert config["height"] == 100
assert config["width"] == 200
output = gr.LinePlot.update(stocks, x="date", y="price", height=100, width=200)
config = json.loads(output["value"]["plot"])
assert config["height"] == 100
assert config["width"] == 200
def test_xlim_ylim(self):
plot = gr.LinePlot(x="date", y="price", x_lim=[200, 400], y_lim=[300, 500])
output = plot.postprocess(stocks)
config = json.loads(output["plot"])
for layer in config["layer"]:
assert layer["encoding"]["x"]["scale"] == {"domain": [200, 400]}
assert layer["encoding"]["y"]["scale"] == {"domain": [300, 500]}
def test_color_encoding(self):
plot = gr.LinePlot(
x="date", y="price", tooltip="symbol", color="symbol", overlay_point=True
)
output = plot.postprocess(stocks)
config = json.loads(output["plot"])
for layer in config["layer"]:
assert layer["encoding"]["color"]["field"] == "symbol"
assert layer["encoding"]["color"]["scale"] == {
"domain": ["MSFT", "AMZN", "IBM", "GOOG", "AAPL"],
"range": [0, 1, 2, 3, 4],
}
assert layer["encoding"]["color"]["type"] == "nominal"
if layer["mark"]["type"] == "point":
assert layer["encoding"]["opacity"] == {}
def test_two_encodings(self):
output = gr.LinePlot.update(
value=stocks,
title="Two encodings",
x="date",
y="price",
color="symbol",
stroke_dash="symbol",
color_legend_title="Color",
stroke_dash_legend_title="Stroke Dash",
)
config = json.loads(output["value"]["plot"])
for layer in config["layer"]:
if layer["mark"]["type"] == "point":
assert layer["encoding"]["opacity"] == {"value": 0}
if layer["mark"]["type"] == "line":
assert layer["encoding"]["strokeDash"]["field"] == "symbol"
assert (
layer["encoding"]["strokeDash"]["legend"]["title"] == "Stroke Dash"
)
def test_legend_position(self):
plot = gr.LinePlot(
value=stocks,
title="Two encodings",
x="date",
y="price",
color="symbol",
stroke_dash="symbol",
color_legend_position="none",
stroke_dash_legend_position="none",
)
output = plot.postprocess(stocks)
config = json.loads(output["plot"])
for layer in config["layer"]:
if layer["mark"]["type"] == "point":
assert layer["encoding"]["color"]["legend"] is None
if layer["mark"]["type"] == "line":
assert layer["encoding"]["strokeDash"]["legend"] is None
assert layer["encoding"]["color"]["legend"] is None
output = gr.LinePlot.update(
value=stocks,
title="Two encodings",
x="date",
y="price",
color="symbol",
stroke_dash="symbol",
color_legend_position="top-right",
stroke_dash_legend_position="top-left",
)
config = json.loads(output["value"]["plot"])
for layer in config["layer"]:
if layer["mark"]["type"] == "point":
assert layer["encoding"]["color"]["legend"]["orient"] == "top-right"
if layer["mark"]["type"] == "line":
assert layer["encoding"]["strokeDash"]["legend"]["orient"] == "top-left"
assert layer["encoding"]["color"]["legend"]["orient"] == "top-right"
def test_update_visibility(self):
output = gr.LinePlot.update(visible=False)
assert not output["visible"]
assert output["value"] is gr.components._Keywords.NO_VALUE
def test_update_errors(self):
with pytest.raises(
ValueError, match="In order to update plot properties the value parameter"
):
gr.LinePlot.update(x="foo", y="bar")
with pytest.raises(
ValueError,
match="In order to update plot properties, the x and y axis data",
):
gr.LinePlot.update(value=stocks, x="foo")
def test_lineplot_accepts_fn_as_value(self):
plot = gr.LinePlot(
value=lambda: stocks.sample(frac=0.1, replace=False),
x="date",
y="price",
color="symbol",
)
assert isinstance(plot.value, dict)
assert isinstance(plot.value["plot"], str)
class TestBarPlot:
@patch.dict("sys.modules", {"bokeh": MagicMock(__version__="3.0.3")})
def test_get_config(self):
assert gr.BarPlot().get_config() == {
"caption": None,
"elem_id": None,
"elem_classes": None,
"interactive": None,
"label": None,
"name": "plot",
"bokeh_version": "3.0.3",
"show_actions_button": False,
"root_url": None,
"show_label": True,
"container": True,
"min_width": 160,
"scale": None,
"value": None,
"visible": True,
"x": None,
"y": None,
"color": None,
"vertical": True,
"group": None,
"title": None,
"tooltip": None,
"x_title": None,
"y_title": None,
"color_legend_title": None,
"group_title": None,
"color_legend_position": None,
"height": None,
"width": None,
"y_lim": None,
"x_label_angle": None,
"y_label_angle": None,
"sort": None,
}
def test_update_defaults_none(self):
output = gr.BarPlot.update(simple, x="a", y="b", height=100, width=200)
assert all(
v is None for k, v in output.items() if k not in ["value", "__type__"]
)
def test_no_color(self):
plot = gr.BarPlot(
x="a",
y="b",
tooltip=["a", "b"],
title="Made Up Bar Plot",
x_title="Variable A",
sort="x",
)
output = plot.postprocess(simple)
assert sorted(output.keys()) == ["chart", "plot", "type"]
assert output["chart"] == "bar"
config = json.loads(output["plot"])
assert config["encoding"]["x"]["sort"] == "x"
assert config["encoding"]["x"]["field"] == "a"
assert config["encoding"]["x"]["title"] == "Variable A"
assert config["encoding"]["y"]["field"] == "b"
assert config["encoding"]["y"]["title"] == "b"
assert config["title"] == "Made Up Bar Plot"
assert "height" not in config
assert "width" not in config
def test_height_width(self):
plot = gr.BarPlot(x="a", y="b", height=100, width=200)
output = plot.postprocess(simple)
assert sorted(output.keys()) == ["chart", "plot", "type"]
config = json.loads(output["plot"])
assert config["height"] == 100
assert config["width"] == 200
output = gr.BarPlot.update(simple, x="a", y="b", height=100, width=200)
config = json.loads(output["value"]["plot"])
assert config["height"] == 100
assert config["width"] == 200
def test_ylim(self):
plot = gr.BarPlot(x="a", y="b", y_lim=[15, 100])
output = plot.postprocess(simple)
config = json.loads(output["plot"])
assert config["encoding"]["y"]["scale"] == {"domain": [15, 100]}
def test_horizontal(self):
output = gr.BarPlot.update(
simple,
x="a",
y="b",
x_title="Variable A",
y_title="Variable B",
title="Simple Bar Plot with made up data",
tooltip=["a", "b"],
vertical=False,
y_lim=[20, 100],
)
assert output["value"]["chart"] == "bar"
config = json.loads(output["value"]["plot"])
assert config["encoding"]["x"]["field"] == "b"
assert config["encoding"]["x"]["scale"] == {"domain": [20, 100]}
assert config["encoding"]["x"]["title"] == "Variable B"
assert config["encoding"]["y"]["field"] == "a"
assert config["encoding"]["y"]["title"] == "Variable A"
def test_stack_via_color(self):
output = gr.BarPlot.update(
barley,
x="variety",
y="yield",
color="site",
title="Barley Yield Data",
color_legend_title="Site",
color_legend_position="bottom",
)
config = json.loads(output["value"]["plot"])
assert config["encoding"]["color"]["field"] == "site"
assert config["encoding"]["color"]["legend"] == {
"title": "Site",
"orient": "bottom",
}
assert config["encoding"]["color"]["scale"] == {
"domain": [
"University Farm",
"Waseca",
"Morris",
"Crookston",
"Grand Rapids",
"Duluth",
],
"range": [0, 1, 2, 3, 4, 5],
}
def test_group(self):
output = gr.BarPlot.update(
barley,
x="year",
y="yield",
color="year",
group="site",
title="Barley Yield by Year and Site",
group_title="",
tooltip=["yield", "site", "year"],
)
config = json.loads(output["value"]["plot"])
assert config["encoding"]["column"] == {"field": "site", "title": ""}
def test_group_horizontal(self):
output = gr.BarPlot.update(
barley,
x="year",
y="yield",
color="year",
group="site",
title="Barley Yield by Year and Site",
group_title="Site Title",
tooltip=["yield", "site", "year"],
vertical=False,
)
config = json.loads(output["value"]["plot"])
assert config["encoding"]["row"] == {"field": "site", "title": "Site Title"}
def test_barplot_accepts_fn_as_value(self):
plot = gr.BarPlot(
value=lambda: barley.sample(frac=0.1, replace=False),
x="year",
y="yield",
)
assert isinstance(plot.value, dict)
assert isinstance(plot.value["plot"], str)
class TestCode:
def test_component_functions(self):
"""
Preprocess, postprocess, serialize, get_config
"""
code = gr.Code()
assert code.preprocess("# hello friends") == "# hello friends"
assert code.preprocess("def fn(a):\n return a") == "def fn(a):\n return a"
assert (
code.postprocess(
"""
def fn(a):
return a
"""
)
== """def fn(a):
return a"""
)
test_file_dir = Path(Path(__file__).parent, "test_files")
path = str(Path(test_file_dir, "test_label_json.json"))
with open(path) as f:
assert code.postprocess(path) == path
assert code.postprocess((path,)) == f.read()
assert code.serialize("def fn(a):\n return a") == "def fn(a):\n return a"
assert code.deserialize("def fn(a):\n return a") == "def fn(a):\n return a"
assert code.get_config() == {
"value": None,
"language": None,
"lines": 5,
"name": "code",
"show_label": True,
"label": None,
"container": True,
"min_width": 160,
"scale": None,
"elem_id": None,
"elem_classes": None,
"visible": True,
"interactive": None,
"root_url": None,
}
class TestTempFileManagement:
def test_hash_file(self):
temp_file_manager = gr.File()
h1 = temp_file_manager.hash_file("gradio/test_data/cheetah1.jpg")
h2 = temp_file_manager.hash_file("gradio/test_data/cheetah1-copy.jpg")
h3 = temp_file_manager.hash_file("gradio/test_data/cheetah2.jpg")
assert h1 == h2
assert h1 != h3
@patch("shutil.copy2")
def test_make_temp_copy_if_needed(self, mock_copy):
temp_file_manager = gr.File()
f = temp_file_manager.make_temp_copy_if_needed("gradio/test_data/cheetah1.jpg")
try: # Delete if already exists from before this test
os.remove(f)
except OSError:
pass
f = temp_file_manager.make_temp_copy_if_needed("gradio/test_data/cheetah1.jpg")
assert mock_copy.called
assert len(temp_file_manager.temp_files) == 1
assert Path(f).name == "cheetah1.jpg"
f = temp_file_manager.make_temp_copy_if_needed("gradio/test_data/cheetah1.jpg")
assert len(temp_file_manager.temp_files) == 1
f = temp_file_manager.make_temp_copy_if_needed(
"gradio/test_data/cheetah1-copy.jpg"
)
assert len(temp_file_manager.temp_files) == 2
assert Path(f).name == "cheetah1-copy.jpg"
def test_base64_to_temp_file_if_needed(self):
temp_file_manager = gr.File()
base64_file_1 = media_data.BASE64_IMAGE
base64_file_2 = media_data.BASE64_AUDIO["data"]
f = temp_file_manager.base64_to_temp_file_if_needed(base64_file_1)
try: # Delete if already exists from before this test
os.remove(f)
except OSError:
pass
f = temp_file_manager.base64_to_temp_file_if_needed(base64_file_1)
assert len(temp_file_manager.temp_files) == 1
f = temp_file_manager.base64_to_temp_file_if_needed(base64_file_1)
assert len(temp_file_manager.temp_files) == 1
f = temp_file_manager.base64_to_temp_file_if_needed(base64_file_2)
assert len(temp_file_manager.temp_files) == 2
for file in temp_file_manager.temp_files:
os.remove(file)
@pytest.mark.flaky
@patch("shutil.copyfileobj")
def test_download_temp_copy_if_needed(self, mock_copy):
temp_file_manager = gr.File()
url1 = "https://raw.githubusercontent.com/gradio-app/gradio/main/gradio/test_data/test_image.png"
url2 = "https://raw.githubusercontent.com/gradio-app/gradio/main/gradio/test_data/cheetah1.jpg"
f = temp_file_manager.download_temp_copy_if_needed(url1)
try: # Delete if already exists from before this test
os.remove(f)
except OSError:
pass
f = temp_file_manager.download_temp_copy_if_needed(url1)
assert mock_copy.called
assert len(temp_file_manager.temp_files) == 1
f = temp_file_manager.download_temp_copy_if_needed(url1)
assert len(temp_file_manager.temp_files) == 1
f = temp_file_manager.download_temp_copy_if_needed(url2)
assert len(temp_file_manager.temp_files) == 2
def test_type_arg_deperecation_warning():
with pytest.warns(GradioUnusedKwargWarning):
gr.Video(type="filepath")
def test_plot_arg_deprecation_warning():
with pytest.warns(GradioDeprecationWarning):
gr.Image(plot=True)
with pytest.warns(GradioUnusedKwargWarning):
gr.File(plot=True)