-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Fix bug with gr.update and interactive=True #2639
Conversation
All the demos for this PR have been deployed at https://huggingface.co/spaces/gradio-pr-deploys/pr-2639-all-demos |
Thanks for the fix @freddyaboulton! I'm trying to understand this part:
Why are passing in a non-None value of |
@abidlabs I thought it was maybe a bit confusing that in the first gif, the "long" version of the textbox is not interactive after you click on the "short" button. If we keep the default value of import gradio as gr
def change_textbox(choice):
if choice == "short":
return gr.Textbox.update(lines=2, visible=True, interactive=False)
elif choice == "long":
return gr.Textbox.update(lines=8, visible=True, interactive=True)
else:
return gr.Textbox.update(visible=False)
with gr.Blocks() as demo:
radio = gr.Radio(
["short", "long", "none"], label="What kind of essay would you like to write?"
)
text = gr.Textbox(lines=2, interactive=True)
gr.Textbox(value="Foo")
radio.change(fn=change_textbox, inputs=radio, outputs=text)
demo.launch() Which I think is ok but I'm worried it will confuse users who are used to thinking of output components as being interactive by default. |
gradio/blocks.py
Outdated
mode = generic_update.get("mode", None) | ||
generic_update.pop("mode", None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mode = generic_update.get("mode", None) | |
generic_update.pop("mode", None) | |
mode = generic_update.pop("mode", None) |
Thanks for the fix @freddyaboulton! I tested and it works. However, I think there is another way to do it which avoids an unnecessary method call. Right now, we have the following chain of methods that are being called:
Although this fixes the problem by extracting the It would be sufficient to add an if condition to def postprocess_update_dict(block: Block, update_dict: Dict, postprocess: bool = True):
"""
Converts a dictionary of updates into a format that can be sent to the frontend.
E.g. {"__type__": "generic_update", "value": "2", "interactive": False}
Into -> {"__type__": "update", "value": 2.0, "mode": "static"}
Parameters:
block: The Block that is being updated with this update dictionary.
update_dict: The original update dictionary
postprocess: Whether to postprocess the "value" key of the update dictionary.
"""
if update_dict.get("__type__", "") == "generic_update":
update_dict = block.get_specific_update(update_dict)
if update_dict.get("value") is components._Keywords.NO_VALUE:
update_dict.pop("value")
update_dict = delete_none(update_dict, skip_value=True)
if "value" in update_dict and postprocess:
update_dict["value"] = block.postprocess(update_dict["value"])
return update_dict |
847f710
to
e4bd361
Compare
@abidlabs Thank you for the very thoughtful review! I followed your suggestion. Should be good for another review now. Was there a reason we were calling the component specific update twice? Was it a way to create a copy of the dict before deleting keys? I wonder if I should also copy the dict in |
No I'm pretty sure I know what happened, basically it was a mistake I made when I was refactoring the code |
@freddyaboulton you can completely revert all changes to the |
93b71e0
to
f77b67c
Compare
@abidlabs Yes, you are right! Reverted the changes to |
Thank you @freddyaboulton for fixing this, looks great! |
f77b67c
to
f689be7
Compare
Description
Fixes #2636
The original bug is fixed by modifying
Block.get_specific_update
to not pass "mode" as a kwarg toupdate
as that's not a user facing argument.In addition, I made it so that the default value of
interactive
inupdate
methods is True. This is because if an update method setsinteractive=False
the user has to explicitly setinteractive=True
again in a separate update call if they want to make the component interactive.For example, in the original repro, if the default value of
interactive
in the textbox update method is None, after clicking onshort
the textbox will never be interactive again. I figured this might be too confusing for users. Wondering what others thoughts are. See the example below:Cant type in "long" after clicking on "short" if the default value of interactive is None
Can type in "long" a
fter clicking on "short" if the default value of interactive is None
Repro code:
Checklist:
A note about the CHANGELOG
Hello 👋 and thank you for contributing to Gradio!
All pull requests must update the change log located in CHANGELOG.md, unless the pull request is labeled with the "no-changelog-update" label.
Please add a brief summary of the change to the Upcoming Release > Full Changelog section of the CHANGELOG.md file and include
a link to the PR (formatted in markdown) and a link to your github profile (if you like). For example, "* Added a cool new feature by
[@myusername](link-to-your-github-profile)
in[PR 11111](https://github.com/gradio-app/gradio/pull/11111)
".If you would like to elaborate on your change further, feel free to include a longer explanation in the other sections.
If you would like an image/gif/video showcasing your feature, it may be best to edit the CHANGELOG file using the
GitHub web UI since that lets you upload files directly via drag-and-drop.