diff --git a/.changeset/silent-pens-decide.md b/.changeset/silent-pens-decide.md new file mode 100644 index 000000000000..7d39aaf4d02c --- /dev/null +++ b/.changeset/silent-pens-decide.md @@ -0,0 +1,6 @@ +--- +"gradio": minor +"website": minor +--- + +feat:Move scripts from old website to CI diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml index d4914ba30f69..1fdc8637872e 100644 --- a/.github/workflows/build-pr.yml +++ b/.github/workflows/build-pr.yml @@ -1,6 +1,9 @@ name: Build PR Artifacts on: + push: + branches: + - main pull_request: branches: - main @@ -35,9 +38,13 @@ jobs: - name: Get PR Number id: get_pr_number run: | - python -c "import os;print(os.environ['GITHUB_REF'].split('/')[2])" > pr_number.txt - echo "PR_NUMBER=$(cat pr_number.txt)" >> $GITHUB_OUTPUT echo "GRADIO_VERSION=$(python -c 'import requests;print(requests.get("https://pypi.org/pypi/gradio/json").json()["info"]["version"])')" >> $GITHUB_OUTPUT + if ${{ github.event_name == 'pull_request' }}; then + python -c "import os;print(os.environ['GITHUB_REF'].split('/')[2])" > pr_number.txt + echo "PR_NUMBER=$(cat pr_number.txt)" >> $GITHUB_OUTPUT + else + echo "PR_NUMBER='main'" >> $GITHUB_OUTPUT + fi - name: Build pr package run: | echo ${{ steps.get_pr_number.outputs.GRADIO_VERSION }} > gradio/version.txt diff --git a/.github/workflows/build-version-docs.yml b/.github/workflows/build-version-docs.yml deleted file mode 100644 index 58c71ecf598b..000000000000 --- a/.github/workflows/build-version-docs.yml +++ /dev/null @@ -1,43 +0,0 @@ -# This workflow will build gradio and create the version's docs file when a new stable version has been released - -name: Create Version's Docs -on: - workflow_dispatch: - pull_request: - types: closed - branches: - - main - paths: - - 'gradio/version.txt' - - -jobs: - check-version: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Install Python - uses: actions/setup-python@v4 - with: - python-version: '3.x' - - name: Install requirements - run: python -m pip install -r website/homepage/requirements.txt - - name: Check new pypi version - run: cd website && python check_version.py - build-docs: - needs: check-version - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Install requirements - run: python -m pip install -r website/homepage/requirements.txt - - name: Pin httpx, httpcore, and h11 - run: pip install h11==0.12.0 httpcore==0.15.0 httpx==0.23.0 - - name: Wait 5 min - run: sleep 300 - - name: Install gradio - run: python -m pip install gradio==$(cat gradio/version.txt) - - name: Build Docs - run: | - export HF_AUTH_TOKEN=${{ secrets.HF_AUTH_TOKEN }} - cd website/homepage && python build-version-docs.py \ No newline at end of file diff --git a/.github/workflows/deploy-pr-to-spaces.yml b/.github/workflows/deploy-pr-to-spaces.yml index 5e1d201f8cff..bd9bac7c7891 100644 --- a/.github/workflows/deploy-pr-to-spaces.yml +++ b/.github/workflows/deploy-pr-to-spaces.yml @@ -14,9 +14,6 @@ jobs: sha: ${{ steps.set-outputs.outputs.gh_sha }} gradio_version: ${{ steps.set-outputs.outputs.gradio_version }} runs-on: ubuntu-latest - if: > - github.event.workflow_run.event == 'pull_request' && - github.event.workflow_run.conclusion == 'success' steps: - uses: actions/checkout@v3 - name: Install Python @@ -51,6 +48,9 @@ jobs: - run: unzip all_demos.zip -d all_demos - run: cp -R all_demos/* demo/all_demos - name: Upload demo to spaces + if: > + github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.conclusion == 'success' id: upload-demo run: | python scripts/upload_demo_to_space.py all_demos \ @@ -58,6 +58,14 @@ jobs: ${{ secrets.SPACES_DEPLOY_TOKEN }} \ --gradio-version ${{ steps.set-outputs.outputs.gradio_version }} > url.txt echo "SPACE_URL=$(cat url.txt)" >> $GITHUB_OUTPUT + - name: Upload website demos + if: > + github.event.workflow_run.event == 'push' && + github.event.workflow_run.conclusion == 'success' + run: | + python scripts/upload_website_demos.py --AUTH_TOKEN ${{ secrets.SPACES_DEPLOY_TOKEN }} \ + --WHEEL_URL https://gradio-builds.s3.amazonaws.com/${{ steps.set-outputs.outputs.gh_sha }}/ \ + comment-spaces-success: uses: "./.github/workflows/comment-queue.yml" needs: [deploy-current-pr] diff --git a/demo/duplicatebutton_component/run.ipynb b/demo/duplicatebutton_component/run.ipynb new file mode 100644 index 000000000000..712304fbee66 --- /dev/null +++ b/demo/duplicatebutton_component/run.ipynb @@ -0,0 +1 @@ +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: duplicatebutton_component"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.DuplicateButton()\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/duplicatebutton_component/run.py b/demo/duplicatebutton_component/run.py new file mode 100644 index 000000000000..f8f314684737 --- /dev/null +++ b/demo/duplicatebutton_component/run.py @@ -0,0 +1,6 @@ +import gradio as gr + +with gr.Blocks() as demo: + gr.DuplicateButton() + +demo.launch() \ No newline at end of file diff --git a/demo/html_component/run.ipynb b/demo/html_component/run.ipynb index 72b8759d00e1..7f7f14697b6a 100644 --- a/demo/html_component/run.ipynb +++ b/demo/html_component/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: html_component"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.HTML(value=\"

