Skip to content

Commit

Permalink
Patch fixes (#5678)
Browse files Browse the repository at this point in the history
* Handle lowercase template name frontend

* Lint

* add changeset

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
  • Loading branch information
freddyaboulton and gradio-pr-bot committed Sep 25, 2023
1 parent 0b072d7 commit 6be98da
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 117 deletions.
5 changes: 5 additions & 0 deletions .changeset/dirty-ghosts-tickle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"gradio": minor
---

feat:Patch fixes
220 changes: 112 additions & 108 deletions gradio/cli/commands/components/_create_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import dataclasses
import inspect
import json
Expand All @@ -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()
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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)

Expand All @@ -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
Expand All @@ -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)
)
6 changes: 4 additions & 2 deletions gradio/cli/commands/components/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
5 changes: 0 additions & 5 deletions gradio/cli/commands/components/dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand Down
2 changes: 2 additions & 0 deletions gradio/components/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -74,6 +75,7 @@
"DataFrame",
"Dataset",
"DuplicateButton",
"Fallback",
"Form",
"FormComponent",
"Gallery",
Expand Down
Original file line number Diff line number Diff line change
@@ -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

Expand Down

0 comments on commit 6be98da

Please sign in to comment.