U
    /e2                     @  s  d dl mZ d dlZeeZd dlZd dlZd dlZ	d dl
Z
d dlmZmZmZ d dlmZmZmZ d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlm Z m!Z! d dl"m#Z# d dl$m%Z% d dl&m'Z' d dl(m)Z) d dl*m+Z+ d dl,m-Z- d dl.m/Z/ d dl0m1Z1 d dl2m3Z3 d dl4m5Z5 d dl6m7Z7 d dl8m9Z9 d dl:m;Z; d dl<m=Z=m>Z>m?Z?m@Z@mAZA dZBG dd deZCG dd deeCZDG dd  d eDZEG d!d" d"eDZFG d#d$ d$eeCZGG d%d& d&e1ZHG d'd( d(eIZJdS ))    )annotationsN)AnyDictSet)parse_qsurljoinurlparse)AsyncConsumer)AsyncHttpConsumer)AsyncWebsocketConsumer)locks)IOLoop)AUTOLOAD_JS)Scriptbundle_for_objs_and_resources)script_for_render_items)server_html_page_for_session)
RenderItem)Protocol)Message)Receiver)	Resources)ServerConnection)ApplicationContext)ProtocolHandler)ServerSession)StaticHandler)settings)check_token_signaturegenerate_jwt_tokengenerate_session_idget_session_idget_token_payload)DocConsumerAutoloadJsConsumer
WSConsumerc                   @  sZ   e Zd ZdZeddddZeddddZdd
dddddZddddddZd	S )ConsumerHelper/z
'AttrDict'returnc                 C  s   t | j}| j|d< |S )N	arguments)AttrDictscoper*   )selfrequest r/   A/tmp/pip-unpacked-wheel-f5fndrjf/bokeh/server/django/consumers.pyr.   M   s    

zConsumerHelper.requestzDict[str, str]c                 C  s.   t d| jd   }dd t|j D S )Nz/?Zquery_stringc                 S  s   i | ]\}\}||qS r/   r/   ).0namevaluer/   r/   r0   
<dictcomp>V   s      z,ConsumerHelper.arguments.<locals>.<dictcomp>)r   r,   decoder   queryitems)r-   
parsed_urlr/   r/   r0   r*   S   s    zConsumerHelper.argumentsNstrz
str | None)r2   defaultr)   c                 C  s   | j ||S N)r*   get)r-   r2   r:   r/   r/   r0   get_argumentX   s    zConsumerHelper.get_argumentr   )absolute_urlr)   c                 C  sD   t jdd}|dkr:|r$t|| jn| j}td|tjdS t|dS )Nserverr:   )moderoot_urlZpath_versioner)rA   )r   	resourcesr   _prefixr   r   Zappend_version)r-   r>   rA   rB   r/   r/   r0   rC   [   s
    zConsumerHelper.resources)N)N)	__name__
__module____qualname__rD   propertyr.   r*   r=   rC   r/   r/   r/   r0   r&   I   s   r&   c                      s<   e Zd ZU ded< ddd fddZdd	d
dZ  ZS )SessionConsumerr   application_contextDict[str, Any]Noner,   r)   c                   s@   t  | | jd d }|d | _| jjd kr<t | j_d S )N	url_routekwargsapp_context)super__init__r,   rJ   io_loopr   currentZ_loopr-   r,   rO   	__class__r/   r0   rR   f   s
    
zSessionConsumer.__init__r   r(   c                   sd   | j dtd dd}dd | jjD t| jjd}t|d dd|d}| j	|| j|I d H }|S )	Nzbokeh-session-idF)
secret_keysignedc                 S  s"   i | ]\}}| d | d qS )zutf-8)r5   )r1   kvr/   r/   r0   r4   s   s    z0SessionConsumer._get_session.<locals>.<dictcomp>)headerscookiesi,  )rX   rY   Z
expirationZextra_payload)
r*   r<   r    r.   r\   dictr]   r   rJ   create_session_if_needed)r-   
session_idpayloadtokensessionr/   r/   r0   _get_sessionp   s     

zSessionConsumer._get_session)rE   rF   rG   __annotations__rR   rd   __classcell__r/   r/   rV   r0   rI   b   s   

rI   c                   @  s   e Zd ZdddddZdS )r$   bytesrL   bodyr)   c              	     s   |   I d H }| jdd d}|s(td| jddd}| jdd d}|rZdjt|d}nd }| d	d
}|dkr|| |nd }td |}	t|j|ddg}
|		t
ti |
||d tj|	|d}ddddg}| jd| |dI d H  d S )Nzbokeh-autoload-elementr@   z)No bokeh-autoload-element query parameterzbokeh-app-pathr'   zbokeh-absolute-urlz{uri.scheme}://{uri.netloc}/)urirC   r:   noneF)rb   	elementidZuse_for_title)app_pathr>   )bundlerl   )s   Access-Control-Allow-Headers   *)s   Access-Control-Allow-Methodss   PUT, GET, OPTIONS)s   Access-Control-Allow-Originro   )   Content-Types   application/javascript   r\   )rd   r=   RuntimeErrorformatr   rC   r   r   rb   addr   r   r   rendersend_responseencode)r-   ri   rc   Z
element_idrm   r>   Z
server_urlZresources_paramrC   rn   Zrender_itemsZjsr\   r/   r/   r0   handle   s*    
zAutoloadJsConsumer.handleNrE   rF   rG   ry   r/   r/   r/   r0   r$   ~   s   r$   c                   @  s   e Zd ZdddddZdS )r#   rg   rL   rh   c                   sP   |   I d H }t||  |jj|jj|jjd}| jd| dgdI d H  d S )N)rC   titletemplatetemplate_variablesrq   )rp   s	   text/htmlrr   )	rd   r   rC   documentr{   r|   r}   rw   rx   )r-   ri   rc   pager/   r/   r0   ry      s    zDocConsumer.handleNrz   r/   r/   r/   r0   r#      s   r#   c                      s   e Zd ZU ded< ded< ddd fdd	Zd
d Zdd ZddddZdddddZdddddZ	dddddddd Z
  ZS )!r%   zSet[ServerConnection]_clientsr   rJ   rK   rL   rM   c                   sN   t  | | jd d }|d | _| jjd kr8tdt | _t	 | _