Gradio Docs Readers: visitor badge

\")\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: html_component"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.HTML(value=\"

This example was written in HTML

\")\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/html_component/run.py b/demo/html_component/run.py index 3b60e476cf64..c3f533d9c499 100644 --- a/demo/html_component/run.py +++ b/demo/html_component/run.py @@ -1,6 +1,6 @@ import gradio as gr with gr.Blocks() as demo: - gr.HTML(value="

Gradio Docs Readers: visitor badge

") + gr.HTML(value="

This example was written in HTML

") demo.launch() \ No newline at end of file diff --git a/demo/loginbutton_component/requirements.txt b/demo/loginbutton_component/requirements.txt new file mode 100644 index 000000000000..f7359a07d4b7 --- /dev/null +++ b/demo/loginbutton_component/requirements.txt @@ -0,0 +1 @@ +gradio[oauth] \ No newline at end of file diff --git a/demo/loginbutton_component/run.ipynb b/demo/loginbutton_component/run.ipynb new file mode 100644 index 000000000000..54acb9264942 --- /dev/null +++ b/demo/loginbutton_component/run.ipynb @@ -0,0 +1 @@ +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: loginbutton_component"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio gradio[oauth]"]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.LoginButton()\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/loginbutton_component/run.py b/demo/loginbutton_component/run.py new file mode 100644 index 000000000000..51a200c2eddd --- /dev/null +++ b/demo/loginbutton_component/run.py @@ -0,0 +1,6 @@ +import gradio as gr + +with gr.Blocks() as demo: + gr.LoginButton() + +demo.launch() \ No newline at end of file diff --git a/demo/logoutbutton_component/requirements.txt b/demo/logoutbutton_component/requirements.txt new file mode 100644 index 000000000000..f7359a07d4b7 --- /dev/null +++ b/demo/logoutbutton_component/requirements.txt @@ -0,0 +1 @@ +gradio[oauth] \ No newline at end of file diff --git a/demo/logoutbutton_component/run.ipynb b/demo/logoutbutton_component/run.ipynb new file mode 100644 index 000000000000..e42b7e828358 --- /dev/null +++ b/demo/logoutbutton_component/run.ipynb @@ -0,0 +1 @@ +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: logoutbutton_component"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio gradio[oauth]"]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr \n", "\n", "with gr.Blocks() as demo:\n", " gr.LogoutButton()\n", "\n", "demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/logoutbutton_component/run.py b/demo/logoutbutton_component/run.py new file mode 100644 index 000000000000..05e04c6e8d36 --- /dev/null +++ b/demo/logoutbutton_component/run.py @@ -0,0 +1,6 @@ +import gradio as gr + +with gr.Blocks() as demo: + gr.LogoutButton() + +demo.launch() \ No newline at end of file diff --git a/gradio/ipython_ext.py b/gradio/ipython_ext.py index 7d998ce4075a..b6bb8063930f 100644 --- a/gradio/ipython_ext.py +++ b/gradio/ipython_ext.py @@ -42,7 +42,7 @@ def current_cell(self): @property def running_app(self) -> App: assert self.running_demo.server - return self.running_demo.server.running_app + return self.running_demo.server.running_app # type: ignore @property def running_demo(self): diff --git a/gradio/networking.py b/gradio/networking.py index 7b0045139ae9..b216f0191e24 100644 --- a/gradio/networking.py +++ b/gradio/networking.py @@ -43,7 +43,6 @@ class Server(uvicorn.Server): def __init__( self, config: Config, reloader: SourceFileReloader | None = None ) -> None: - assert isinstance(config.app, App) self.running_app = config.app super().__init__(config) self.reloader = reloader diff --git a/guides/08_other-tutorials/how-to-use-3D-model-component.md b/guides/08_other-tutorials/how-to-use-3D-model-component.md index 0c170553ad24..3e14ee763ba2 100644 --- a/guides/08_other-tutorials/how-to-use-3D-model-component.md +++ b/guides/08_other-tutorials/how-to-use-3D-model-component.md @@ -1,6 +1,6 @@ # How to Use the 3D Model Component -Related spaces: https://huggingface.co/spaces/dawood/Model3D, https://huggingface.co/spaces/radames/PIFu-Clothed-Human-Digitization, https://huggingface.co/spaces/radames/dpt-depth-estimation-3d-obj +Related spaces: https://huggingface.co/spaces/gradio/Model3D, https://huggingface.co/spaces/gradio/PIFu-Clothed-Human-Digitization, https://huggingface.co/spaces/gradio/dpt-depth-estimation-3d-obj Tags: VISION, IMAGE ## Introduction @@ -9,7 +9,7 @@ Tags: VISION, IMAGE This guide will show you how to build a demo for your 3D image model in a few lines of code; like the one below. Play around with 3D object by clicking around, dragging and zooming: - + ### Prerequisites @@ -21,24 +21,28 @@ Let's take a look at how to create the minimal interface above. The prediction f ```python import gradio as gr +import os + def load_mesh(mesh_file_name): return mesh_file_name + demo = gr.Interface( fn=load_mesh, inputs=gr.Model3D(), - outputs=gr.Model3D(clear_color=[0.0, 0.0, 0.0, 0.0], label="3D Model"), + outputs=gr.Model3D( + clear_color=[0.0, 0.0, 0.0, 0.0], label="3D Model"), examples=[ - ["files/Bunny.obj"], - ["files/Duck.glb"], - ["files/Fox.gltf"], - ["files/face.obj"], + [os.path.join(os.path.dirname(__file__), "files/Bunny.obj")], + [os.path.join(os.path.dirname(__file__), "files/Duck.glb")], + [os.path.join(os.path.dirname(__file__), "files/Fox.gltf")], + [os.path.join(os.path.dirname(__file__), "files/face.obj")], ], - cache_examples=True, ) -demo.launch() +if __name__ == "__main__": + demo.launch() ``` Let's break down the code above: @@ -55,18 +59,14 @@ Creating the Interface: - `examples`: list of 3D model files. The 3D model component can accept _.obj_, _.glb_, & _.gltf_ file types. - `cache_examples`: saves the predicted output for the examples, to save time on inference. -## Exploring mode complex Model3D Demos: - -Below is a demo that uses the DPT model to predict the depth of an image and then uses 3D Point Cloud to create a 3D object. Take a look at the [app.py](https://huggingface.co/spaces/radames/dpt-depth-estimation-3d-obj/blob/main/app.py) file for a peek into the code and the model prediction function. - - -Below is a demo that uses the PIFu model to convert an image of a clothed human into a 3D digitized model. Take a look at the [spaces.py](https://huggingface.co/spaces/radames/PIFu-Clothed-Human-Digitization/blob/main/PIFu/spaces.py) file for a peek into the code and the model prediction function. +## Exploring a more complex Model3D Demo: - +Below is a demo that uses the DPT model to predict the depth of an image and then uses 3D Point Cloud to create a 3D object. Take a look at the [app.py](https://huggingface.co/spaces/gradio/dpt-depth-estimation-3d-obj/blob/main/app.py) file for a peek into the code and the model prediction function. + --- And you're done! That's all the code you need to build an interface for your Model3D model. Here are some references that you may find useful: - Gradio's ["Getting Started" guide](https://gradio.app/getting_started/) -- The first [3D Model Demo](https://huggingface.co/spaces/dawood/Model3D) and [complete code](https://huggingface.co/spaces/dawood/Model3D/tree/main) (on Hugging Face Spaces) +- The first [3D Model Demo](https://huggingface.co/spaces/gradio/Model3D) and [complete code](https://huggingface.co/spaces/gradio/Model3D/tree/main) (on Hugging Face Spaces) diff --git a/js/_website/src/routes/[[version]]/docs/[doc=valid_doc]/+page.svelte b/js/_website/src/routes/[[version]]/docs/[doc=valid_doc]/+page.svelte index 675707072c61..aeee2c44be47 100644 --- a/js/_website/src/routes/[[version]]/docs/[doc=valid_doc]/+page.svelte +++ b/js/_website/src/routes/[[version]]/docs/[doc=valid_doc]/+page.svelte @@ -165,11 +165,13 @@ {#if mode === "components"}
{#key obj.name} + {#if obj.name !== "State"} + {/if} {/key}
{/if} diff --git a/scripts/upload_website_demos.py b/scripts/upload_website_demos.py new file mode 100644 index 000000000000..2b3b36cd2826 --- /dev/null +++ b/scripts/upload_website_demos.py @@ -0,0 +1,109 @@ +from __future__ import annotations + +import argparse +import os +import pathlib +import shutil +import tempfile +import textwrap +import requests + +import huggingface_hub + +ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) +VERSION_TXT = os.path.abspath(os.path.join(ROOT, "gradio", "version.txt")) +DIR = os.path.dirname(__file__) +GRADIO_DEMO_DIR = os.path.abspath(os.path.join(ROOT, "demo")) + +with open(VERSION_TXT) as f: + gradio_version=f.read() +gradio_version = gradio_version.strip() + +# Reasoning: +# 1. all_demos includes all demos and is for testing PRs +# 2. reset_components includes media files that are only present in all_demos (only for PRs) +# 3. custom_path doesn't have .launch since the point is to show how to launch with uvicorn +# 4. The same reason as 2 for kitchen_sink_random and blocks_kitchen_sink +DEMOS_TO_SKIP = {"all_demos", "clear_components", "custom_path", "kitchen_sink_random", "blocks_kitchen_sink"} + + +def upload_demo_to_space( + demo_name: str, + space_id: str, + hf_token: str, + gradio_version: str | None, + gradio_wheel_url: str | None = None +): + """Upload a demo in the demo directory to a huggingface space. + Parameters: + demo_name: The name of the demo to upload. + space_id: The id of the space to upload the demo to. + hf_token: HF api token. Need to have permission to write to space_id for this to work. + gradio_version: If not None, will set the gradio version in the created Space to the given version. + gradio_wheel_url: If not None, will install the version of gradio using the wheel url in the created Space. + """ + + with tempfile.TemporaryDirectory() as tmpdir: + demo_path = pathlib.Path(GRADIO_DEMO_DIR, demo_name) + shutil.copytree(demo_path, tmpdir, dirs_exist_ok=True) + readme = pathlib.Path(tmpdir, "README.md") + readme_content = f""" + --- + title: {space_id.split("/")[-1]} + emoji: 🔥 + colorFrom: indigo + colorTo: indigo + sdk: gradio + sdk_version: {gradio_version} + app_file: run.py + pinned: false + hf_oauth: true + --- + """ + readme.open("w").write(textwrap.dedent(readme_content)) + + if gradio_wheel_url: + requirements_path = os.path.join(tmpdir, "requirements.txt") + if not os.path.exists(requirements_path): + with open(os.path.join(requirements_path), "w") as f: + f.write(gradio_wheel_url) + else: + with open(os.path.join(requirements_path), "r") as f: + content = f.read() + with open(os.path.join(requirements_path), "w") as f: + f.seek(0, 0) + f.write(gradio_wheel_url + '\n' + content) + + api = huggingface_hub.HfApi() + huggingface_hub.create_repo( + space_id, + space_sdk="gradio", + repo_type="space", + token=hf_token, + exist_ok=True, + ) + api.upload_folder( + token=hf_token, + repo_id=space_id, + repo_type="space", + folder_path=tmpdir, + path_in_repo="", + ) + return f"https://huggingface.co/spaces/{space_id}" + +demos = os.listdir(GRADIO_DEMO_DIR) + +demos = [demo for demo in demos if demo not in DEMOS_TO_SKIP and os.path.isdir(os.path.join(GRADIO_DEMO_DIR, demo)) and os.path.exists(os.path.join(GRADIO_DEMO_DIR, demo, "run.py"))] + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--WHEEL_URL", type=str, help="aws link to gradio wheel") + parser.add_argument("--AUTH_TOKEN", type=str, help="huggingface auth token") + args = parser.parse_args() + gradio_wheel_url = args.WHEEL_URL + f"gradio-{gradio_version}-py3-none-any.whl" + if args.AUTH_TOKEN is not None: + hello_world_version = str(huggingface_hub.space_info("gradio/hello_world").cardData["sdk_version"]) + for demo in demos: + if hello_world_version != gradio_version: + upload_demo_to_space(demo_name=demo, space_id="gradio/" + demo, hf_token=args.AUTH_TOKEN, gradio_version=gradio_version) + upload_demo_to_space(demo_name=demo, space_id="gradio/" + demo + "_main", hf_token=args.AUTH_TOKEN, gradio_version=gradio_version, gradio_wheel_url=gradio_wheel_url)