Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot use gr.Accordion as output for gr.Checkbox.change #10208

Open
1 task done
acylam opened this issue Dec 16, 2024 · 4 comments
Open
1 task done

Cannot use gr.Accordion as output for gr.Checkbox.change #10208

acylam opened this issue Dec 16, 2024 · 4 comments
Labels
bug Something isn't working

Comments

@acylam
Copy link

acylam commented Dec 16, 2024

Describe the bug

I'm trying to toggle a gr.Accordion's visibility based on a gr.Checkbox selection, but run into this error:

gradio.exceptions.InvalidComponentError: <class 'gradio.layouts.accordion.Accordion'> Component not a valid output component.

This doesn't seem to happen when I set an accordion as an output for other event listeners like gr.Button.click. Does gr.Checkbox.change currently not support gr.Accordion as output?

Have you searched existing issues? 🔎

  • I have searched and found no existing issues

Reproduction

import gradio as gr


def toggle_accordion(
    accordion_toggle: bool,
):
    if accordion_toggle:
        output_accordion = gr.Accordion(visible=True)
    else:
        output_accordion = gr.Accordion(visible=False)

    return [output_accordion]


with gr.Blocks() as demo:
    accordion_toggle = gr.Checkbox(
        value=True,
        label="Accordion toggle",
        show_label=True,
        interactive=True,
        visible=True,
    )

    with gr.Accordion(
        label="this is an accordion", open=True, visible=True
    ) as accordion:
        gr.Markdown("some text")

    accordion_toggle.change(
        fn=toggle_accordion,
        inputs=[accordion_toggle],
        outputs=[accordion],
    )

if __name__ == "__main__":
    demo.launch()

Screenshot

image

Logs

gradio.exceptions.InvalidComponentError: <class 'gradio.layouts.accordion.Accordion'> Component not a valid output component.

System Info

Gradio Environment Information:
------------------------------
Operating System: Linux
gradio version: 5.8.0
gradio_client version: 1.5.1

------------------------------------------------
gradio dependencies in your environment:

aiofiles: 23.2.1
anyio: 3.7.1
audioop-lts is not installed.
fastapi: 0.115.6
ffmpy: 0.3.2
gradio-client==1.5.1 is not installed.
httpx: 0.25.0
huggingface-hub: 0.26.5
jinja2: 3.1.2
markupsafe: 2.1.5
numpy: 1.26.4
orjson: 3.10.1
packaging: 24.0
pandas: 2.2.3
pillow: 10.3.0
pydantic: 2.4.2
pydub: 0.25.1
python-multipart: 0.0.19
pyyaml: 6.0.1
ruff: 0.4.1
safehttpx: 0.1.6
semantic-version: 2.10.0
starlette: 0.41.3
tomlkit: 0.12.0
typer: 0.12.3
typing-extensions: 4.11.0
urllib3: 2.2.1
uvicorn: 0.23.2
authlib; extra == 'oauth' is not installed.
itsdangerous; extra == 'oauth' is not installed.


gradio_client dependencies in your environment:

fsspec: 2024.3.1
httpx: 0.25.0
huggingface-hub: 0.26.5
packaging: 24.0
typing-extensions: 4.11.0
websockets: 11.0.3

Severity

I can work around it

@acylam acylam added the bug Something isn't working label Dec 16, 2024
@abidlabs
Copy link
Member

Hi @acylam I can reproduce the issue, but I can't reproduce the error not happening when I set an accordion as an output for other event listeners like gr.Button.click. For example, this produces the same error:

import gradio as gr


def toggle_accordion(at: bool):
    return gr.Accordion(visible=False)


with gr.Blocks() as demo:
    b = gr.Button()

    with gr.Accordion(
        label="this is an accordion", open=True, visible=True
    ) as accordion:
        gr.Markdown("some text")

    b.click(
        fn=toggle_accordion,
        inputs=[accordion_toggle],
        outputs=[accordion],
    )        

if __name__ == "__main__":
    demo.launch()

Can you share an example where an accordion is working as an output component?

@acylam
Copy link
Author

acylam commented Dec 17, 2024

