Repository: bokeh/bokeh

Issue:
IPywidgets examples
Need at least the following examples

* server example with basic sliders, etc
* server example with ipyvolume
* server example with ipyleaflet 
* notebook example with bokeh plot in ipywidgets layotut

maybe best under a `howto/ipywidgets` directory?

@mattpap for the last I am basing on my understanding that that direction is also now possible. Can you point to some example code for how to do that?


Discussion:
@mattpap it would be very helpful and appreciated if you could take one hour and provide 1 or 2 of the examples above so I can point users asking how to actually use this feature, at something concrete
Rescheduling back 2.0.1. I will get that done by tomorrow.
I was planning on building packages today, since I have the time today. 
I see. In that case let's proceed, but we will need to have 2.0.2 soon after that.

Resolving patch:
diff --git a/examples/howto/ipywidgets/ipyleaflet_tiles.py b/examples/howto/ipywidgets/ipyleaflet_tiles.py
new file mode 100644
--- /dev/null
+++ b/examples/howto/ipywidgets/ipyleaflet_tiles.py
@@ -0,0 +1,26 @@
+from ipyleaflet import Map
+from ipywidgets_bokeh import IPyWidget
+
+from bokeh.layouts import row
+from bokeh.models import WMTSTileSource
+from bokeh.plotting import curdoc, figure
+
+center = [51.1079, 17.0385]
+zoom = 7
+
+map = Map(center=center, zoom=zoom)
+map_wrapper = IPyWidget(widget=map, width=600, height=400)
+
+url = "http://c.tile.openstreetmap.org/{z}/{x}/{y}.png"
+attribution = "Map data (c) <a href='https://www.openstreetmap.org/'>OpenStreetMap</a> contributors"
+tile_source = WMTSTileSource(url=url, attribution=attribution)
+
+plot = figure(
+    x_range=(1551600, 2212000), y_range=(6417000, 6872000),
+    x_axis_type=None, y_axis_type=None,
+    width=600, height=400,
+)
+plot.add_tile(tile_source)
+
+doc = curdoc()
+doc.add_root(row(map_wrapper, plot))
diff --git a/examples/howto/ipywidgets/ipyvolume_camera.py b/examples/howto/ipywidgets/ipyvolume_camera.py
new file mode 100644
--- /dev/null
+++ b/examples/howto/ipywidgets/ipyvolume_camera.py
@@ -0,0 +1,59 @@
+import ipyvolume as ipv
+import ipywidgets as ipw
+import numpy as np
+from ipywidgets_bokeh import IPyWidget
+
+from bokeh.layouts import column, row
+from bokeh.models import Slider
+from bokeh.plotting import curdoc
+
+x, y, z = np.random.random((3, 1000))
+ipv.quickscatter(x, y, z, size=1, marker="sphere")
+plot = ipv.current.figure
+
+x_slider = Slider(start=0, end=359, value=0, step=1, title="X-axis")
+y_slider = Slider(start=0, end=359, value=0, step=1, title="Y-axis")
+z_slider = Slider(start=0, end=359, value=0, step=1, title="Z-axis")
+
+def randomize(button):
+    x, y, z = np.random.random((3, 1000))
+    scatter = plot.scatters[0]
+    with plot.hold_sync():
+        scatter.x = x
+        scatter.y = y
+        scatter.z = z
+
+randomize_button = ipw.Button(description="Randomize")
+randomize_button.on_click(randomize)
+
+def change_anglex(change):
+    v = round(np.degrees(change["new"])) % 360
+    x_slider.value = v
+def change_angley(change):
+    v = round(np.degrees(change["new"])) % 360
+    y_slider.value = v
+def change_anglez(change):
+    v = round(np.degrees(change["new"])) % 360
+    z_slider.value = v
+plot.observe(change_anglex, names="anglex")
+plot.observe(change_angley, names="angley")
+plot.observe(change_anglez, names="anglez")
+
+def change_x(_attr, _old, new):
+    plot.anglex = np.radians(new)
+def change_y(_attr, _old, new):
+    plot.angley = np.radians(new)
+def change_z(_attr, _old, new):
+    plot.anglez = np.radians(new)
+x_slider.on_change("value", change_x)
+y_slider.on_change("value", change_y)
+z_slider.on_change("value", change_z)
+
+button_wrapper = IPyWidget(widget=randomize_button)
+plot_wrapper = IPyWidget(widget=plot)
+
+vbox = column([x_slider, y_slider, z_slider, button_wrapper])
+hbox = row([vbox, plot_wrapper])
+
+doc = curdoc()
+doc.add_root(hbox)


Test patch:
diff --git a/tests/unit/bokeh/server/test_server__server.py b/tests/unit/bokeh/server/test_server__server.py
--- a/tests/unit/bokeh/server/test_server__server.py
+++ b/tests/unit/bokeh/server/test_server__server.py
@@ -680,6 +680,7 @@ async def test__autocreate_signed_session_doc(ManagedServerLoop) -> None:
 
         assert check_token_signature(token, signed=True, secret_key='foo')
 
+@flaky(max_runs=10)
 async def test__accept_session_websocket(ManagedServerLoop) -> None:
     application = Application()
     with ManagedServerLoop(application, session_token_expiration=1) as server: