Repository: gradio-app/gradio

Issue:
Bokeh plots do not appear
### Describe the bug

When using the `Plot` component, bokeh plots do not appear at all.

This is documented here: #1632 

> Pictures cannot be generated in Bokeh mode.

And in this PR: #1609 

> The Bokeh plots are currently broken. The reason for this is that bokehJS internally uses getElementById to get the container of the plot and render it. Since Gradio UI is using the shadow DOM to render, this step fails.

> I have tried here a workaround where I added a new hidden div in the index.html file to use as a helper to render the plot, once it is rendered, then the content is appended to the actual div that should have the plot. This part is all working, unfortunately although I can see the div with the expected content, the plot is still not showing.

The PR was closed because it was an attempt to fix the problem using an older version of bokeh. We still need to find a solution using the latest version of bokeh.


### Is there an existing issue for this?

- [X] I have searched the existing issues

### Reproduction

https://github.com/gradio-app/gradio/blob/main/demo/outbreak_forecast/run.py

### Screenshot

_No response_

### Logs

```shell
N/A
```


### System Info

```shell
3.1.3
```


### Severity

serious, but I can work around it


Discussion:
cc @dawoodkhan82 @Ian-GL 
Is this Bug resolved in the latest release 3.4.0?
> Is this Bug resolved in the latest release 3.4.0?

Unfortunately not yet. It is on our radar though. Will update this issue when we do resolve this.
It looks like bokeh 3.0.3 is out, so it might be good to revisit this @dawoodkhan82 
Will revisit!
I was trying to use bokeh maps. Got an error `TypeError: Model.to_json() missing 1 required positional argument: 'include_defaults'`


```python
import gradio as gr
import xyzservices.providers as xyz
from bokeh.plotting import figure
from bokeh.tile_providers import get_provider

def create_map(text):

    tile_provider = get_provider(xyz.OpenStreetMap.Mapnik)
    p = figure(x_range=(-2000000, 6000000), y_range=(-1000000, 7000000),
            x_axis_type="mercator", y_axis_type="mercator")
    p.add_tile(tile_provider)
    return p

demo = gr.Interface(
    fn=create_map,
    inputs='text',
    outputs=gr.Plot().style(),
)
demo.launch()
```
Will take a look @giswqs ! My guess is that the gradio library is using an outdated bokeh api that's not compatible with the bokeh version in your demo.

Mind sharing your bokeh version? As well as xyzservices? BTW what is that library?

See the example at https://docs.bokeh.org/en/latest/docs/examples/topics/geo/tile_xyzservices.html

