From 6be98dac33626ed48e0da8abf62fa545ed217ae0 Mon Sep 17 00:00:00 2001 From: Freddy Boulton Date: Mon, 25 Sep 2023 11:26:36 -0400 Subject: [PATCH] Patch fixes (#5678) * Handle lowercase template name frontend * Lint * add changeset --------- Co-authored-by: gradio-pr-bot --- .changeset/dirty-ghosts-tickle.md | 5 + .../cli/commands/components/_create_utils.py | 220 +++++++++--------- gradio/cli/commands/components/create.py | 6 +- gradio/cli/commands/components/dev.py | 5 - gradio/components/__init__.py | 2 + .../fallback.py} | 4 +- 6 files changed, 125 insertions(+), 117 deletions(-) create mode 100644 .changeset/dirty-ghosts-tickle.md rename gradio/{cli/commands/components/files/NoTemplateComponent.py => components/fallback.py} (77%) diff --git a/.changeset/dirty-ghosts-tickle.md b/.changeset/dirty-ghosts-tickle.md new file mode 100644 index 000000000000..84898c9d8508 --- /dev/null +++ b/.changeset/dirty-ghosts-tickle.md @@ -0,0 +1,5 @@ +--- +"gradio": minor +--- + +feat:Patch fixes diff --git a/gradio/cli/commands/components/_create_utils.py b/gradio/cli/commands/components/_create_utils.py index c53605b8933e..e9b8cb10e4e1 100644 --- a/gradio/cli/commands/components/_create_utils.py +++ b/gradio/cli/commands/components/_create_utils.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import dataclasses import inspect import json @@ -20,68 +22,6 @@ def _in_test_dir(): return False -def _get_js_dependency_version(name: str, local_js_dir: Path) -> str: - package_json = json.load( - open(str(local_js_dir / name.split("/")[1] / "package.json")) - ) - return package_json["version"] - - -def _modify_js_deps( - package_json: dict, - key: Literal["dependencies", "devDependencies"], - gradio_dir: Path, -): - for dep in package_json.get(key, []): - # if curent working directory is the gradio repo, use the local version of the dependency' - if not _in_test_dir() and dep.startswith("@gradio/"): - package_json[key][dep] = _get_js_dependency_version( - dep, gradio_dir / "_frontend_code" - ) - return package_json - - -def _create_frontend(name: str, template: str, directory: Path): - frontend = directory / "frontend" - frontend.mkdir(exist_ok=True) - - if not template: - template = "fallback" - - p = Path(inspect.getfile(gradio)).parent - - def ignore(s, names): - ignored = [] - for n in names: - if ( - n.startswith("CHANGELOG") - or n.startswith("README.md") - or ".test." in n - or ".stories." in n - or ".spec." in n - ): - ignored.append(n) - return ignored - - shutil.copytree( - str(p / "_frontend_code" / template), - frontend, - dirs_exist_ok=True, - ignore=ignore, - ) - source_package_json = json.load(open(str(frontend / "package.json"))) - source_package_json["name"] = name.lower() - source_package_json = _modify_js_deps(source_package_json, "dependencies", p) - source_package_json = _modify_js_deps(source_package_json, "devDependencies", p) - - json.dump(source_package_json, open(str(frontend / "package.json"), "w"), indent=2) - - -def _replace_old_class_name(old_class_name: str, new_class_name: str, content: str): - pattern = rf"(?<=\b){re.escape(old_class_name)}(?=\b)" - return re.sub(pattern, new_class_name, content) - - default_demo_code = """ example = {name}().example_inputs() @@ -92,14 +32,17 @@ def _replace_old_class_name(old_class_name: str, new_class_name: str, content: s @dataclasses.dataclass -class Override: +class ComponentFiles: + template: str demo_code: str = default_demo_code python_file_name: str = "" + js_dir: str = "" OVERRIDES = { - "JSON": Override(python_file_name="json_component"), - "Row": Override( + "JSON": ComponentFiles(template="JSON", python_file_name="json_component"), + "Row": ComponentFiles( + template="Row", demo_code=textwrap.dedent( """ with gr.Blocks() as demo: @@ -110,7 +53,8 @@ class Override: ), python_file_name="row", ), - "Column": Override( + "Column": ComponentFiles( + template="Column", demo_code=textwrap.dedent( """ with gr.Blocks() as demo: @@ -121,7 +65,8 @@ class Override: ), python_file_name="column", ), - "Tabs": Override( + "Tabs": ComponentFiles( + template="Tabs", demo_code=textwrap.dedent( """ with gr.Blocks() as demo: @@ -134,7 +79,8 @@ class Override: ), python_file_name="tabs", ), - "Group": Override( + "Group": ComponentFiles( + template="Group", demo_code=textwrap.dedent( """ with gr.Blocks() as demo: @@ -145,7 +91,8 @@ class Override: ), python_file_name="group", ), - "Accordion": Override( + "Accordion": ComponentFiles( + template="Accordion", demo_code=textwrap.dedent( """ with gr.Blocks() as demo: @@ -159,11 +106,86 @@ class Override: } -def get_default(template: str): - return Override(python_file_name=f"{template.lower()}.py") +def _get_component_code(template: str | None) -> ComponentFiles: + template = template or "Fallback" + return ComponentFiles( + python_file_name=f"{template.lower()}.py", + js_dir=template.lower(), + template=template, + ) + + +def _get_js_dependency_version(name: str, local_js_dir: Path) -> str: + package_json = json.load( + open(str(local_js_dir / name.split("/")[1] / "package.json")) + ) + return package_json["version"] + + +def _modify_js_deps( + package_json: dict, + key: Literal["dependencies", "devDependencies"], + gradio_dir: Path, +): + for dep in package_json.get(key, []): + # if curent working directory is the gradio repo, use the local version of the dependency' + if not _in_test_dir() and dep.startswith("@gradio/"): + package_json[key][dep] = _get_js_dependency_version( + dep, gradio_dir / "_frontend_code" + ) + return package_json -def _create_backend(name: str, template: str, directory: Path, package_name: str): +def _create_frontend(name: str, component: ComponentFiles, directory: Path): + frontend = directory / "frontend" + frontend.mkdir(exist_ok=True) + + p = Path(inspect.getfile(gradio)).parent + + def ignore(s, names): + ignored = [] + for n in names: + if ( + n.startswith("CHANGELOG") + or n.startswith("README.md") + or ".test." in n + or ".stories." in n + or ".spec." in n + ): + ignored.append(n) + return ignored + + shutil.copytree( + str(p / "_frontend_code" / component.js_dir), + frontend, + dirs_exist_ok=True, + ignore=ignore, + ) + source_package_json = json.load(open(str(frontend / "package.json"))) + source_package_json["name"] = name.lower() + source_package_json = _modify_js_deps(source_package_json, "dependencies", p) + source_package_json = _modify_js_deps(source_package_json, "devDependencies", p) + + json.dump(source_package_json, open(str(frontend / "package.json"), "w"), indent=2) + + +def _replace_old_class_name(old_class_name: str, new_class_name: str, content: str): + pattern = rf"(?<=\b){re.escape(old_class_name)}(?=\b)" + return re.sub(pattern, new_class_name, content) + + +def _create_backend( + name: str, component: ComponentFiles, directory: Path, package_name: str +): + if component.template in gradio.components.__all__: + module = "components" + elif component.template in gradio.layouts.__all__: + module = "layouts" + else: + raise ValueError( + f"Cannot find {component.template} in gradio.components or gradio.layouts" + ) + backend = directory / "backend" / package_name backend.mkdir(exist_ok=True, parents=True) @@ -180,8 +202,6 @@ def _create_backend(name: str, template: str, directory: Path, package_name: str demo_dir = directory / "demo" demo_dir.mkdir(exist_ok=True, parents=True) - component = OVERRIDES[template] if template in OVERRIDES else get_default(template) - (demo_dir / "app.py").write_text( f""" import gradio as gr @@ -203,39 +223,23 @@ def _create_backend(name: str, template: str, directory: Path, package_name: str """ ) - if not template: - backend = backend / f"{name.lower()}.py" - no_template = ( - (Path(__file__).parent / "files" / "NoTemplateComponent.py") - .read_text() - .replace("NAME", name) - ) - backend.write_text(no_template) - else: - p = Path(inspect.getfile(gradio)).parent - python_file = backend / f"{name.lower()}.py" - - if template in gradio.components.__all__: - module = "components" - elif template in gradio.layouts.__all__: - module = "layouts" - else: - raise ValueError( - f"Cannot find {template} in gradio.components or gradio.layouts" - ) - - shutil.copy( - str(p / module / f"{component.python_file_name}.py"), - str(python_file), - ) + p = Path(inspect.getfile(gradio)).parent + python_file = backend / f"{name.lower()}.py" - source_pyi_file = p / module / f"{component.python_file_name}.pyi" - pyi_file = backend / f"{name.lower()}.pyi" - if source_pyi_file.exists(): - shutil.copy(str(source_pyi_file), str(pyi_file)) + shutil.copy( + str(p / module / component.python_file_name), + str(python_file), + ) - content = python_file.read_text() - python_file.write_text(_replace_old_class_name(template, name, content)) - if pyi_file.exists(): - pyi_content = pyi_file.read_text() - pyi_file.write_text(_replace_old_class_name(template, name, pyi_content)) + source_pyi_file = p / module / component.python_file_name.replace(".py", ".pyi") + pyi_file = backend / f"{name.lower()}.pyi" + if source_pyi_file.exists(): + shutil.copy(str(source_pyi_file), str(pyi_file)) + + content = python_file.read_text() + python_file.write_text(_replace_old_class_name(component.template, name, content)) + if pyi_file.exists(): + pyi_content = pyi_file.read_text() + pyi_file.write_text( + _replace_old_class_name(component.template, name, pyi_content) + ) diff --git a/gradio/cli/commands/components/create.py b/gradio/cli/commands/components/create.py index 310c3c712ceb..f792fbab3ea7 100644 --- a/gradio/cli/commands/components/create.py +++ b/gradio/cli/commands/components/create.py @@ -76,10 +76,12 @@ def _create( else: live.update(":page_facing_up: Creating a new component from scratch.") - _create_utils._create_frontend(name.lower(), template, directory=directory) + component = _create_utils._get_component_code(template) + + _create_utils._create_frontend(name.lower(), component, directory=directory) live.update(":art: Created frontend code", add_sleep=0.2) - _create_utils._create_backend(name, template, directory, package_name) + _create_utils._create_backend(name, component, directory, package_name) live.update(":snake: Created backend code", add_sleep=0.2) if install: diff --git a/gradio/cli/commands/components/dev.py b/gradio/cli/commands/components/dev.py index 759820359891..41450514a4e8 100644 --- a/gradio/cli/commands/components/dev.py +++ b/gradio/cli/commands/components/dev.py @@ -27,11 +27,6 @@ def _dev( ] = Path("."), ): component_directory = component_directory.resolve() - if not (component_directory / "pyproject.toml").exists(): - raise ValueError( - f"Cannot find pyproject.toml file in {component_directory}. Make sure " - f"{component_directory} parameter points to a valid python package." - ) print(f":recycle: [green]Launching[/] {app} in reload mode\n") diff --git a/gradio/components/__init__.py b/gradio/components/__init__.py index ee8d3c17d67a..13f537ab2f81 100644 --- a/gradio/components/__init__.py +++ b/gradio/components/__init__.py @@ -23,6 +23,7 @@ from gradio.components.dataset import Dataset from gradio.components.dropdown import Dropdown from gradio.components.duplicate_button import DuplicateButton +from gradio.components.fallback import Fallback from gradio.components.file import File from gradio.components.gallery import Gallery from gradio.components.highlighted_text import HighlightedText @@ -74,6 +75,7 @@ "DataFrame", "Dataset", "DuplicateButton", + "Fallback", "Form", "FormComponent", "Gallery", diff --git a/gradio/cli/commands/components/files/NoTemplateComponent.py b/gradio/components/fallback.py similarity index 77% rename from gradio/cli/commands/components/files/NoTemplateComponent.py rename to gradio/components/fallback.py index 740668962491..2a229e13c400 100644 --- a/gradio/cli/commands/components/files/NoTemplateComponent.py +++ b/gradio/components/fallback.py @@ -1,7 +1,7 @@ -import gradio as gr +from gradio.components.base import Component -class NAME(gr.components.Component): +class Fallback(Component): def preprocess(self, x): return x