
    -e%.                       U d Z ddlmZ ddlZ ej        e          ZddlZddlm	Z	m
Z
mZmZmZmZ ddlmc mZ ddlmZ ddlmZmZ ddlmZ d	d
lmZmZ e	rddlmZmZ ddl m!Z! dZ" G d de          Z# G d de          Z$ ed          Z%e&e'e
f         Z(de)d<   e*e$e+f         Z,de)d<    G d de          Z- G d dee%                   Z.dS )a   Provide a base class for all Bokeh Server Protocol message types.

Boker messages are comprised of a sequence of JSON fragments. Specified as
Python JSON-like data, messages have the general form:

.. code-block:: python

    [
        # these are required
        b'{header}',        # serialized header dict
        b'{metadata}',      # serialized metadata dict
        b'{content}',       # serialized content dict

        # these are optional, and come in pairs; header contains num_buffers
        b'{buf_header}',    # serialized buffer header dict
        b'array'            # raw buffer payload data
        ...
    ]

The ``header`` fragment will have the form:

.. code-block:: python

    header = {
        # these are required
        'msgid'       : <str> # a unique id for the message
        'msgtype'     : <str> # a message type, e.g. 'ACK', 'PATCH-DOC', etc

        # these are optional
        'num_buffers' : <int> # the number of additional buffers, if any
    }

The ``metadata`` fragment may contain any arbitrary information. It is not
processed by Bokeh for any purpose, but may be useful for external
monitoring or instrumentation tools.

The ``content`` fragment is defined by the specific message type.

    )annotationsN)TYPE_CHECKINGAnyClassVarGeneric	TypedDictTypeVar   )serialize_json)Buffer
Serialized)ID   )MessageErrorProtocolError)NotRequired	TypeAlias) WebSocketClientConnectionWrapper)Messagec                  8    e Zd ZU ded<   ded<   ded<   ded<   d	S )
Headerr   msgidstrmsgtypezNotRequired[ID]reqidzNotRequired[int]num_buffersN__name__
__module____qualname____annotations__     6lib/python3.11/site-packages/bokeh/protocol/message.pyr   r   d   s<         IIILLL!!!!!!r#   r   c                      e Zd ZU ded<   dS )BufferHeaderr   idNr   r"   r#   r$   r&   r&   j   s         
FFFFFr#   r&   Contentr   Metadata	BufferRefc                      e Zd ZdS )EmptyN)r   r   r    r"   r#   r$   r,   r,   s   s        Dr#   r,   c                     e Zd ZU dZded<   ded<   ded<   ded	<   ded
<   ded<   ded<   ded<   d?dZd@dZedAd            ZdBdZ	dCd$Z
dDdEd+ZedFdGd/            ZdHd0ZedId1            ZedJd3            ZedKd4            Zej        dLd6            Zed@d7            ZedMd8            Zej        dNd9            Zed@d:            ZedOd;            Zej        dPd<            Zed@d=            ZedQd>            Zd,S )Rr   z The Message base class encapsulates creating, assembling, and
    validating the integrity of Bokeh Server messages. Additionally, it
    provide hooks

    zClassVar[str]r   r   _headerz
str | None_header_jsonr(   _content_content_jsonr)   	_metadata_metadata_jsonlist[Buffer]_buffersheadermetadatacontentreturnNonec                >    || _         || _        || _        g | _        dS )a   Initialize a new message from header, metadata, and content
        dictionaries.

        To assemble a message from existing JSON fragments, use the
        ``assemble`` method.

        To create new messages with automatically generated headers,
        use subclass ``create`` methods.

        Args:
            header (JSON-like) :

            metadata (JSON-like) :

            content (JSON-like) :

        N)r6   r7   r8   r5   )selfr6   r7   r8   s       r$   __init__zMessage.__init__   s$    $  r#   r   c                &    d| j         d| j        S )NzMessage z
 content: )r   r8   r<   s    r$   __repr__zMessage.__repr__   s    D$,DDDLDDDr#   header_jsonmetadata_jsoncontent_jsonMessage[Content]c                |   	 t          j        |          }n# t          $ r t          d          w xY w	 t          j        |          }n# t          $ r t          d          w xY w	 t          j        |          }n# t          $ r t          d          w xY w | |||          }||_        ||_        ||_        |S )a   Creates a new message, assembled from JSON fragments.

        Args:
            header_json (``JSON``) :

            metadata_json (``JSON``) :

            content_json (``JSON``) :

        Returns:
            Message subclass

        Raises:
            MessageError

        zheader could not be decodedzmetadata could not be decodedzcontent could not be decoded)jsonloads
