Always set queue=False if every is None for load events (#3391)

* Always set queue=False if every is None

* CHANGELOG + linting

* Move to latest release section

* changelog

---------

Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
This commit is contained in:
Freddy Boulton 2023-03-06 18:27:04 -07:00 committed by GitHub
parent d906dedf97
commit 47d6231680
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 24 additions and 31 deletions

View File

@ -5,25 +5,21 @@
No changes to highlight.
## Bug Fixes:
No changes to highlight.
- Ensure load events created by components (randomize for slider, callable values) are never queued unless every is passed by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3391](https://github.com/gradio-app/gradio/pull/3391)
## Documentation Changes:
No changes to highlight.
- Add Chinese README by [@uanu2002](https://github.com/uanu2002) in [PR 3394](https://github.com/gradio-app/gradio/pull/3394)
## Testing and Infrastructure Changes:
No changes to highlight.
## Breaking Changes:
Add Chinese Readme.md by [@uanu2002](https://github.com/uanu2002) in [PR 3394](https://github.com/gradio-app/gradio/pull/3394)
No changes to highlight.
## Full Changelog:
No changes to highlight.
## Contributors Shoutout:
No changes to highlight.
# 3.20.1

View File

@ -1686,15 +1686,20 @@ class Blocks(BlockContext):
):
load_fn, every = component.load_event_to_attach
# Use set_event_trigger to avoid ambiguity between load class/instance method
self.set_event_trigger(
dep = self.set_event_trigger(
"load",
load_fn,
None,
component,
no_target=True,
queue=False,
# If every is None, for sure skip the queue
# else, let the enable_queue parameter take precedence
# this will raise a nice error message is every is used
# without queue
queue=False if every is None else None,
every=every,
)
component.load_event = dep
def startup_events(self):
"""Events that should be run when the app containing this block starts up."""

View File

@ -31,7 +31,6 @@ from typing_extensions import Literal
from gradio import media_data, processing_utils, utils
from gradio.blocks import Block, BlockContext
from gradio.context import Context
from gradio.documentation import document, set_documentation_group
from gradio.events import (
Blurrable,
@ -177,7 +176,8 @@ class IOComponent(Component, Serializable):
self.show_label = show_label
self.interactive = interactive
self.load_event = None
# load_event is set in the Blocks.attach_load_events method
self.load_event: None | Dict[str, Any] = None
self.load_event_to_attach = None
load_fn, initial_value = self.get_load_fn_and_initial_value(value)
self.value = (
@ -186,7 +186,7 @@ class IOComponent(Component, Serializable):
else self.postprocess(initial_value)
)
if callable(load_fn):
self.load_event = self.attach_load_event(load_fn, every)
self.attach_load_event(load_fn, every)
def get_config(self):
config = {
@ -223,16 +223,7 @@ class IOComponent(Component, Serializable):
def attach_load_event(self, callable: Callable, every: float | None):
"""Add a load event that runs `callable`, optionally every `every` seconds."""
if Context.root_block:
return Context.root_block.load(
callable,
None,
self,
no_target=True,
every=every,
)
else:
self.load_event_to_attach = (callable, every)
self.load_event_to_attach = (callable, every)
def as_example(self, input_data):
"""Return the input data in a way that can be displayed by the examples dataset component in the front-end."""

View File

@ -347,14 +347,14 @@ class TestBlocksMethods:
demo.load(continuous_fn, inputs=None, outputs=[meaning_of_life], every=1)
for i, dependency in enumerate(demo.config["dependencies"]):
if i == 0:
assert dependency["types"] == {"continuous": True, "generator": True}
if i == 1:
assert dependency["types"] == {"continuous": False, "generator": False}
if i == 2:
assert dependency["types"] == {"continuous": False, "generator": True}
if i == 3:
assert dependency["types"] == {"continuous": True, "generator": True}
if i == 0:
assert dependency["types"] == {"continuous": False, "generator": False}
if i == 1:
assert dependency["types"] == {"continuous": False, "generator": True}
if i == 2:
assert dependency["types"] == {"continuous": True, "generator": True}
@pytest.mark.asyncio
async def test_run_without_launching(self):
@ -414,15 +414,16 @@ class TestComponentsInBlocks:
for component in demo.blocks.values():
if isinstance(component, gr.components.IOComponent):
if "Non-random" in component.label:
assert not component.load_event
assert not component.load_event_to_attach
else:
assert component.load_event
assert component.load_event_to_attach
dependencies_on_load = [
dep["trigger"] == "load" for dep in demo.config["dependencies"]
]
assert all(dependencies_on_load)
assert len(dependencies_on_load) == 2
assert not any([dep["queue"] for dep in demo.config["dependencies"]])
# Queue should be explicitly false for these events
assert all([dep["queue"] is False for dep in demo.config["dependencies"]])
def test_io_components_attach_load_events_when_value_is_fn(self, io_components):
io_components = [comp for comp in io_components if comp not in [gr.State]]