Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

generate docs when running gradio cc build #7109

Merged
merged 9 commits into from Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/lazy-things-accept.md
@@ -0,0 +1,5 @@
---
"gradio": minor
---

feat:generate docs when running `gradio cc build`
36 changes: 35 additions & 1 deletion gradio/cli/commands/components/build.py
Expand Up @@ -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"
Expand All @@ -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():
Expand All @@ -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:
Expand All @@ -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()
Expand Down
125 changes: 85 additions & 40 deletions gradio/cli/commands/components/docs.py
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The warning about python 3.9 needs to be printed with live otherwise it's out of order:

image

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would maybe skip the "Generating documentation" and just print the "Documentation generated..." but something like

Documentation generated in demo/app.py and README.md. Pass `--no-generate-docs` to disable auto documentation

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kinda wanted it to be not in the live panel because there isn't actually an issue with the doc gen, just a note. But I can put it at the bottom with some space.

Will update the message.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! My bad, I think we should remove the backticks around --no-generate-docs since they don't change. how it renders

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_path).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."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be space.py not demo.py no?

image

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed!

)

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.[/]"
)