ValueErrorr   r/   r3   r1   )clsrA   rB   rC   r6   r7   r8   msgs           r$   assemblezMessage.assemble   s    &	>Z,,FF 	> 	> 	><===	>	@z-00HH 	@ 	@ 	@>???	@	?j..GG 	? 	? 	?=>>>	? c&(G,,&*(
s    1A
 
A$(A= =Bbufferr   c                    d| j         v r| j         dxx         dz  cc<   n
d| j         d<   d| _        | j                            |           dS )a   Associate a buffer header and payload with this message.

        Args:
            buf_header (``JSON``) : a buffer header
            buf_payload (``JSON`` or bytes) : a buffer payload

        Returns:
            None

        Raises:
            MessageError

        r   r   N)r.   r/   r5   append)r<   rL   s     r$   
add_bufferzMessage.add_buffer   sb     DL((L'''1,''''*+DL' V$$$$$r#   
buf_headerr&   buf_payloadbytesc                    | j                             dd          }|t          | j                  k    rt	          d|           | j                            t          |d         |                     dS )a   Add a buffer header and payload that we read from the socket.

        This differs from add_buffer() because we're validating vs.
        the header's num_buffers, instead of filling in the header.

        Args:
            buf_header (``JSON``) : a buffer header
            buf_payload (``JSON`` or bytes) : a buffer payload

        Returns:
            None

        Raises:
            ProtocolError
        r   r   z$too many buffers received expecting r'   N)r6   getlenr5   r   rN   r   )r<   rP   rQ   r   s       r$   assemble_bufferzMessage.assemble_buffer   sp      koomQ77#dm,,,, T{ T TUUUVJt$4kBBCCCCCr#   Tconnr   lockedboolintc                X  K   |t          d          d}| j        D ]}t          j        |j                  }|                                }|                    ||           d{V  |                    |d|           d{V  |t          |          t          |          z   z  }|S )aa   Write any buffer headers and payloads to the given connection.

        Args:
            conn (object) :
                May be any object with a ``write_message`` method. Typically,
                a Tornado ``WSHandler`` or ``WebSocketClientConnection``

            locked (bool) :

        Returns:
            int : number of bytes sent

        Nz'Cannot write_buffers to connection Noner   rX   T)binaryrX   )rH   r5   rF   dumpsrefto_byteswrite_messagerU   )r<   rW   rX   sentrL   r6   payloads          r$   write_bufferszMessage.write_buffers   s       <FGGGm 	/ 	/FZ
