From 125a832ab7ee2b5affa574e8b32c88f430cc6663 Mon Sep 17 00:00:00 2001 From: pngwn Date: Wed, 24 Jan 2024 18:12:18 +0000 Subject: [PATCH] generate docs when running `gradio cc build` (#7109) * add docs command to build * add changeset * add changeset * add arg to disable * add changeset * tweaks * tweaks * tweaks * add changeset --------- Co-authored-by: gradio-pr-bot --- .changeset/lazy-things-accept.md | 6 ++ gradio/cli/commands/components/build.py | 36 ++++++- gradio/cli/commands/components/docs.py | 125 ++++++++++++++++-------- js/paramviewer/ParamViewer.svelte | 5 + 4 files changed, 131 insertions(+), 41 deletions(-) create mode 100644 .changeset/lazy-things-accept.md diff --git a/.changeset/lazy-things-accept.md b/.changeset/lazy-things-accept.md new file mode 100644 index 000000000000..8bd031ca4c91 --- /dev/null +++ b/.changeset/lazy-things-accept.md @@ -0,0 +1,6 @@ +--- +"@gradio/paramviewer": minor +"gradio": minor +--- + +feat:generate docs when running `gradio cc build` diff --git a/gradio/cli/commands/components/build.py b/gradio/cli/commands/components/build.py index 990cf75c3dc4..f3e58f12b2bc 100644 --- a/gradio/cli/commands/components/build.py +++ b/gradio/cli/commands/components/build.py @@ -9,6 +9,10 @@ from typing_extensions import Annotated import gradio +from gradio.cli.commands.components._docs_utils import ( + get_deep, +) +from gradio.cli.commands.components.docs import run_command from gradio.cli.commands.display import LivePanelDisplay gradio_template_path = Path(gradio.__file__).parent / "templates" / "frontend" @@ -25,6 +29,9 @@ def _build( bump_version: Annotated[ bool, typer.Option(help="Whether to bump the version number automatically.") ] = False, + generate_docs: Annotated[ + bool, typer.Option(help="Whether to generate the documentation as well.") + ] = True, ): name = Path(path).resolve() if not (name / "pyproject.toml").exists(): @@ -35,7 +42,12 @@ def _build( f":package: Building package in [orange3]{str(name.name)}[/]", add_sleep=0.2 ) pyproject_toml = parse((path / "pyproject.toml").read_text()) - package_name = pyproject_toml["project"]["name"] # type: ignore + package_name = get_deep(pyproject_toml, ["project", "name"]) + + if not isinstance(package_name, str): + raise ValueError( + "Your pyproject.toml file does not have a [project] name field!" + ) try: importlib.import_module(package_name) # type: ignore except ModuleNotFoundError as e: @@ -62,6 +74,28 @@ def _build( "Set [bold][magenta]--bump-version[/][/] to automatically bump the version number." ) + if generate_docs: + _demo_dir = Path("demo").resolve() + _demo_name = "app.py" + _demo_path = _demo_dir / _demo_name + _readme_path = name / "README.md" + + run_command( + live=live, + name=package_name, + suppress_demo_check=False, + pyproject_toml=pyproject_toml, + generate_space=True, + generate_readme=True, + type_mode="simple", + _demo_path=_demo_path, + _demo_dir=_demo_dir, + _readme_path=_readme_path, + space_url=None, + _component_dir=name, + simple=True, + ) + if build_frontend: live.update(":art: Building frontend") component_directory = path.resolve() diff --git a/gradio/cli/commands/components/docs.py b/gradio/cli/commands/components/docs.py index 93b15f8a6190..58e3564c3e44 100644 --- a/gradio/cli/commands/components/docs.py +++ b/gradio/cli/commands/components/docs.py @@ -2,7 +2,7 @@ import importlib from pathlib import Path -from typing import Optional +from typing import Any, Optional import requests import tomlkit as toml @@ -77,69 +77,114 @@ def _docs( with open(_component_dir / "pyproject.toml") as f: data = toml.loads(f.read()) - with open(_demo_path) as f: - demo = f.read() name = get_deep(data, ["project", "name"]) if not isinstance(name, str): raise ValueError("Name not found in pyproject.toml") - pypi_exists = requests.get(f"https://pypi.org/pypi/{name}/json").status_code + run_command( + live=live, + name=name, + suppress_demo_check=suppress_demo_check, + pyproject_toml=data, + generate_space=generate_space, + generate_readme=generate_readme, + type_mode="simple", + _demo_path=_demo_path, + _demo_dir=_demo_dir, + _readme_path=_readme_path, + space_url=space_url, + _component_dir=_component_dir, + ) - pypi_exists = pypi_exists == 200 or False - local_version = get_deep(data, ["project", "version"]) - description = str(get_deep(data, ["project", "description"]) or "") - repo = get_deep(data, ["project", "urls", "repository"]) - space = space_url if space_url else get_deep(data, ["project", "urls", "space"]) +def run_command( + live: LivePanelDisplay, + name: str, + pyproject_toml: dict[str, Any], + suppress_demo_check: bool, + generate_space: bool, + generate_readme: bool, + type_mode: str, + _demo_path: Path, + _demo_dir: Path, + _readme_path: Path, + space_url: str | None, + _component_dir: Path, + simple: bool = False, +): + with open(_demo_path) as f: + demo = f.read() - if not local_version and not pypi_exists: - raise ValueError( - f"Cannot find version in pyproject.toml or on PyPI for [orange3]{name}[/].\nIf you have just published to PyPI, please wait a few minutes and try again." - ) + pypi_exists = requests.get(f"https://pypi.org/pypi/{name}/json").status_code - module = importlib.import_module(name) - (docs, type_mode) = extract_docstrings(module) + pypi_exists = pypi_exists == 200 or False + + local_version = get_deep(pyproject_toml, ["project", "version"]) + description = str(get_deep(pyproject_toml, ["project", "description"]) or "") + repo = get_deep(pyproject_toml, ["project", "urls", "repository"]) + space = ( + space_url + if space_url + else get_deep(pyproject_toml, ["project", "urls", "space"]) + ) + + if not local_version and not pypi_exists: + raise ValueError( + f"Cannot find version in pyproject.toml or on PyPI for [orange3]{name}[/].\nIf you have just published to PyPI, please wait a few minutes and try again." + ) + module = importlib.import_module(name) + (docs, type_mode) = extract_docstrings(module) - if generate_space: + if generate_space: + if not simple: live.update(":computer: [blue]Generating space.[/]") - source = make_space( - docs=docs, - name=name, - description=description, - local_version=local_version - if local_version is None - else str(local_version), - demo=demo, - space=space if space is None else str(space), - repo=repo if repo is None else str(repo), - pypi_exists=pypi_exists, - suppress_demo_check=suppress_demo_check, - ) + source = make_space( + docs=docs, + name=name, + description=description, + local_version=local_version + if local_version is None + else str(local_version), + demo=demo, + space=space if space is None else str(space), + repo=repo if repo is None else str(repo), + pypi_exists=pypi_exists, + suppress_demo_check=suppress_demo_check, + ) - with open(_demo_dir / "space.py", "w") as f: - f.write(source) + with open(_demo_dir / "space.py", "w") as f: + f.write(source) + if not simple: live.update( f":white_check_mark: Space created in [orange3]{_demo_dir}/space.py[/]\n" ) - with open(_demo_dir / "css.css", "w") as f: - f.write(css) + with open(_demo_dir / "css.css", "w") as f: + f.write(css) - if generate_readme: + if generate_readme: + if not simple: live.update(":pencil: [blue]Generating README.[/]") - readme = make_markdown( - docs, name, description, local_version, demo, space, repo, pypi_exists - ) + readme = make_markdown( + docs, name, description, local_version, demo, space, repo, pypi_exists + ) - with open(_readme_path, "w") as f: - f.write(readme) + with open(_readme_path, "w") as f: + f.write(readme) + if not simple: live.update( f":white_check_mark: README generated in [orange3]{_readme_path}[/]" ) + if simple: + short_readme_path = Path(_readme_path).relative_to(_component_dir) + short_demo_path = Path(_demo_dir / "space.py").relative_to(_component_dir) + live.update( + f":white_check_mark: Documention generated in [orange3]{short_demo_path}[/] and [orange3]{short_readme_path}[/]. Pass --no-generate-docs to disable auto documentation." + ) if type_mode == "simple": - print( + live.update( "\n:orange_circle: [red]The docs were generated in simple mode. Updating python to a version greater than 3.9 will result in richer documentation.[/]" ) diff --git a/js/paramviewer/ParamViewer.svelte b/js/paramviewer/ParamViewer.svelte index 71017cb98e3b..a46cce6f6a2d 100644 --- a/js/paramviewer/ParamViewer.svelte +++ b/js/paramviewer/ParamViewer.svelte @@ -69,6 +69,7 @@ @@ -94,6 +95,10 @@ display: inline-block; } + .disbaled { + opacity: 0; + } + .wrap :global(pre), .wrap :global(.highlight) { margin: 0;