From 63caf9e11e77c461a44d955e07d66c2695363708 Mon Sep 17 00:00:00 2001 From: Anentropic Date: Mon, 22 May 2023 13:29:04 +0100 Subject: [PATCH 1/5] return a Dependency instance from Blocks.load event listener --- gradio/blocks.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/gradio/blocks.py b/gradio/blocks.py index 7b35cd846840f..9731fb739ddb6 100644 --- a/gradio/blocks.py +++ b/gradio/blocks.py @@ -1482,7 +1482,9 @@ def get_time(): name=name, src=src, hf_token=api_key, alias=alias, **kwargs ) else: - return self_or_cls.set_event_trigger( + from gradio.events import Dependency + + dep, dep_index = self_or_cls.set_event_trigger( event_name="load", fn=fn, inputs=inputs, @@ -1498,7 +1500,8 @@ def get_time(): max_batch_size=max_batch_size, every=every, no_target=True, - )[0] + ) + return Dependency(self_or_cls, dep, dep_index) def clear(self): """Resets the layout of the Blocks object.""" From 24d80930be41ef456fe694c2c3cd1b3d5f84a197 Mon Sep 17 00:00:00 2001 From: Anentropic Date: Mon, 22 May 2023 14:48:22 +0100 Subject: [PATCH 2/5] a test case for chaining then from load event --- test/test_events.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/test_events.py b/test/test_events.py index 79f8b63b87828..75fd314cf5005 100644 --- a/test/test_events.py +++ b/test/test_events.py @@ -1,8 +1,12 @@ +import os + import pytest from fastapi.testclient import TestClient import gradio as gr +os.environ["GRADIO_ANALYTICS_ENABLED"] = "False" + class TestEvent: def test_clear_event(self): @@ -69,6 +73,25 @@ def clear(): assert not parent.config["dependencies"][2]["trigger_only_on_success"] assert parent.config["dependencies"][3]["trigger_only_on_success"] + def test_load_chaining(self): + calls = 0 + + def increment(): + calls += 1 + return str(calls) + + with gr.Blocks() as demo: + out = gr.Textbox(label="Call counter") + demo.load(increment, inputs=None, outputs=out).then( + increment, inputs=None, outputs=out + ) + + assert demo.config["dependencies"][0]["trigger"] == "load" + assert demo.config["dependencies"][0]["trigger_after"] is None + assert demo.config["dependencies"][1]["trigger"] == "then" + assert demo.config["dependencies"][1]["trigger_after"] == 0 + demo.launch(prevent_thread_lock=True) + class TestEventErrors: def test_event_defined_invalid_scope(self): From 22decbe84479db060532e89bdd7cb857b040d092 Mon Sep 17 00:00:00 2001 From: Anentropic Date: Mon, 22 May 2023 14:51:18 +0100 Subject: [PATCH 3/5] update CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1cb61049dd82..e472419714c22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## New Features: -No changes to highlight. +* Make `Blocks.load` behave like other event listeners (allows chaining `then` off of it) [@anentropic](https://github.com/anentropic/) in [PR 4304](https://github.com/gradio-app/gradio/pull/4304) ## Bug Fixes: From 1551220925207379fb96210779ad245264b4caa8 Mon Sep 17 00:00:00 2001 From: Anentropic Date: Wed, 24 May 2023 15:13:01 +0100 Subject: [PATCH 4/5] add test for load.then with blocks re-used --- test/test_events.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/test/test_events.py b/test/test_events.py index 75fd314cf5005..2c72af136cf67 100644 --- a/test/test_events.py +++ b/test/test_events.py @@ -77,6 +77,7 @@ def test_load_chaining(self): calls = 0 def increment(): + nonlocal calls calls += 1 return str(calls) @@ -90,7 +91,28 @@ def increment(): assert demo.config["dependencies"][0]["trigger_after"] is None assert demo.config["dependencies"][1]["trigger"] == "then" assert demo.config["dependencies"][1]["trigger_after"] == 0 - demo.launch(prevent_thread_lock=True) + + def test_load_chaining_reuse(self): + calls = 0 + + def increment(): + nonlocal calls + calls += 1 + return str(calls) + + with gr.Blocks() as demo: + out = gr.Textbox(label="Call counter") + demo.load(increment, inputs=None, outputs=out).then( + increment, inputs=None, outputs=out + ) + + with gr.Blocks() as demo2: + demo.render() + + assert demo2.config["dependencies"][0]["trigger"] == "load" + assert demo2.config["dependencies"][0]["trigger_after"] is None + assert demo2.config["dependencies"][1]["trigger"] == "then" + assert demo2.config["dependencies"][1]["trigger_after"] == 0 class TestEventErrors: From 1226f4c67e969ae12bcf2061844ec02d0d4169e6 Mon Sep 17 00:00:00 2001 From: Abubakar Abid Date: Mon, 29 May 2023 13:42:26 -0700 Subject: [PATCH 5/5] fixes --- gradio/analytics.py | 5 ++++- gradio/routes.py | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/gradio/analytics.py b/gradio/analytics.py index c1c1a908bbb1e..c4b710aa26687 100644 --- a/gradio/analytics.py +++ b/gradio/analytics.py @@ -114,7 +114,10 @@ def launched_analytics(blocks: gradio.Blocks, data: dict[str, Any]) -> None: for x in blocks.dependencies: targets_telemetry = targets_telemetry + [ - str(blocks.blocks[y]) for y in x["targets"] + # Sometimes the target can be the Blocks object itself, so we need to check if its in blocks.blocks + str(blocks.blocks[y]) + for y in x["targets"] + if y in blocks.blocks ] inputs_telemetry = inputs_telemetry + [ str(blocks.blocks[y]) for y in x["inputs"] diff --git a/gradio/routes.py b/gradio/routes.py index aad4270d16b8d..753c55c7c634b 100644 --- a/gradio/routes.py +++ b/gradio/routes.py @@ -411,7 +411,7 @@ async def run_predict( dependency = app.get_blocks().dependencies[fn_index_inferred] target = dependency["targets"][0] if len(dependency["targets"]) else None event_data = EventData( - app.get_blocks().blocks[target] if target else None, + app.get_blocks().blocks.get(target) if target else None, body.event_data, ) batch = dependency["batch"]