Make FileExplorer work on python 3.8 and 3.9. Also make it update on changes to root, glob, or glob_dir (#6550)

* Add code

* add changeset

* add changeset

* Add test

* fix

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
This commit is contained in:
Freddy Boulton 2023-11-28 05:27:45 -05:00 committed by GitHub
parent 9bcb1da189
commit 315659817e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 70 additions and 8 deletions

View File

@ -0,0 +1,6 @@
---
"@gradio/fileexplorer": patch
"gradio": patch
---
fix:Make FileExplorer work on python 3.8 and 3.9. Also make it update on changes to root, glob, or glob_dir

View File

@ -0,0 +1 @@
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: file_explorer_component_events"]}, {"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": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('dir1')\n", "!wget -q -O dir1/bar.txt https://github.com/gradio-app/gradio/raw/main/demo/file_explorer_component_events/dir1/bar.txt\n", "!wget -q -O dir1/foo.txt https://github.com/gradio-app/gradio/raw/main/demo/file_explorer_component_events/dir1/foo.txt\n", "os.mkdir('dir2')\n", "!wget -q -O dir2/baz.png https://github.com/gradio-app/gradio/raw/main/demo/file_explorer_component_events/dir2/baz.png\n", "!wget -q -O dir2/foo.png https://github.com/gradio-app/gradio/raw/main/demo/file_explorer_component_events/dir2/foo.png"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from pathlib import Path\n", "\n", "base_root = Path(__file__).parent.resolve()\n", "\n", "with gr.Blocks() as demo:\n", " dd = gr.Dropdown(label=\"Select File Explorer Root\",\n", " value=str(base_root / \"dir1\"),\n", " choices=[str(base_root / \"dir1\"), str(base_root / \"dir2\")])\n", " fe = gr.FileExplorer(root=str(base_root / \"dir1\"), interactive=True)\n", " dd.select(lambda s: gr.FileExplorer(root=s), inputs=[dd], outputs=[fe])\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}

View File

@ -0,0 +1,15 @@
import gradio as gr
from pathlib import Path
base_root = Path(__file__).parent.resolve()
with gr.Blocks() as demo:
dd = gr.Dropdown(label="Select File Explorer Root",
value=str(base_root / "dir1"),
choices=[str(base_root / "dir1"), str(base_root / "dir2")])
fe = gr.FileExplorer(root=str(base_root / "dir1"), interactive=True)
dd.select(lambda s: gr.FileExplorer(root=s), inputs=[dd], outputs=[fe])
if __name__ == "__main__":
demo.launch()

View File

@ -5,7 +5,6 @@ from __future__ import annotations
import itertools
import os
import re
from glob import glob as glob_func
from pathlib import Path
from typing import Any, Callable, List, Literal
@ -190,16 +189,15 @@ class FileExplorer(Component):
files = []
for result in expand_braces(self.glob):
files += glob_func(result, recursive=True, root_dir=self.root) # type: ignore
files += list(Path(self.root).resolve().glob(result))
ignore_files = []
if self.ignore_glob:
for result in expand_braces(self.ignore_glob):
ignore_files += glob_func(result, recursive=True, root_dir=self.root) # type: ignore
ignore_files += list(Path(self.ignore_glob).resolve().glob(result))
files = list(set(files) - set(ignore_files))
tree = make_tree(files)
tree = make_tree([str(f.relative_to(self.root)) for f in files])
return tree
def _safe_join(self, folders):

View File

@ -0,0 +1,29 @@
import { test } from "@gradio/tootils";
test("File Explorer is interactive and re-runs the server_fn when root is updated", async ({
page
}) => {
await page
.locator("span")
.filter({ hasText: "bar.txt" })
.getByRole("checkbox")
.check();
await page
.locator("span")
.filter({ hasText: "foo.txt" })
.getByRole("checkbox")
.check();
await page.getByLabel("Select File Explorer Root").click();
await page.getByLabel(new RegExp("/dir2$"), { exact: true }).first().click();
await page
.locator("span")
.filter({ hasText: "baz.png" })
.getByRole("checkbox")
.check();
await page
.locator("span")
.filter({ hasText: "foo.png" })
.getByRole("checkbox")
.check();
});

View File

@ -21,6 +21,10 @@
export let height: number | undefined = undefined;
export let file_count: "single" | "multiple" = "multiple";
export let glob: string;
export let ignore_glob: string;
export let root: string;
export let loading_status: LoadingStatus;
export let container = true;
export let scale: number | null = null;
@ -63,6 +67,9 @@
{file_count}
{server}
{interactive}
{root}
{glob}
{ignore_glob}
on:change={() => gradio.dispatch("change")}
/>
</Block>

View File

@ -6,6 +6,9 @@
import { File } from "@gradio/icons";
import { Empty } from "@gradio/atoms";
export let glob: string;
export let ignore_glob: string;
export let root: string;
export let interactive: boolean;
export let server: any;
export let file_count: "single" | "multiple" = "multiple";
@ -17,9 +20,12 @@
}>();
const tree = make_fs_store();
server.ls().then((v: any) => {
tree.create_fs_graph(v);
});
$: glob,
ignore_glob,
root,
server.ls().then((v: any) => {
tree.create_fs_graph(v);
});
$: value.length && $tree && set_checked_from_paths();