d S )NrN   rO   rP   zio_loop should already been set)rQ   rR   r,   rJ   rS   rs   setr   r   LocklockrU   rV   r/   r0   rR      s    
zWSConsumer.__init__c           	        s  t d | jd }t|dks,|d dkr<|   td|d }|d kr\|   tdttj	
  }t|}d	|kr|   td
nH||d	 kr|   tdn*t|dd dst|}t d| tddd }| |}t|}|| | dI d H  d S )NzWebSocket connection openedsubprotocols   r   Zbokehz!Subprotocol header is not 'bokeh'   z'No token received in subprotocol headerZsession_expiryz$Session expiry has not been providedzToken is expired.F)rY   rX   z*Token for session %r had invalid signaturezInvalid token signaturec                 S  s    |   }|d k	rtd| d S )Nz'Failed to fully open connlocksection %r)	exceptionlogdebug)futureer/   r/   r0   on_fully_opened   s    z+WSConsumer.connect.<locals>.on_fully_opened)r   infor,   lenclosers   calendartimegmdtdatetimeutcnowutctimetupler"   r   r!   error_async_openasyncioZensure_futureZadd_done_callbackaccept)	r-   r   rb   nowra   r`   r   r   Ztaskr/   r/   r0   connect   s:    






zWSConsumer.connectc                   s   | j j  d S r;   )
connectionrc   destroy)r-   Z
close_coder/   r/   r0   
disconnect   s    zWSConsumer.disconnectr(   c                   sH   |}| j |I d H }|rD| j|| jI d H }|rD| |I d H  d S r;   )receiverconsumehandlerry   r   _send_bokeh_message)r-   	text_datafragmentmessageZworkr/   r/   r0   receive   s    zWSConsumer.receiver9   )rb   r)   c              
     s   z~t |}| j|| j|I d H  | j|}t }t|| _t	d| t
 | _t	d| | || | j|| _td W n: tk
r } ztd| |   |W 5 d }~X Y nX | jjd}| |I d H  d S )NzReceiver created for %rzProtocolHandler created for %rzServerConnection createdz/Could not create new server session, reason: %sZACK)r!   rJ   r_   r.   Zget_sessionr   r   r   r   r   r   r   _new_connectionr   r   	Exceptionr   r   protocolcreater   )r-   rb   r`   rc   r   r   msgr/   r/   r0   r      s"    
zWSConsumer._async_openr   int)r   r)   c              
     s   d}z| j 4 I d H  | j|jdI d H  |t|j7 }| j|jdI d H  |t|j7 }| j|jdI d H  |t|j7 }|jD ]F\}}| jt|dI d H  | j|dI d H  |t|t| 7 }qW 5 Q I d H R X W n t	k
r   t
d Y nX |S )Nr   )r   )
bytes_dataz/Failed sending message as connection was closed)r   sendZheader_jsonr   Zmetadata_jsonZcontent_json_buffersjsondumpsr   r   warn)r-   r   sentheaderra   r/   r/   r0   r     s     *zWSConsumer._send_bokeh_messager   r	   r   r   )r   socketrJ   rc   r)   c                 C  s   t ||||}| j| |S r;   )AsyncServerConnectionr   ru   )r-   r   r   rJ   rc   r   r/   r/   r0   r   #  s    zWSConsumer._new_connection)rE   rF   rG   re   rR   r   r   r   r   r   r   rf   r/   r/   rV   r0   r%      s   
,	r%   c                   @  s   e Zd Zdd ZdS )r   c                   s&   | j d|g}| j|I dH  dS )zW Sends a PATCH-DOC message, returning a Future that's completed when it's written out. z	PATCH-DOCN)r   r   _socketr   )r-   eventr   r/   r/   r0   send_patch_document7  s    z)AsyncServerConnection.send_patch_documentN)rE   rF   rG   r   r/   r/   r/   r0   r   5  s   r   c                   @  s   e Zd ZdZdd ZdS )r+   zH Provide a dict subclass that supports access by named attributes.

    c                 C  s   | | S r;   r/   )r-   keyr/   r/   r0   __getattr__A  s    zAttrDict.__getattr__N)rE   rF   rG   __doc__r   r/   r/   r/   r0   r+   <  s   r+   )K
__future__r   logging	getLoggerrE   r   r   r   r   r   r   typingr   r   r   urllib.parser   r   r   Zchannels.consumerr	   Zchannels.generic.httpr
   Zchannels.generic.websocketr   Ztornador   Ztornado.ioloopr   Zbokeh.core.templatesr   Zbokeh.embed.bundler   r   Zbokeh.embed.elementsr   Zbokeh.embed.serverr   Zbokeh.embed.utilr   Zbokeh.protocolr   Zbokeh.protocol.messager   Zbokeh.protocol.receiverr   Zbokeh.resourcesr   Zbokeh.server.connectionr   Zbokeh.server.contextsr   Zbokeh.server.protocol_handlerr   Zbokeh.server.sessionr   Z!bokeh.server.views.static_handlerr   Zbokeh.settingsr   Zbokeh.util.tokenr   r   r    r!   r"   __all__r&   rI   r$   r#   r%   r   r^   r+   r/   r/   r/   r0   <module>   sL   

" 