Repository: gradio-app/gradio

Issue:
`gr.Update` doesn't work for the `interactive` property 
### Describe the bug

I would like to programatically swap whether a field is interactive or not depending on other things that happen in my application, however the `interactive` property seem not to be working with the `gr.Update` function

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Reproduction

By taking the demo in the docs page and just adding an `interactive=False` to the first choice:
```py
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)
    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)

    radio.change(fn=change_textbox, inputs=radio, outputs=text)

if __name__ == "__main__":
    demo.launch()
```

I get the following error
```
raceback (most recent call last):
  File "/home/poli/miniconda3/envs/multimodal/lib/python3.9/site-packages/gradio/routes.py", line 289, in run_predict
    output = await app.blocks.process_api(
  File "/home/poli/miniconda3/envs/multimodal/lib/python3.9/site-packages/gradio/blocks.py", line 983, in process_api
    data = self.postprocess_data(fn_index, result["prediction"], state)
  File "/home/poli/miniconda3/envs/multimodal/lib/python3.9/site-packages/gradio/blocks.py", line 924, in postprocess_data
    prediction_value = postprocess_update_dict(
  File "/home/poli/miniconda3/envs/multimodal/lib/python3.9/site-packages/gradio/blocks.py", line 424, in postprocess_update_dict
    prediction_value = block.get_specific_update(update_dict)
  File "/home/poli/miniconda3/envs/multimodal/lib/python3.9/site-packages/gradio/blocks.py", line 265, in get_specific_update
    generic_update = cls.update(**generic_update)
TypeError: update() got an unexpected keyword argument 'mode'
```

### Screenshot

_No response_

### Logs

```shell
-
```


### System Info

```shell
Gradio == 3.9.1
```


### Severity

serious, but I can work around it


Discussion:

Resolving patch:
diff --git a/gradio/blocks.py b/gradio/blocks.py
--- a/gradio/blocks.py
+++ b/gradio/blocks.py
@@ -421,10 +421,11 @@ def postprocess_update_dict(block: Block, update_dict: Dict, postprocess: bool =
         update_dict: The original update dictionary
         postprocess: Whether to postprocess the "value" key of the update dictionary.
     """
-    prediction_value = block.get_specific_update(update_dict)
-    if prediction_value.get("value") is components._Keywords.NO_VALUE:
-        prediction_value.pop("value")
-    prediction_value = delete_none(prediction_value, skip_value=True)
+    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")
+    prediction_value = delete_none(update_dict, skip_value=True)
     if "value" in prediction_value and postprocess:
         prediction_value["value"] = block.postprocess(prediction_value["value"])
     return prediction_value


Test patch:
diff --git a/test/test_blocks.py b/test/test_blocks.py
--- a/test/test_blocks.py
+++ b/test/test_blocks.py
@@ -391,6 +391,35 @@ def infer(x):
             "value": gr.media_data.BASE64_IMAGE,
         }
 
+    @pytest.mark.asyncio
+    async def test_blocks_update_interactive(
+        self,
+    ):
+        def specific_update():
+            return [
+                gr.Image.update(interactive=True),
+                gr.Textbox.update(interactive=True),
+            ]
+
+        def generic_update():
+            return [gr.update(interactive=True), gr.update(interactive=True)]
+
+        with gr.Blocks() as demo:
+            run = gr.Button(value="Make interactive")
+            image = gr.Image()
+            textbox = gr.Text()
+            run.click(specific_update, None, [image, textbox])
+            run.click(generic_update, None, [image, textbox])
+
+        for fn_index in range(2):
+            output = await demo.process_api(fn_index, [])
+            assert output["data"][0] == {
+                "interactive": True,
+                "__type__": "update",
+                "mode": "dynamic",
+            }
+            assert output["data"][1] == {"__type__": "update", "mode": "dynamic"}
+
 
 class TestCallFunction:
     @pytest.mark.asyncio
@@ -677,7 +706,22 @@ def test_without_update(self):
 
     def test_with_update(self):
         specific_update = gr.Textbox.get_specific_update(
-            {"lines": 4, "__type__": "update"}
+            {"lines": 4, "__type__": "update", "interactive": False}
+        )
+        assert specific_update == {
+            "lines": 4,
+            "max_lines": None,
+            "placeholder": None,
+            "label": None,
+            "show_label": None,
+            "visible": None,
+            "value": gr.components._Keywords.NO_VALUE,
+            "__type__": "update",
+            "mode": "static",
+        }
+
+        specific_update = gr.Textbox.get_specific_update(
+            {"lines": 4, "__type__": "update", "interactive": True}
         )
         assert specific_update == {
             "lines": 4,
@@ -688,19 +732,26 @@ def test_with_update(self):
             "visible": None,
             "value": gr.components._Keywords.NO_VALUE,
             "__type__": "update",
+            "mode": "dynamic",
         }
 
     def test_with_generic_update(self):
         specific_update = gr.Video.get_specific_update(
-            {"visible": True, "value": "test.mp4", "__type__": "generic_update"}
+            {
+                "visible": True,
+                "value": "test.mp4",
+                "__type__": "generic_update",
+                "interactive": True,
+            }
         )
         assert specific_update == {
             "source": None,
             "label": None,
             "show_label": None,
-            "interactive": None,
             "visible": True,
             "value": "test.mp4",
+            "mode": "dynamic",
+            "interactive": True,
             "__type__": "update",
         }
 
diff --git a/test/test_examples.py b/test/test_examples.py
--- a/test/test_examples.py
+++ b/test/test_examples.py
@@ -151,7 +151,10 @@ async def test_caching_with_update(self):
             cache_examples=True,
         )
         prediction = await io.examples_handler.load_from_cache(1)
-        assert prediction[0] == {"visible": False, "__type__": "update"}
+        assert prediction[0] == {
+            "visible": False,
+            "__type__": "update",
+        }
 
     @pytest.mark.asyncio
     async def test_caching_with_mix_update(self):
@@ -163,7 +166,11 @@ async def test_caching_with_mix_update(self):
             cache_examples=True,
         )
         prediction = await io.examples_handler.load_from_cache(1)
-        assert prediction[0] == {"lines": 4, "value": "hello", "__type__": "update"}
+        assert prediction[0] == {
+            "lines": 4,
+            "value": "hello",
+            "__type__": "update",
+        }
 
     @pytest.mark.asyncio
     async def test_caching_with_dict(self):
@@ -171,15 +178,18 @@ async def test_caching_with_dict(self):
         out = gr.Label()
 
         io = gr.Interface(
-            lambda _: {text: gr.update(lines=4), out: "lion"},
+            lambda _: {text: gr.update(lines=4, interactive=False), out: "lion"},
             "textbox",
             [text, out],
             examples=["abc"],
             cache_examples=True,
         )
         prediction = await io.examples_handler.load_from_cache(0)
-        assert prediction == [{"lines": 4, "__type__": "update"}, {"label": "lion"}]
         assert not any(d["trigger"] == "fake_event" for d in io.config["dependencies"])
+        assert prediction == [
+            {"lines": 4, "__type__": "update", "mode": "static"},
+            {"label": "lion"},
+        ]
 
     def test_raise_helpful_error_message_if_providing_partial_examples(self, tmp_path):
         def foo(a, b):