Show view api button even if there are no named api routes in the app (#2250)

* Show message when no named api routes

* Lint

* Change text slightly

* Add show_api to launch method + fix text

* Undo changes to demos

* Change url example
This commit is contained in:
Freddy Boulton 2022-09-15 10:11:31 -05:00 committed by GitHub
parent f43481c18a
commit f346118133
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 130 additions and 94 deletions

View File

@ -14,7 +14,7 @@ demo = gr.Interface(fn=reverse_audio,
inputs="microphone",
outputs="audio",
examples=[
"https://file-examples.com/storage/fe6d784fb46320d949c245e/2017/11/file_example_MP3_700KB.mp3",
"https://samplelib.com/lib/preview/mp3/sample-3s.mp3",
os.path.join(os.path.dirname(__file__), "audio/recording1.wav")
], cache_examples=True)

View File

@ -413,6 +413,7 @@ class Blocks(BlockContext):
self.app_id = random.getrandbits(64)
self.temp_dirs = set()
self.title = title
self.show_api = True
data = {
"mode": self.mode,
@ -785,6 +786,7 @@ class Blocks(BlockContext):
"is_space": self.is_space,
"enable_queue": getattr(self, "enable_queue", False), # launch attributes
"show_error": getattr(self, "show_error", False),
"show_api": self.show_api,
}
def getLayout(block):
@ -946,6 +948,7 @@ class Blocks(BlockContext):
ssl_certfile: Optional[str] = None,
ssl_keyfile_password: Optional[str] = None,
quiet: bool = False,
show_api: bool = True,
_frontend: bool = True,
) -> Tuple[FastAPI, str, str]:
"""
@ -974,6 +977,7 @@ class Blocks(BlockContext):
ssl_certfile: If a path to a file is provided, will use this as the signed certificate for https. Needs to be provided if ssl_keyfile is provided.
ssl_keyfile_password: If a password is provided, will use this with the ssl certificate for https.
quiet: If True, suppresses most print statements.
show_api: If True, shows the api docs in the footer of the app. Default True.
Returns:
app: FastAPI app object that is running the demo
local_url: Locally accessible link to the demo
@ -1000,6 +1004,7 @@ class Blocks(BlockContext):
self.height = height
self.width = width
self.favicon_path = favicon_path
self.show_api = show_api
if enable_queue is not None:
self.enable_queue = enable_queue
warnings.warn(

View File

@ -108,6 +108,9 @@ class TestBlocks(unittest.TestCase):
config = demo.get_config_file()
self.assertTrue(assert_configs_are_equivalent_besides_ids(XRAY_CONFIG, config))
assert config["show_api"] is True
_ = demo.launch(prevent_thread_lock=True, show_api=False)
assert demo.config["show_api"] is False
def test_load_from_config(self):
def update(name):

View File

@ -16,99 +16,126 @@
</script>
<div>
<h2 class="text-3xl text-center mb-6">
API Docs for
<span class="italic text-amber-500">
{root}
</span>
</h2>
<div class="flex flex-col gap-6">
{#each dependencies as dependency, d}
{#if dependency.documentation}
<div
class="bg-gray-50 border border-gray-100 dark:bg-gray-800 dark:border-gray-700 p-6 rounded"
>
<h3 class="text-3xl text-amber-500 font-semibold mb-2">
POST /api/{dependency.api_name}
</h3>
<div class="mb-6">
Full URL: <span class="underline"
>{root}api/{dependency.api_name}</span
>
<button
class="ml-1 px-2 py-0.5 rounded bg-gray-200 dark:bg-gray-700"
on:click={() => {
navigator.clipboard.writeText(
root + "api/" + dependency.api_name
);
just_copied = d;
setTimeout(() => {
just_copied = -1;
}, 500);
}}
>
{#if just_copied === d}copied!{:else}copy{/if}
</button>
</div>
<h4 class="text-2xl mt-6 mb-4">Input Payload</h4>
{#if dependencies.some((d) => "documentation" in d)}
<h2 class="text-3xl text-center mb-6">
API Docs for
<span class="italic text-amber-500">
{root}
</span>
</h2>
<div class="flex flex-col gap-6">
{#each dependencies as dependency, d}
{#if dependency.documentation}
<div
class="block mb-4 text-lg bg-gray-100 dark:bg-gray-700 p-4 font-mono"
class="bg-gray-50 border border-gray-100 dark:bg-gray-800 dark:border-gray-700 p-6 rounded"
>
&#123;<br />
&nbsp;&nbsp;"data": [<br />
{#each dependency.documentation[0] as dependency_doc, i}
&nbsp;&nbsp;&nbsp;&nbsp;{dependency_doc[1]},
<span class="text-pink-400 dark:text-pink-600"
>// represents {dependency_doc[0]} of
{((label) => {
return label ? "'" + label + "'" : "the";
})(
components.filter((c) => c.id === dependency.inputs[i])[0]
.props.label
)}
<h3 class="text-3xl text-amber-500 font-semibold mb-2">
POST /api/{dependency.api_name}
</h3>
<div class="mb-6">
Full URL: <span class="underline"
>{root}api/{dependency.api_name}</span
>
<button
class="ml-1 px-2 py-0.5 rounded bg-gray-200 dark:bg-gray-700"
on:click={() => {
navigator.clipboard.writeText(
root + "api/" + dependency.api_name
);
just_copied = d;
setTimeout(() => {
just_copied = -1;
}, 500);
}}
>
{#if just_copied === d}copied!{:else}copy{/if}
</button>
</div>
<h4 class="text-2xl mt-6 mb-4">Input Payload</h4>
<div
class="block mb-4 text-lg bg-gray-100 dark:bg-gray-700 p-4 font-mono"
>
&#123;<br />
&nbsp;&nbsp;"data": [<br />
{#each dependency.documentation[0] as dependency_doc, i}
&nbsp;&nbsp;&nbsp;&nbsp;{dependency_doc[1]},
<span class="text-pink-400 dark:text-pink-600"
>// represents {dependency_doc[0]} of
{((label) => {
return label ? "'" + label + "'" : "the";
})(
components.filter((c) => c.id === dependency.inputs[i])[0]
.props.label
)}
<span class="capitalize"
>{components.filter((c) => c.id === dependency.inputs[i])[0]
.props.name}</span
> component
</span>
<br />
{/each}
&nbsp;&nbsp;]<br />
&#125;
<span class="capitalize"
>{components.filter((c) => c.id === dependency.inputs[i])[0]
.props.name}</span
> component
</span>
<br />
{/each}
&nbsp;&nbsp;]<br />
&#125;
</div>
<h4 class="text-2xl mt-6 mb-4">Response Object</h4>
<div
class="block mb-4 text-lg bg-gray-100 dark:bg-gray-700 p-4 font-mono"
>
&#123;<br />
&nbsp;&nbsp;"data": [<br />
{#each dependency.documentation[1] as dependency_doc, i}
&nbsp;&nbsp;&nbsp;&nbsp;{dependency_doc[1]},
<span class="text-pink-400 dark:text-pink-600"
>// represents {dependency_doc[0]} of
{((label) => {
return label ? "'" + label + "'" : "the";
})(
components.filter((c) => c.id === dependency.outputs[i])[0]
.props.label
)}
<span class="capitalize"
>{components.filter(
(c) => c.id === dependency.outputs[i]
)[0].props.name}</span
> component
</span>
<br />
{/each}
&nbsp;&nbsp;],<br />
&nbsp;&nbsp;"duration": (float)
<span class="text-pink-400 dark:text-pink-600">
// number of seconds to run function call</span
><br />
&#125;
</div>
</div>
<h4 class="text-2xl mt-6 mb-4">Response Object</h4>
<div
class="block mb-4 text-lg bg-gray-100 dark:bg-gray-700 p-4 font-mono"
>
&#123;<br />
&nbsp;&nbsp;"data": [<br />
{#each dependency.documentation[1] as dependency_doc, i}
&nbsp;&nbsp;&nbsp;&nbsp;{dependency_doc[1]},
<span class="text-pink-400 dark:text-pink-600"
>// represents {dependency_doc[0]} of
{((label) => {
return label ? "'" + label + "'" : "the";
})(
components.filter((c) => c.id === dependency.outputs[i])[0]
.props.label
)}
<span class="capitalize"
>{components.filter((c) => c.id === dependency.outputs[i])[0]
.props.name}</span
> component
</span>
<br />
{/each}
&nbsp;&nbsp;],<br />
&nbsp;&nbsp;"duration": (float)
<span class="text-pink-400 dark:text-pink-600">
// number of seconds to run function call</span
><br />
&#125;
</div>
</div>
{/if}
{/each}
</div>
{/if}
{/each}
</div>
{:else}
<h2 class="text-3xl text-center mb-6">
There are no named API Routes for
<span class="italic text-amber-500">
{root}
</span>
</h2>
<div>
To expose an API endpoint of your app in these API docs, set the <span
class="italic text-amber-500"
>
api_name
</span>
parameter of the event listener. For more information, see the "API Page"
<a
href="https://gradio.app/sharing_your_app/#api-page"
class="text-amber-500"
>
section</a
>
in the guides. To hide this API page, set
<span class="italic text-amber-500"> show_api=False </span>
in the <span class="italic text-amber-500"> Blocks.launch()</span> method.
</div>
{/if}
</div>

View File

@ -35,6 +35,7 @@
export let target: HTMLElement;
export let id: number = 0;
export let autoscroll: boolean = false;
export let show_api: boolean = true;
let app_mode = window.__gradio_mode__ === "app";
let loading_status = create_loading_status_store();
@ -66,7 +67,6 @@
}
}
});
let show_api_docs = dependencies.some((d) => "documentation" in d);
let api_docs_visible = false;
function is_dep(
@ -456,7 +456,7 @@
<footer
class="flex justify-center pb-6 text-gray-300 dark:text-gray-500 font-semibold"
>
{#if show_api_docs}
{#if show_api}
<div
class="cursor-pointer hover:text-gray-400 dark:hover:text-gray-400 transition-colors"
on:click={() => {

View File

@ -34,6 +34,7 @@ interface Config {
title: string;
version: string;
is_space: boolean;
show_api: boolean;
// allow_flagging: string;
// allow_interpretation: boolean;
// article: string;