#-----------------------------------------------------------------------------# Copyright (c) 2012 - 2022, Anaconda, Inc., and Bokeh Contributors.# All rights reserved.## The full license is in the file LICENSE.txt, distributed with this software.#-----------------------------------------------------------------------------''' Implement and provide message protocols for communication between BokehServers and clients.'''#-----------------------------------------------------------------------------# Boilerplate#-----------------------------------------------------------------------------from__future__importannotationsimportlogging# isort:skiplog=logging.getLogger(__name__)#-----------------------------------------------------------------------------# Imports#-----------------------------------------------------------------------------# Standard library importsimportjsonfromtypingimport(TYPE_CHECKING,Any,Dict,List,Type,overload,)# External importsfromtyping_extensionsimportLiteral# Bokeh importsfrom.exceptionsimportProtocolErrorfrom.messageimportMessagefrom.messages.ackimportackfrom.messages.errorimporterrorfrom.messages.okimportokfrom.messages.patch_docimportpatch_docfrom.messages.pull_doc_replyimportpull_doc_replyfrom.messages.pull_doc_reqimportpull_doc_reqfrom.messages.push_docimportpush_docfrom.messages.server_info_replyimportserver_info_replyfrom.messages.server_info_reqimportserver_info_reqifTYPE_CHECKING:from..core.typesimportIDfrom..document.documentimportDocumentfrom..document.eventsimportDocumentPatchedEventfrom.receiverimportFragment#-----------------------------------------------------------------------------# Globals and constants#-----------------------------------------------------------------------------__all__=('Protocol',)MessageType=Literal["ACK","ERROR","OK","PATCH-DOC","PULL-DOC-REPLY","PULL-DOC-REQ","PUSH-DOC","SERVER-INFO-REPLY","SERVER-INFO-REQ",]SPEC:Dict[MessageType,Type[Message[Any]]]={"ACK":ack,"ERROR":error,"OK":ok,"PATCH-DOC":patch_doc,"PULL-DOC-REPLY":pull_doc_reply,"PULL-DOC-REQ":pull_doc_req,"PUSH-DOC":push_doc,"SERVER-INFO-REPLY":server_info_reply,"SERVER-INFO-REQ":server_info_req,}#-----------------------------------------------------------------------------# General API#-----------------------------------------------------------------------------#-----------------------------------------------------------------------------# Dev API#-----------------------------------------------------------------------------
[docs]classProtocol:''' Provide a message factory for the Bokeh Server message protocol. '''_messages:Dict[MessageType,Type[Message[Any]]]def__init__(self)->None:self._messages=SPECdef__repr__(self)->str:return"Protocol()"@overloaddefcreate(self,msgtype:Literal["ACK"],**metadata:Any)->ack:...@overloaddefcreate(self,msgtype:Literal["ERROR"],request_id:ID,text:str,**metadata:Any)->error:...@overloaddefcreate(self,msgtype:Literal["OK"],request_id:ID,**metadata:Any)->ok:...@overloaddefcreate(self,msgtype:Literal["PATCH-DOC"],events:List[DocumentPatchedEvent],use_buffers:bool=...,**metadata:Any)->patch_doc:...@overloaddefcreate(self,msgtype:Literal["PULL-DOC-REPLY"],request_id:ID,document:Document,**metadata:Any)->pull_doc_reply:...@overloaddefcreate(self,msgtype:Literal["PULL-DOC-REQ"],**metadata:Any)->pull_doc_req:...@overloaddefcreate(self,msgtype:Literal["PUSH-DOC"],document:Document,**metadata:Any)->push_doc:...@overloaddefcreate(self,msgtype:Literal["SERVER-INFO-REPLY"],request_id:ID,**metadata:Any)->server_info_reply:...@overloaddefcreate(self,msgtype:Literal["SERVER-INFO-REQ"],**metadata:Any)->server_info_req:...
[docs]defcreate(self,msgtype:MessageType,*args:Any,**kwargs:Any)->Message[Any]:''' Create a new Message instance for the given type. Args: msgtype (str) : '''ifmsgtypenotinself._messages:raiseProtocolError(f"Unknown message type {msgtype!r} for Bokeh protocol")returnself._messages[msgtype].create(*args,**kwargs)# type: ignore [attr-defined]
[docs]defassemble(self,header_json:str,metadata_json:str,content_json:str)->Message[Any]:''' Create a Message instance assembled from json fragments. Args: header_json (``JSON``) : metadata_json (``JSON``) : content_json (``JSON``) : Returns: message '''header=json.loads(header_json)if'msgtype'notinheader:log.error(f"Bad header with no msgtype was: {header!r}")raiseProtocolError("No 'msgtype' in header")returnself._messages[header["msgtype"]].assemble(header_json,metadata_json,content_json)