Skip to content

Commit

Permalink
Push to spaces (#4033)
Browse files Browse the repository at this point in the history
* changes

* first commit

* Update gradio/upload.py

Co-authored-by: Aarni Koskela <[email protected]>

* Update gradio/upload.py

Co-authored-by: Aarni Koskela <[email protected]>

* changes

* changes

* changes

* changes

* changes

* changes

* changes

* chnages

* changes

* changes

* changes

* changes

* Update 03_sharing-your-app.md

* changes

* changes

* change

* changes

* changes

* changes

* Update gradio/deploy_space.py

Co-authored-by: Abubakar Abid <[email protected]>

* changes

* changes

* changes

---------

Co-authored-by: Aarni Koskela <[email protected]>
Co-authored-by: Abubakar Abid <[email protected]>
  • Loading branch information
3 people authored May 31, 2023
1 parent 7781665 commit 114f4b4
Show file tree
Hide file tree
Showing 12 changed files with 1,710 additions and 1,865 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## New Features:

- Introduced `gradio deploy` to launch a Gradio app to Spaces directly from your terminal. By [@aliabid94](https://github.com/aliabid94) in [PR 4033](https://github.com/gradio-app/gradio/pull/4033).


## Bug Fixes:

Expand Down Expand Up @@ -53,7 +55,6 @@ No changes to highlight.
- Add JS client code snippets to use via api page by [@aliabd](https://github.com/aliabd) in [PR 3927](https://github.com/gradio-app/gradio/pull/3927).
- Update to the JS client by [@pngwn](https://github.com/pngwn) in [PR 4202](https://github.com/gradio-app/gradio/pull/4202)


## Bug Fixes:

- Fix "TypeError: issubclass() arg 1 must be a class" When use Optional[Types] by [@lingfengchencn](https://github.com/lingfengchencn) in [PR 4200](https://github.com/gradio-app/gradio/pull/4200).
Expand Down
1 change: 1 addition & 0 deletions gradio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
Video,
component,
)
from gradio.deploy_space import deploy
from gradio.events import SelectData
from gradio.exceptions import Error
from gradio.external import load
Expand Down
14 changes: 14 additions & 0 deletions gradio/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import sys

import gradio.deploy_space
import gradio.reload


def cli():
args = sys.argv[1:]
if len(args) == 0:
raise ValueError("No file specified.")
if args[0] == "deploy":
gradio.deploy_space.deploy()
else:
gradio.reload.main()
175 changes: 175 additions & 0 deletions gradio/deploy_space.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
from __future__ import annotations

import argparse
import os
import re

import huggingface_hub

import gradio as gr

repo_directory = os.getcwd()
readme_file = os.path.join(repo_directory, "README.md")
github_action_template = os.path.join(
os.path.dirname(__file__), "deploy_space_action.yaml"
)


def add_configuration_to_readme(
title: str | None,
app_file: str | None,
) -> dict:
configuration = {}

dir_name = os.path.basename(repo_directory)
if title is None:
title = input(f"Enter Spaces app title [{dir_name}]: ") or dir_name
formatted_title = format_title(title)
if formatted_title != title:
print(f"Formatted to {formatted_title}. ")
configuration["title"] = formatted_title

if app_file is None:
for file in os.listdir(repo_directory):
file_path = os.path.join(repo_directory, file)
if not os.path.isfile(file_path) or not file.endswith(".py"):
continue

with open(file_path, encoding="utf-8", errors="ignore") as f:
content = f.read()
if "import gradio" in content:
app_file = file
break

app_file = (
input(f"Enter Gradio app file {f'[{app_file}]' if app_file else ''}: ")
or app_file
)
if not app_file or not os.path.exists(app_file):
raise FileNotFoundError("Failed to find Gradio app file.")
configuration["app_file"] = app_file

configuration["sdk"] = "gradio"
configuration["sdk_version"] = gr.__version__
huggingface_hub.metadata_save(readme_file, configuration)

configuration["hardware"] = (
input(
f"Enter Spaces hardware ({', '.join(hardware.value for hardware in huggingface_hub.SpaceHardware)}) [cpu-basic]: "
)
or "cpu-basic"
)

secrets = {}
if input("Any Spaces secrets (y/n) [n]: ") == "y":
while True:
secret_name = input("Enter secret name (leave blank to end): ")
if not secret_name:
break
secret_value = input(f"Enter secret value for {secret_name}: ")
secrets[secret_name] = secret_value
configuration["secrets"] = secrets

requirements_file = os.path.join(repo_directory, "requirements.txt")
if (
not os.path.exists(requirements_file)
and input("Create requirements.txt file? (y/n) [n]: ").lower() == "y"
):
while True:
requirement = input("Enter a dependency (leave blank to end): ")
if not requirement:
break
with open(requirements_file, "a") as f:
f.write(requirement + "\n")

if (
input(
"Create Github Action to automatically update Space on 'git push'? [n]: "
).lower()
== "y"
):
track_branch = input("Enter branch to track [main]: ") or "main"
github_action_file = os.path.join(
repo_directory, ".github/workflows/update_space.yml"
)
os.makedirs(os.path.dirname(github_action_file), exist_ok=True)
with open(github_action_template) as f:
github_action_content = f.read()
github_action_content = github_action_content.replace("$branch", track_branch)
with open(github_action_file, "w") as f:
f.write(github_action_content)

print(
"Github Action created. Add your Hugging Face write token (from https://huggingface.co/settings/tokens) as an Actions Secret named 'hf_token' to your GitHub repository. This can be set in your repository's settings page."
)

return configuration


def format_title(title: str):
title = title.replace(" ", "_")
title = re.sub(r"[^a-zA-Z0-9\-._]", "", title)
title = re.sub("-+", "-", title)
while title.startswith("."):
title = title[1:]
return title


def deploy():
if (
os.getenv("SYSTEM") == "spaces"
): # in case a repo with this function is uploaded to spaces
return
parser = argparse.ArgumentParser(description="Deploy to Spaces")
parser.add_argument("deploy")
parser.add_argument("--title", type=str, help="Spaces app title")
parser.add_argument("--app-file", type=str, help="File containing the Gradio app")

args = parser.parse_args()

hf_api = huggingface_hub.HfApi()
whoami = None
login = False
try:
whoami = hf_api.whoami()
if whoami["auth"]["accessToken"]["role"] != "write":
login = True
except OSError:
login = True
if login:
print("Need 'write' access token to create a Spaces repo.")
huggingface_hub.login(add_to_git_credential=False)
whoami = hf_api.whoami()

configuration: None | dict = None
if os.path.exists(readme_file):
try:
configuration = huggingface_hub.metadata_load(readme_file)
except ValueError:
pass

if configuration is None:
print(
f"Creating new Spaces Repo in '{repo_directory}'. Collecting metadata, press Enter to accept default value."
)
configuration = add_configuration_to_readme(
args.title,
args.app_file,
)

space_id = huggingface_hub.create_repo(
configuration["title"],
space_sdk="gradio",
repo_type="space",
exist_ok=True,
space_hardware=configuration.get("hardware"),
).repo_id
hf_api.upload_folder(
repo_id=space_id,
repo_type="space",
folder_path=repo_directory,
)
if configuration.get("secrets"):
for secret_name, secret_value in configuration["secrets"].items():
huggingface_hub.add_space_secret(space_id, secret_name, secret_value)
print(f"Space available at https://huggingface.co/spaces/{space_id}")
28 changes: 28 additions & 0 deletions gradio/deploy_space_action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Run Python script

on:
push:
branches:
- $branch

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v2

- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'

- name: Install Gradio
run: python -m pip install gradio

- name: Log in to Hugging Face
run: python -c 'import huggingface_hub; huggingface_hub.login(token="${{ secrets.hf_token }}")'

- name: Deploy to Spaces
run: gradio deploy
2 changes: 1 addition & 1 deletion gradio/strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"To turn off, set debug=False in launch().",
"COLAB_DEBUG_FALSE": "Colab notebook detected. To show errors in colab notebook, set debug=True in launch()",
"COLAB_WARNING": "Note: opening Chrome Inspector may crash demo inside Colab notebooks.",
"SHARE_LINK_MESSAGE": "\nThis share link expires in 72 hours. For free permanent hosting and GPU upgrades (NEW!), check out Spaces: https://huggingface.co/spaces",
"SHARE_LINK_MESSAGE": "\nThis share link expires in 72 hours. For free permanent hosting and GPU upgrades, run `gradio deploy` from Terminal to deploy to Spaces (https://huggingface.co/spaces)",
"INLINE_DISPLAY_BELOW": "Interface loading below...",
"TIPS": [
"You can add authentication to your app with the `auth=` kwarg in the `launch()` command; for example: `gr.Interface(...).launch(auth=('username', 'password'))`",
Expand Down
5 changes: 4 additions & 1 deletion guides/01_getting-started/03_sharing-your-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ Share links expire after 72 hours.

If you'd like to have a permanent link to your Gradio demo on the internet, use Hugging Face Spaces. [Hugging Face Spaces](http://huggingface.co/spaces/) provides the infrastructure to permanently host your machine learning model for free!

You can either drag and drop a folder containing your Gradio model and all related files, or you can point Spaces to your Git repository and Spaces will pull the Gradio app from there. See [this guide how to host on Hugging Face Spaces](https://huggingface.co/blog/gradio-spaces) for more information.
After you have [created a free Hugging Face account](https://huggingface.co/join), you have three methods to deploy your Gradio app to Hugging Face Spaces:
1. From terminal: run `gradio deploy` in your app directory. The CLI will gather some basic metadata and then launch your app. To update your space, you can re-run this command or enable the Github Actions option to automatically update the Spaces on `git push`.
2. From your browser: Drag and drop a folder containing your Gradio model and all related files [here](https://huggingface.co/new-space).
3. Connect Spaces with your Git repository and Spaces will pull the Gradio app from there. See [this guide how to host on Hugging Face Spaces](https://huggingface.co/blog/gradio-spaces) for more information.

<video autoplay muted loop>
<source src="/assets/guides/hf_demo.mp4" type="video/mp4" />
Expand Down
Loading

0 comments on commit 114f4b4

Please sign in to comment.