[xyzservices](https://github.com/geopandas/xyzservices) is a lightweight library providing a repository of available XYZ services offering raster basemap tiles. 

- gradio: 3.18.0
- bokeh: 2.4.3
- xyzservices: 2022.9.0
Thanks @giswqs ! So the issue about `to_json() missing 1 required positional argument` should be easy to fix but the problem about the UI not displaying the plots persists. What's more, looks like there's a big difference between bokeh 2.0 and bokeh 3.0. Might be hard to support both? If we had to choose one, would 3.0 be better?
Yes, prefer bokeh 3.x.

Resolving patch:
diff --git a/demo/bokeh_plot/run.py b/demo/bokeh_plot/run.py
new file mode 100644
--- /dev/null
+++ b/demo/bokeh_plot/run.py
@@ -0,0 +1,94 @@
+import gradio as gr
+import xyzservices.providers as xyz
+from bokeh.plotting import figure
+from bokeh.tile_providers import get_provider
+from bokeh.models import ColumnDataSource, Whisker
+from bokeh.plotting import figure
+from bokeh.sampledata.autompg2 import autompg2 as df
+from bokeh.sampledata.penguins import data
+from bokeh.transform import factor_cmap, jitter, factor_mark
+
+
+def get_plot(plot_type):
+    if plot_type == "map":
+        tile_provider = get_provider(xyz.OpenStreetMap.Mapnik)
+        plot = figure(
+            x_range=(-2000000, 6000000),
+            y_range=(-1000000, 7000000),
+            x_axis_type="mercator",
+            y_axis_type="mercator",
+        )
+        plot.add_tile(tile_provider)
+        return plot
+    elif plot_type == "whisker":
+        classes = list(sorted(df["class"].unique()))
+
+        p = figure(
+            height=400,
+            x_range=classes,
+            background_fill_color="#efefef",
+            title="Car class vs HWY mpg with quintile ranges",
+        )
+        p.xgrid.grid_line_color = None
+
+        g = df.groupby("class")
+        upper = g.hwy.quantile(0.80)
+        lower = g.hwy.quantile(0.20)
+        source = ColumnDataSource(data=dict(base=classes, upper=upper, lower=lower))
+
+        error = Whisker(
+            base="base",
+            upper="upper",
+            lower="lower",
+            source=source,
+            level="annotation",
+            line_width=2,
+        )
+        error.upper_head.size = 20
+        error.lower_head.size = 20
+        p.add_layout(error)
+
+        p.circle(
+            jitter("class", 0.3, range=p.x_range),
+            "hwy",
+            source=df,
+            alpha=0.5,
+            size=13,
+            line_color="white",
+            color=factor_cmap("class", "Light6", classes),
+        )
+        return p
+    elif plot_type == "scatter":
+
+        SPECIES = sorted(data.species.unique())
+        MARKERS = ["hex", "circle_x", "triangle"]
+
+        p = figure(title="Penguin size", background_fill_color="#fafafa")
+        p.xaxis.axis_label = "Flipper Length (mm)"
+        p.yaxis.axis_label = "Body Mass (g)"
+
+        p.scatter(
+            "flipper_length_mm",
+            "body_mass_g",
+            source=data,
+            legend_group="species",
+            fill_alpha=0.4,
+            size=12,
+            marker=factor_mark("species", MARKERS, SPECIES),
+            color=factor_cmap("species", "Category10_3", SPECIES),
+        )
+
+        p.legend.location = "top_left"
+        p.legend.title = "Species"
+        return p
+
+with gr.Blocks() as demo:
+    with gr.Row():
+        plot_type = gr.Radio(value="scatter", choices=["scatter", "whisker", "map"])
+        plot = gr.Plot()
+    plot_type.change(get_plot, inputs=[plot_type], outputs=[plot])
+    demo.load(get_plot, inputs=[plot_type], outputs=[plot])
+
+
+if __name__ == "__main__":
+    demo.launch()
\ No newline at end of file
diff --git a/gradio/components.py b/gradio/components.py
--- a/gradio/components.py
+++ b/gradio/components.py
@@ -4132,7 +4132,17 @@ def __init__(
         )
 
     def get_config(self):
-        return {"value": self.value, **IOComponent.get_config(self)}
+        try:
+            import bokeh  # type: ignore
+
+            bokeh_version = bokeh.__version__
+        except ImportError:
+            bokeh_version = None
+        return {
+            "value": self.value,
+            "bokeh_version": bokeh_version,
+            **IOComponent.get_config(self),
+        }
 
     @staticmethod
     def update(
@@ -4162,9 +4172,11 @@ def postprocess(self, y) -> Dict[str, str] | None:
         if isinstance(y, (ModuleType, matplotlib.figure.Figure)):
             dtype = "matplotlib"
             out_y = processing_utils.encode_plot_to_base64(y)
-        elif isinstance(y, dict):
+        elif "bokeh" in y.__module__:
             dtype = "bokeh"
-            out_y = json.dumps(y)
+            from bokeh.embed import json_item  # type: ignore
+
+            out_y = json.dumps(json_item(y))
         else:
             is_altair = "altair" in y.__module__
             if is_altair:


Test patch:
diff --git a/test/test_components.py b/test/test_components.py
--- a/test/test_components.py
+++ b/test/test_components.py
@@ -2017,7 +2017,9 @@ def test_dataset_calls_as_example(*mocks):
 
 
 class TestScatterPlot:
+    @patch.dict("sys.modules", {"bokeh": MagicMock(__version__="3.0.3")})
     def test_get_config(self):
+
         assert gr.ScatterPlot().get_config() == {
             "caption": None,
             "elem_id": None,
@@ -2029,6 +2031,7 @@ def test_get_config(self):
             "style": {},
             "value": None,
             "visible": True,
+            "bokeh_version": "3.0.3",
         }
 
     def test_no_color(self):
@@ -2199,6 +2202,7 @@ def test_scatterplot_accepts_fn_as_value(self):
 
 
 class TestLinePlot:
+    @patch.dict("sys.modules", {"bokeh": MagicMock(__version__="3.0.3")})
     def test_get_config(self):
         assert gr.LinePlot().get_config() == {
             "caption": None,
@@ -2211,6 +2215,7 @@ def test_get_config(self):
             "style": {},
             "value": None,
             "visible": True,
+            "bokeh_version": "3.0.3",
         }
 
     def test_no_color(self):
@@ -2360,6 +2365,7 @@ def test_lineplot_accepts_fn_as_value(self):
 
 
 class TestBarPlot:
+    @patch.dict("sys.modules", {"bokeh": MagicMock(__version__="3.0.3")})
     def test_get_config(self):
         assert gr.BarPlot().get_config() == {
             "caption": None,
@@ -2372,6 +2378,7 @@ def test_get_config(self):
             "style": {},
             "value": None,
             "visible": True,
+            "bokeh_version": "3.0.3",
         }
 
     def test_no_color(self):