++Foo''G$$VF$;;;;;;;;;$$WT&$IIIIIIIIICKK#g,,..DDr#   N
request_id	ID | Nonec                b    t          t          j                    | j                  }|||d<   |S )z Return a message header fragment dict.

        Args:
            request_id (str or None) :
                Message ID of the message this message replies to

        Returns:
            dict : a message header

        )r   r   Nr   )r   bkserialmake_idr   )rI   re   r6   s      r$   create_headerzMessage.create_header  s?     &((k
 
 
 !(F7Or#   c                8  K   |t          d          |j                                         d{V 5  d}|                    | j        d           d{V  |t          | j                  z  }|                    | j        d           d{V  |t          | j                  z  }|                    | j        d           d{V  |t          | j                  z  }||                     |d           d{V z  }|cddd           S # 1 swxY w Y   dS )z Send the message on the given connection.

        Args:
            conn (WebSocketHandler) : a WebSocketHandler to send messages

        Returns:
            int : number of bytes sent

        NzCannot send to connection Noner   Fr\   )	rH   
write_lockacquirera   rA   rU   rB   rC   rd   )r<   rW   rb   s      r$   sendzMessage.send&  s      <=>>>?**,,,,,,,, 	 	D$$T%5e$DDDDDDDDDC()))D
 $$T%7$FFFFFFFFFC*+++D
 $$T%6u$EEEEEEEEEC)***D$,,T%,@@@@@@@@@D)	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	s   CDDDc                    | j         duoB| j        duo9| j        duo0| j                             dd          t	          | j                  k    S )z Returns whether all required parts of a message are present.

        Returns:
            bool : True if the message is complete, False otherwise

        Nr   r   )r6   r7   r8   rT   rU   r5   r?   s    r$   completezMessage.completeI  s^     {$& G}D(G|4'G {}a00C4F4FF	Gr#   Serialized[Content]c                6    t          | j        | j                  S N)r   r8   buffersr?   s    r$   rc   zMessage.payloadV  s    $,555r#   c                    | j         S rs   )r.   r?   s    r$   r6   zMessage.header\  s
    |r#   valuec                "    || _         d | _        d S rs   )r.   r/   r<   rv   s     r$   r6   zMessage.header`  s     r#   c                Z    | j         st          j        | j                  | _         | j         S rs   )r/   rF   r^   r6   r?   s    r$   rA   zMessage.header_jsone  s*      	8 $
4; 7 7D  r#   c                    | j         S rs   )r0   r?   s    r$   r8   zMessage.contentm  s
    }r#   c                "    || _         d | _        d S rs   )r0   r1   rx   s     r$   r8   zMessage.contentq  s    !r#   c                P    | j         st          | j                  | _         | j         S rs   )r1   r   rc   r?   s    r$   rC   zMessage.content_jsonv  s(    ! 	>!/!=!=D!!r#   c                    | j         S rs   )r2   r?   s    r$   r7   zMessage.metadata~  s
    ~r#   c                "    || _         d | _        d S rs   )r2   r3   rx   s     r$   r7   zMessage.metadata  s    "r#   c                Z    | j         st          j        | j                  | _         | j         S rs   )r3   rF   r^   r7   r?   s    r$   rB   zMessage.metadata_json  s*    " 	<"&*T]";";D""r#   c                *    t          | j                  S rs   )listr5   r?   s    r$   rt   zMessage.buffers  s    DM"""r#   )r6   r   r7   r)   r8   r(   r9   r:   )r9   r   )rA   r   rB   r   rC   r   r9   rD   )rL   r   r9   r:   )rP   r&   rQ   rR   r9   r:   )T)rW   r   rX   rY   r9   rZ   rs   )re   rf   r9   r   )rW   r   r9   rZ   )r9   rY   )r9   rq   )r9   r   )rv   r   r9   r:   )r9   r(   )rv   r(   r9   r:   )r9   r)   )rv   r)   r9   r:   )r9   r4   )r   r   r    __doc__r!   r=   r@   classmethodrK   rO   rV   rd   rj   rn   propertyrp   rc   r6   setterrA   r8   rC   r7   rB   rt   r"   r#   r$   r   r   v   s          OOO   .E E E E ' ' ' ['R% % % %,D D D D*    2     [&! ! ! !F 
G 
G 
G X
G 6 6 6 X6
    X ]! ! ! ]! ! ! ! X!    X ^" " " ^" " " " X"    X _# # # _# # # # X# # # # X# # #r#   r   )/r   
__future__r   logging	getLoggerr   logrF   typingr   r   r   r   r   r	   bokeh.util.serializationutilserializationrh   core.json_encoderr   core.serializationr   r   
core.typesr   
exceptionsr   r   typing_extensionsr   r   client.websocketr   __all__r   r&   r(   dictr   r)   r!   tuplerR   r*   r,   r   r"   r#   r$   <module>r      sR  & & &V # " " " " " g!!                 , + + + + + + + + / . . . . . 3 3 3 3 3 3 3 3       3 3 3 3 3 3 3 3 D88888888CCCCCC" " " " "Y " " "    9    ')

38n $ $ $ $\501	 1 1 1 1	 	 	 	 	I 	 	 	[# [# [# [# [#gg [# [# [# [# [#r#   