Skip to content

Commit

Permalink
Documents auth in the guides, in the view API page, and also types th…
Browse files Browse the repository at this point in the history
…e Blocks.config object (#8720)

* auth docs

* changes

* add changeset

* add changeset

* add changeset

* type

* changes

* snippets

* import

* add changeset

* changes

* fix typing

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
  • Loading branch information
abidlabs and gradio-pr-bot committed Jul 9, 2024
1 parent 012da05 commit 936c713
Show file tree
Hide file tree
Showing 16 changed files with 127 additions and 24 deletions.
7 changes: 7 additions & 0 deletions .changeset/witty-pugs-beg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@gradio/app": patch
"@gradio/client": patch
"gradio": patch
---

fix:Documents auth in the guides, in the view API page, and also types the Blocks.config object
3 changes: 2 additions & 1 deletion client/js/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export type SpaceStatusCallback = (a: SpaceStatus) => void;
// Configuration and Response Types
// --------------------------------
export interface Config {
auth_required: boolean;
auth_required?: true;
analytics_enabled: boolean;
connect_heartbeat: boolean;
auth_message: string;
Expand Down Expand Up @@ -181,6 +181,7 @@ export interface Config {
protocol: "sse_v3" | "sse_v2.1" | "sse_v2" | "sse_v1" | "sse" | "ws";
max_file_size?: number;
theme_hash?: number;
username: string | null;
}

// todo: DRY up types
Expand Down
3 changes: 2 additions & 1 deletion globals.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ declare global {
}

export interface Config {
auth_required: boolean;
auth_required?: true;
auth_message: string;
components: any[];
css: string | null;
Expand All @@ -41,4 +41,5 @@ export interface Config {
is_space: boolean;
protocol: "ws" | "sse" | "sse_v1" | "sse_v2" | "sse_v2.1" | "sse_v3";
theme_hash?: number;
username: string | null;
}
12 changes: 6 additions & 6 deletions gradio/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
get_render_context,
set_render_context,
)
from gradio.data_classes import FileData, GradioModel, GradioRootModel
from gradio.data_classes import BlocksConfigDict, FileData, GradioModel, GradioRootModel
from gradio.events import (
EventData,
EventListener,
Expand Down Expand Up @@ -1024,7 +1024,7 @@ def __init__(
self.predict = None
self.input_components = None
self.output_components = None
self.__name__ = None
self.__name__ = None # type: ignore
self.api_mode = None

self.progress_tracking = None
Expand Down Expand Up @@ -1082,7 +1082,7 @@ def _is_running_in_reload_thread(self):
@classmethod
def from_config(
cls,
config: dict,
config: BlocksConfigDict,
fns: list[Callable],
proxy_url: str,
) -> Blocks:
Expand Down Expand Up @@ -1978,8 +1978,8 @@ def create_limiter(self):
def get_config(self):
return {"type": "column"}

def get_config_file(self):
config = {
def get_config_file(self) -> BlocksConfigDict:
config: BlocksConfigDict = {
"version": routes.VERSION,
"mode": self.mode,
"app_id": self.app_id,
Expand Down Expand Up @@ -2015,7 +2015,7 @@ def get_config_file(self):
"fill_height": self.fill_height,
"theme_hash": self.theme_hash,
}
config.update(self.default_config.get_config())
config.update(self.default_config.get_config()) # type: ignore
config["connect_heartbeat"] = utils.connect_heartbeat(
config, self.blocks.values()
)
Expand Down
45 changes: 44 additions & 1 deletion gradio/data_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
import shutil
from abc import ABC, abstractmethod
from enum import Enum, auto
from typing import TYPE_CHECKING, Any, List, Optional, Tuple, TypedDict, Union
from typing import TYPE_CHECKING, Any, List, Literal, Optional, Tuple, TypedDict, Union

from fastapi import Request
from gradio_client.utils import traverse
from typing_extensions import NotRequired

from . import wasm_utils

Expand Down Expand Up @@ -288,3 +289,45 @@ def __init__(self, paths: list[str | pathlib.Path]) -> None:
@classmethod
def clear(cls):
cls.all_paths = []


class BodyCSS(TypedDict):
body_background_fill: str
body_text_color: str
body_background_fill_dark: str
body_text_color_dark: str


class Layout(TypedDict):
id: int
children: list[int | Layout]


class BlocksConfigDict(TypedDict):
version: str
mode: str
app_id: int
dev_mode: bool
analytics_enabled: bool
components: list[dict[str, Any]]
css: str | None
connect_heartbeat: bool
js: str | None
head: str | None
title: str
space_id: str | None
enable_queue: bool
show_error: bool
show_api: bool
is_colab: bool
max_file_size: int | None
stylesheets: list[str]
theme: str | None
protocol: Literal["ws", "sse", "sse_v1", "sse_v2", "sse_v2.1", "sse_v3"]
body_css: BodyCSS
fill_height: bool
theme_hash: str
layout: NotRequired[Layout]
dependencies: NotRequired[list[dict[str, Any]]]
root: NotRequired[str | None]
username: NotRequired[str | None]
2 changes: 1 addition & 1 deletion gradio/external.py
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ def from_spaces_blocks(space: str, hf_token: str | None) -> Blocks:
predict_fns.append(endpoint.make_end_to_end_fn(helper))
else:
predict_fns.append(None)
return gradio.Blocks.from_config(client.config, predict_fns, client.src)
return gradio.Blocks.from_config(client.config, predict_fns, client.src) # type: ignore


def from_spaces_interface(
Expand Down
6 changes: 3 additions & 3 deletions gradio/route_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
from starlette.types import ASGIApp, Message, Receive, Scope, Send

from gradio import processing_utils, utils
from gradio.data_classes import PredictBody
from gradio.data_classes import BlocksConfigDict, PredictBody
from gradio.exceptions import Error
from gradio.helpers import EventData
from gradio.state_holder import SessionState
Expand Down Expand Up @@ -640,7 +640,7 @@ def move_uploaded_files_to_cache(files: list[str], destinations: list[str]) -> N
shutil.move(file, dest)


def update_root_in_config(config: dict, root: str) -> dict:
def update_root_in_config(config: BlocksConfigDict, root: str) -> BlocksConfigDict:
"""
Updates the root "key" in the config dictionary to the new root url. If the
root url has changed, all of the urls in the config that correspond to component
Expand All @@ -649,7 +649,7 @@ def update_root_in_config(config: dict, root: str) -> dict:
previous_root = config.get("root")
if previous_root is None or previous_root != root:
config["root"] = root
config = processing_utils.add_root_url(config, root, previous_root)
config = processing_utils.add_root_url(config, root, previous_root) # type: ignore
return config


Expand Down
2 changes: 2 additions & 0 deletions gradio/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ def main(request: fastapi.Request, user: str = Depends(get_current_user)):
if (app.auth is None and app.auth_dependency is None) or user is not None:
config = blocks.config
config = route_utils.update_root_in_config(config, root)
config["username"] = user
elif app.auth_dependency:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="Not authenticated"
Expand Down Expand Up @@ -440,6 +441,7 @@ def get_config(request: fastapi.Request):
request=request, route_path="/config", root_path=app.root_path
)
config = route_utils.update_root_in_config(config, root)
config["username"] = get_current_user(request)
return ORJSONResponse(content=config)

@app.get("/static/{path:path}")
Expand Down
14 changes: 12 additions & 2 deletions gradio/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@

import gradio
from gradio.context import get_blocks_context
from gradio.data_classes import FileData
from gradio.data_classes import BlocksConfigDict, FileData
from gradio.exceptions import Error
from gradio.strings import en

Expand Down Expand Up @@ -1363,11 +1363,21 @@ def _parse_file_size(size: str | int | None) -> int | None:
return multiple * size_int


def connect_heartbeat(config: dict[str, Any], blocks) -> bool:
def connect_heartbeat(config: BlocksConfigDict, blocks) -> bool:
"""
Determines whether a heartbeat is required for a given config.
"""
from gradio.components import State

any_state = any(isinstance(block, State) for block in blocks)
any_unload = False

if "dependencies" not in config:
raise ValueError(
"Dependencies not found in config. Cannot determine whether"
"heartbeat is required."
)

for dep in config["dependencies"]:
for target in dep["targets"]:
if isinstance(target, (list, tuple)) and len(target) == 2:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,20 @@ from gradio_client import Client
client = Client("https://bec81a83-5b5c-471e.gradio.live")
```

## Connecting to a Gradio app with auth

If the Gradio application you are connecting to [requires a username and password](/guides/sharing-your-app#authentication), then provide them as a tuple to the `auth` argument of the `Client` class:

```python
from gradio_client import Client

Client(
space_name,
auth=[username, password]
)
```


## Inspecting the API endpoints

Once you have connected to a Gradio app, you can view the APIs that are available to you by calling the `Client.view_api()` method. For the Whisper Space, we see the following:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,20 @@ import { Client } from "@gradio/client";
const app = Client.connect("https://bec81a83-5b5c-471e.gradio.live");
```

## Connecting to a Gradio app with auth

If the Gradio application you are connecting to [requires a username and password](/guides/sharing-your-app#authentication), then provide them as a tuple to the `auth` argument of the `Client` class:

```js
import { Client } from "@gradio/client";

Client.connect(
space_name,
{ auth: [username, password] }
)
```


## Inspecting the API endpoints

Once you have connected to a Gradio app, you can view the APIs that are available to you by calling the `Client`'s `view_api` method.
Expand Down
2 changes: 2 additions & 0 deletions js/app/src/Blocks.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
export let js: string | null;
export let fill_height = false;
export let ready: boolean;
export let username: string | null;
const {
layout: _layout,
Expand Down Expand Up @@ -678,6 +679,7 @@
{app}
{space_id}
{api_calls}
{username}
/>
</div>
</div>
Expand Down
3 changes: 2 additions & 1 deletion js/app/src/Index.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
declare let BUILD_MODE: string;
interface Config {
auth_required: boolean | undefined;
auth_required?: true;
auth_message: string;
components: ComponentMeta[];
css: string | null;
Expand All @@ -30,6 +30,7 @@
app_id?: string;
fill_height?: boolean;
theme_hash?: number;
username: string | null;
}
let id = -1;
Expand Down
11 changes: 9 additions & 2 deletions js/app/src/api_docs/ApiDocs.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
export let app: Awaited<ReturnType<typeof Client.connect>>;
export let space_id: string | null;
export let root_node: ComponentMeta;
export let username: string | null;
const js_docs =
"https://www.gradio.app/guides/getting-started-with-the-js-client";
const py_docs =
Expand Down Expand Up @@ -142,6 +144,7 @@
{dependencies}
{root}
short_root={space_id || root}
{username}
/>
<p>
Note: Some API calls only affect the UI, so when using the
Expand Down Expand Up @@ -195,7 +198,7 @@
<p class="self-baseline">API Recorder</p>
</Button>
to automatically generate your API requests.
{#if current_language == "bash"}<br />&nbsp;<br />Note: making a
{#if current_language == "bash"}<br />&nbsp;<br />Making a
prediction and getting a result requires
<strong>2 requests</strong>: a
<code>POST</code>
Expand All @@ -204,7 +207,10 @@
<code>GET</code> request to fetch the results. In these snippets,
we've used <code>awk</code> and <code>read</code> to parse the
results, combining these two requests into one command for ease of
use. See <a href={bash_docs} target="_blank">curl docs</a>.
use. {#if username !== null}
Note: connecting to an authenticated app requires an additional
request.{/if} See
<a href={bash_docs} target="_blank">curl docs</a>.
{/if}

<!-- <span
Expand All @@ -228,6 +234,7 @@
{current_language}
{root}
{space_id}
{username}
/>

<ParametersSnippet
Expand Down
6 changes: 3 additions & 3 deletions js/app/src/api_docs/CodeSnippet.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
export let space_id: string | null;
export let endpoint_parameters: any;
export let named: boolean;
export let username: string | null;
export let current_language: "python" | "javascript" | "bash";
let python_code: HTMLElement;
Expand Down Expand Up @@ -54,7 +54,7 @@
class="highlight">import</span
> Client{#if has_file_path}, handle_file{/if}

client = Client(<span class="token string">"{space_id || root}"</span>)
client = Client(<span class="token string">"{space_id || root}"</span>{#if username !== null}, auth=("{username}", **password**){/if})
result = client.<span class="highlight">predict</span
>(<!--
-->{#each endpoint_parameters as { python_type, example_input, parameter_name, parameter_has_default, parameter_default }, i}<!--
Expand Down Expand Up @@ -93,7 +93,7 @@ const example{component} = await response_{i}.blob();
-->
const client = await Client.connect(<span class="token string"
>"{space_id || root}"</span
>);
>{#if username !== null}, &lbrace;auth: ["{username}", **password**]&rbrace;{/if});
const result = await client.predict({#if named}<span class="api-name"
>"/{dependency.api_name}"</span
>{:else}{dependency_index}{/if}, &lbrace; <!--
Expand Down
Loading

0 comments on commit 936c713

Please sign in to comment.