text: from unittest import SkipTest
  
  from holoviews.core.spaces import DynamicMap
  from holoviews.core.options import Store
  from holoviews.element import Curve, Polygons, Path, Image, HLine
  from holoviews.element.comparison import ComparisonTestCase
  from holoviews.streams import RangeXY, PlotReset
  
  try:
      from bokeh.application.handlers import FunctionHandler
      from bokeh.application import Application
      from bokeh.client import pull_session
      from bokeh.document import Document
      from bokeh.io import curdoc
      from bokeh.server.server import Server
  
      from holoviews.plotting.bokeh.callbacks import (
          Callback, RangeXYCallback, ResetCallback
      )
      from holoviews.plotting.bokeh.renderer import BokehRenderer
      bokeh_renderer = BokehRenderer.instance(mode='server')
  except:
      bokeh_renderer = None
  
  
  class TestBokehServerSetup(ComparisonTestCase):
  
      def setUp(self):
          self.previous_backend = Store.current_backend
          if not bokeh_renderer:
              raise SkipTest("Bokeh required to test plot instantiation")
          Store.current_backend = 'bokeh'
  
      def tearDown(self):
          Store.current_backend = self.previous_backend
          bokeh_renderer.last_plot = None
          Callback._callbacks = {}
  
      def test_render_server_doc_element(self):
          obj = Curve([])
          doc = bokeh_renderer.server_doc(obj)
          self.assertIs(doc, curdoc())
          self.assertIs(bokeh_renderer.last_plot.document, curdoc())
  
      def test_render_explicit_server_doc_element(self):
          obj = Curve([])
          doc = Document()
          server_doc = bokeh_renderer.server_doc(obj, doc)
          self.assertIs(server_doc, doc)
          self.assertIs(bokeh_renderer.last_plot.document, doc)
  
      def test_set_up_linked_change_stream_on_server_doc(self):
          obj = Curve([])
          stream = RangeXY(source=obj)
          server_doc = bokeh_renderer.server_doc(obj)
          self.assertEqual(len(bokeh_renderer.last_plot.callbacks), 1)
          cb = bokeh_renderer.last_plot.callbacks[0]
          self.assertIsInstance(cb, RangeXYCallback)
          self.assertEqual(cb.streams, [stream])
          x_range = bokeh_renderer.last_plot.handles['x_range']
          self.assertIn(cb.on_change, x_range._callbacks['start'])
          self.assertIn(cb.on_change, x_range._callbacks['end'])
          y_range = bokeh_renderer.last_plot.handles['y_range']
          self.assertIn(cb.on_change, y_range._callbacks['start'])
          self.assertIn(cb.on_change, y_range._callbacks['end'])
  
      def test_set_up_linked_event_stream_on_server_doc(self):
          obj = Curve([])
          stream = PlotReset(source=obj)
          server_doc = bokeh_renderer.server_doc(obj)
          cb = bokeh_renderer.last_plot.callbacks[0]
          self.assertIsInstance(cb, ResetCallback)
          self.assertEqual(cb.streams, [stream])
          plot = bokeh_renderer.last_plot.state
          self.assertIn(cb.on_event, plot._event_callbacks['reset'])
  
  
  
  class TestBokehServerRun(ComparisonTestCase):
  
      def setUp(self):
          self.previous_backend = Store.current_backend
          if not bokeh_renderer:
              raise SkipTest("Bokeh required to test plot instantiation")
          Store.current_backend = 'bokeh'
  
      def tearDown(self):
          Store.current_backend = self.previous_backend
          Callback._callbacks = {}
  
      def test_launch_simple_server(self):
          obj = Curve([])
          launched = []
          def modify_doc(doc):
              bokeh_renderer(obj, doc=doc)
              launched.append(True)
              server.stop()
          handler = FunctionHandler(modify_doc)
          app = Application(handler)
          server = Server({'/': app}, port=0)
          server.start()
          url = "http://localhost:" + str(server.port) + "/"
          pull_session(session_id='Test', url=url, io_loop=server.io_loop)
          self.assertTrue(len(launched)==1)
  
      def test_launch_server_with_stream(self):
          obj = Curve([])
          stream = RangeXY(source=obj)
  
          launched = []
          def modify_doc(doc):
              bokeh_renderer(obj, doc=doc)
              launched.append(True)
              server.stop()
          handler = FunctionHandler(modify_doc)
          app = Application(handler)
          server = Server({'/': app}, port=0)
          server.start()
          url = "http://localhost:" + str(server.port) + "/"
          pull_session(session_id='Test', url=url, io_loop=server.io_loop)
  
          self.assertTrue(len(launched)==1)
          cb = bokeh_renderer.last_plot.callbacks[0]
          self.assertIsInstance(cb, RangeXYCallback)
          self.assertEqual(cb.streams, [stream])
          x_range = bokeh_renderer.last_plot.handles['x_range']
          self.assertIn(cb.on_change, x_range._callbacks['start'])
          self.assertIn(cb.on_change, x_range._callbacks['end'])
          y_range = bokeh_renderer.last_plot.handles['y_range']
          self.assertIn(cb.on_change, y_range._callbacks['start'])
          self.assertIn(cb.on_change, y_range._callbacks['end'])
  
  
      def test_launch_server_with_complex_plot(self):
          dmap = DynamicMap(lambda x_range, y_range: Curve([]), streams=[RangeXY()])
          overlay = dmap * HLine(0)
          static = Polygons([]) * Path([]) * Curve([])
          layout = overlay + static
  
          launched = []
          def modify_doc(doc):
              bokeh_renderer(layout, doc=doc)
              launched.append(True)
              server.stop()
          handler = FunctionHandler(modify_doc)
          app = Application(handler)
          server = Server({'/': app}, port=0)
          server.start()
          url = "http://localhost:" + str(server.port) + "/"
          pull_session(session_id='Test', url=url, io_loop=server.io_loop)
          self.assertTrue(len(launched)==1)
  