[accordion_toggle]

Hi @abidlabs , thanks for swift response. Your example gives an error because accordion_toggle is not defined. Here's an example that works:

import gradio as gr


def toggle_accordion():
    return gr.Accordion(visible=False)


with gr.Blocks() as demo:
    b = gr.Button()

    with gr.Accordion(
        label="this is an accordion", open=True, visible=True
    ) as accordion:
        gr.Markdown("some text")

    b.click(
        fn=toggle_accordion,
        inputs=None,
        outputs=[accordion],
    )        

if __name__ == "__main__":
    demo.launch()

@acylam
Copy link
Author

acylam commented Dec 17, 2024

The current work around is to use a button to simulate a checkbox and use a gr.State to track the visibility of the accordion and reverse it, but I'll have to tweak the CSS to change the look of the button and there's one extra variable I have to keep track of.

import gradio as gr


def toggle_accordion(accordion_visibility: bool):
    new_accordion = gr.Accordion(visible=not accordion_visibility)
    return [not accordion_visibility, new_accordion]


with gr.Blocks() as demo:
    b = gr.Button("Toggle Accordion Visibility")

    with gr.Accordion(
        label="this is an accordion", open=True, visible=True
    ) as accordion:
        gr.Markdown("some text")

    accordion_visibility = gr.State(accordion.visible)

    b.click(
        fn=toggle_accordion,
        inputs=[accordion_visibility],
        outputs=[accordion_visibility, accordion],
    )        

if __name__ == "__main__":
    demo.launch()

@acylam
Copy link
Author

acylam commented Dec 18, 2024

Hi @abidlabs, I've been testing some more cases and have narrowed down the issue further.

TLDR; Error occurs when there is only 1 output component returned in a list. Works as expected otherwise.

See example below:

import gradio as gr


def toggle_accordion_2_comps(
    accordion_toggle: bool,
):
    output_accordion = gr.Accordion(visible=accordion_toggle)

    return [True, output_accordion]


def toggle_accordion_1_comp_no_list(
    accordion_toggle: bool,
):
    output_accordion = gr.Accordion(visible=accordion_toggle)

    return output_accordion


def toggle_accordion_1_comp_list(
    accordion_toggle: bool,
):
    output_accordion = gr.Accordion(visible=accordion_toggle)

    return [output_accordion]


with gr.Blocks() as demo:
    accordion_toggle1 = gr.Checkbox(
        value=True,
        label="Accordion toggle (2 output components)",
        show_label=True,
        interactive=True,
        visible=True,
    )

    accordion_toggle2 = gr.Checkbox(
        value=True,
        label="Accordion toggle (1 output component no list)",
        show_label=True,
        interactive=True,
        visible=True,
    )

    accordion_toggle3 = gr.Checkbox(
        value=True,
        label="Accordion toggle  (1 output component with list)",
        show_label=True,
        interactive=True,
        visible=True,
    )

    with gr.Accordion(
        label="this is an accordion", open=True, visible=True
    ) as accordion:
        gr.Markdown("some text")

    dummy_state = gr.State(True)

    accordion_toggle1.change(
        fn=toggle_accordion_2_comps,
        inputs=[accordion_toggle1],
        outputs=[dummy_state, accordion],
    )

    accordion_toggle2.change(
        fn=toggle_accordion_1_comp_no_list,
        inputs=[accordion_toggle2],
        outputs=[accordion],
    )

    accordion_toggle3.change(
        fn=toggle_accordion_1_comp_list,
        inputs=[accordion_toggle3],
        outputs=[accordion],
    )

if __name__ == "__main__":
    demo.launch()

It seems that the crux of the problem is with how you're returning the output components from the event function. As I observed, the error only occurs when the event function returns a list containing a single component (toggle_accordion_1_comp_list), but not with more than 1 returned component (toggle_accordion_2_comps). For a single output component, I have to return the component as-is (toggle_accordion_1_comp_no_list).

Not sure if this is expected behavior, but IMO, all three cases should work, or at least toggle_accordion_1_comp_list and toggle_accordion_2_comps should both work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants