Source code for bokeh.client.websocket

''' Provide a low-level wrapper for Tornado Websockets that adds locking
and smooths some compatibility issues.

'''
from __future__ import absolute_import, print_function

from tornado import gen, locks
from tornado.websocket import WebSocketError

[docs]class WebSocketClientConnectionWrapper(object): ''' Used for compat across Tornado versions and to add write_lock''' def __init__(self, socket): if socket is None: raise ValueError("socket must not be None") self._socket = socket # write_lock allows us to lock the connection to send multiple # messages atomically. self.write_lock = locks.Lock() @gen.coroutine
[docs] def write_message(self, message, binary=False, locked=True): ''' Write a message to the websocket after obtaining the appropriate Bokeh Document lock. ''' def write_message_unlocked(): if self._socket.protocol is None: # Tornado is maybe supposed to do this, but in fact it # tries to do _socket.protocol.write_message when protocol # is None and throws AttributeError or something. So avoid # trying to write to the closed socket. There doesn't seem # to be an obvious public function to check if the socket # is closed. raise WebSocketError("Connection to the server has been closed") future = self._socket.write_message(message, binary) # don't yield this future or we're blocking on ourselves! raise gen.Return(future) if locked: with (yield self.write_lock.acquire()): write_message_unlocked() else: write_message_unlocked()
[docs] def close(self, code=None, reason=None): ''' Close the websocket. ''' return self._socket.close(code, reason)
[docs] def read_message(self, callback=None): ''' Read a message from websocket and execute a callback. ''' return self._socket.read_message(callback)