U
    /e7                     @  s"  d Z ddlmZ ddlZeeZddlZddlm	Z	m
Z
mZmZmZmZmZ ddlmZ e	rvd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  e	rddlm!Z! ddl"m#Z# ddlm$Z$ dZ%G dd deZ&G dd deZ'G dd dZ(G dd dZ)dS )zA Provides the Application, Server, and Session context classes.

    )annotationsN)TYPE_CHECKINGAny	AwaitableCallableDictIterableList)gen)HTTPServerRequest)IOLoop   )ServerContextSessionContext)Document)ProtocolError)get_token_payload   )ServerSession)Application)ID)TokenPayload)ApplicationContextBokehServerContextBokehSessionContextc                   @  s@   e Zd ZdddddZedddd	Zed
dddZdS )r   r   None)application_contextreturnc                 C  s   t || _d S N)weakrefref_application_context)selfr    r#   9/tmp/pip-unpacked-wheel-f5fndrjf/bokeh/server/contexts.py__init__M   s    zBokehServerContext.__init__zApplicationContext | Noner   c                 C  s   |   S r   )r!   r"   r#   r#   r$   r   P   s    z&BokehServerContext.application_contextzList[ServerSession]c                 C  s(   g }| j }|r$|jD ]}|| q|S r   )r   sessionsappend)r"   resultcontextsessionr#   r#   r$   r(   T   s    
zBokehServerContext.sessionsN)__name__
__module____qualname__r%   propertyr   r(   r#   r#   r#   r$   r   L   s
   r   c                      s   e Zd ZU ded< ded< ded< d$dd	d
ddd fddZdddddZdddddZeddddZeddddZ	eddddZ
eddd d!Zeddd"d#Z  ZS )%r   zServerSession | None_sessionz_RequestProxy | None_request
str | None_tokenNr   r   r   r   )
session_idserver_contextdocument
logout_urlr   c                   s0   || _ d | _|| _t || d | _d | _d S r   )	_documentr1   _logout_urlsuperr%   r2   r4   )r"   r5   r6   r7   r8   	__class__r#   r$   r%   c   s    zBokehSessionContext.__init__r   r,   r   c                 C  s
   || _ d S r   r1   )r"   r,   r#   r#   r$   _set_sessionm   s    z BokehSessionContext._set_sessionz%Callable[[Document], Awaitable[None]])funcr   c                   s6   | j d kr|| jI d H  n| j || jI d H  d S r   )r1   r9   with_document_locked)r"   rA   r#   r#   r$   with_locked_documentp   s    
z(BokehSessionContext.with_locked_documentboolr&   c                 C  s   | j d krdS | j jS d S )NF)r1   	destroyedr'   r#   r#   r$   rE   x   s    
zBokehSessionContext.destroyedc                 C  s   | j S r   )r:   r'   r#   r#   r$   r8      s    zBokehSessionContext.logout_urlc                 C  s   | j S r   )r2   r'   r#   r#   r$   request   s    zBokehSessionContext.requestr   c                 C  s   | j d k	stt| j S r   )r4   AssertionErrorr   r'   r#   r#   r$   token_payload   s    z!BokehSessionContext.token_payloadc                 C  s   | j S r   r?   r'   r#   r#   r$   r,      s    zBokehSessionContext.session)N)r-   r.   r/   __annotations__r%   r@   rC   r0   rE   r8   rF   rH   r,   __classcell__r#   r#   r<   r$   r   ]   s"   
 
r   c                   @  s  e Zd ZU dZded< ded< ded< ded	< d3dddddddZeddddZeddddZeddddZ	eddddZ
eddddZddddZddd d!Zd4d"d#dd$d%d&d'Zd"d$d(d)d*Zd$d+dd,d-d.Zd/dd0d1d2Zd
S )5r   a    Server-side holder for ``bokeh.application.Application`` plus any associated data.
        This holds data that's global to all sessions, while ``ServerSession`` holds
        data specific to an "instance" of the application.

    .. autoclasstoc::

    zDict[ID, ServerSession]	_sessionsz#Dict[ID, gen.Future[ServerSession]]_pending_sessionszDict[ID, SessionContext]_session_contextsr   _server_contextNr   zIOLoop | Noner3   )applicationio_loopurlr8   c                 C  s8   || _ || _i | _i | _i | _t| | _|| _|| _d S r   )	_application_looprK   rL   rM   r   rN   _urlr:   )r"   rO   rP   rQ   r8   r#   r#   r$   r%      s    
zApplicationContext.__init__r&   c                 C  s   | j S r   )rS   r'   r#   r#   r$   rP      s    zApplicationContext.io_loopc                 C  s   | j S r   )rR   r'   r#   r#   r$   rO      s    zApplicationContext.applicationc                 C  s   | j S r   )rT   r'   r#   r#   r$   rQ      s    zApplicationContext.urlc                 C  s   | j S r   )rN   r'   r#   r#   r$   r6      s    z!ApplicationContext.server_contextzIterable[ServerSession]c                 C  s
   | j  S r   )rK   valuesr'   r#   r#   r$   r(      s    zApplicationContext.sessionsr   c              
   C  sN   z| j | j W n6 tk
rH } ztjd|dd W 5 d }~X Y nX d S )NzError in server loaded hook Texc_info)rR   Zon_server_loadedr6   	Exceptionlogerrorr"   er#   r#   r$   run_load_hook   s    z ApplicationContext.run_load_hookc              
   C  sN   z| j | j W n6 tk
rH } ztjd|dd W 5 d }~X Y nX d S )NzError in server unloaded hook TrV   )rR   Zon_server_unloadedr6   rX   rY   rZ   r[   r#   r#   r$   run_unload_hook   s    z"ApplicationContext.run_unload_hookr   zHTTPServerRequest | Noner   )r5   rF   tokenr   c           
   
     s  t |dkrtd|| jkrx|| jkrxt  }| j|< t }t|| j|| j	d}|d k	r|rlt
|ni }d|krd|krd|d krddd	 |d  D |d d< t||d|dd
|_||_t||_z| j|I d H  W n4 tk
r( } ztjd|dd W 5 d }~X Y nX | j| t||| j|d}	| j|= |	| j|< ||	 || j|< ||	 || jkr| j| I d H }	n
| j| }	|	S )Nr   zSession ID must not be empty)r8   cookiesheadersCookiez; c                 S  s   g | ]\}}| d | qS )=r#   .0kvr#   r#   r$   
<listcomp>   s    z?ApplicationContext.create_session_if_needed.<locals>.<listcomp>)r`   ra   z'Failed to run session creation hooks %rTrV   )rP   r_   )lenr   rK   rL   r
   ZFuturer   r   r6   r:   r   joinitems_RequestProxygetr2   r4   r   r    Z_session_contextrR   Zon_session_createdrX   rY   rZ   Zinitialize_documentr   rS   r@   rM   Z
set_result)
r"   r5   rF   r_   futuredocsession_contextpayloadr\   r,   r#   r#   r$   create_session_if_needed   sR    


"




z+ApplicationContext.create_session_if_needed)r5   r   c                 C  s(   || j kr| j | }|S td| d S )NzNo such session )rK   r   )r"   r5   r,   r#   r#   r$   get_session  s    

zApplicationContext.get_sessionzCallable[[ServerSession], bool])r,   should_discardr   c              
     s   j dkrtdtdjj  jj }dd fdd}|I d H  |jrz j	
|I d H  W n2 tk
r } ztjd|d	d
 W 5 d }~X Y nX d S )Nr   z8Should not be discarding a session with open connectionsz5Discarding session %r last in use %r milliseconds agor   r&   c                     s\   rDj dkrD   jj=  jj= tdjd ntdjd d S )Nr   zSession z was successfully discardedz/ was scheduled to discard but came back to life)Zexpiration_blocked_countdestroyrK   idrM   rY   tracewarningr#   r"   r,   rt   r#   r$   
do_discard  s    

z7ApplicationContext._discard_session.<locals>.do_discardz&Failed to run session destroy hooks %rTrV   )connection_countRuntimeErrorrY   debugrv   #milliseconds_since_last_unsubscriberM   rB   rE   rR   Zon_session_destroyedrX   rZ   )r"   r,   rt   rp   rz   r\   r#   ry   r$   _discard_session  s    
"z#ApplicationContext._discard_sessionint)"unused_session_linger_millisecondsr   c                   s   ddd fdd}g }| j  D ]}||r"|js"|| q"t|dkr^tdt|  |D ]$}||rb|jsb| ||I d H  qbd S )Nr   rD   r>   c                   s   | j dko| j kp| jS )Nr   )r{   r~   Zexpiration_requested)r,   r   r#   r$   should_discard_ignoring_block1  s    

zKApplicationContext._cleanup_sessions.<locals>.should_discard_ignoring_blockr   z!Scheduling %s sessions to discard)rK   rU   Zexpiration_blockedr)   ri   rY   r}   r   )r"   r   r   Z
to_discardr,   r#   r   r$   _cleanup_sessions0  s    z$ApplicationContext._cleanup_sessions)NNN)NN)r-   r.   r/   __doc__rI   r%   r0   rP   rO   rQ   r6   r(   r]   r^   rr   rs   r   r   r#   r#   r#   r$   r      s6   
      <"r   c                      s   e Zd ZU ded< ded< ded< ddd	d
ddddZeddddZeddddZeddddZddd fddZ	  Z
S )rl   zDict[str, List[bytes]]
_argumentszDict[str, str]_cookieszDict[str, str | List[str]]_headersNr   zDict[str, str] | Nonez!Dict[str, str | List[str]] | Noner   )rF   r`   ra   r   c                 C  s   || _ t|j}d|kr|d= || _|d k	r4|| _n(t|drVdd |j D | _ni | _|d k	rl|| _nt|drt|j	| _ni | _d S )Nzbokeh-session-idr`   c                 S  s&   i | ]\}}|t |tr|n|jqS r#   )
isinstancestrvaluerd   r#   r#   r$   
<dictcomp>Z  s      z*_RequestProxy.__init__.<locals>.<dictcomp>ra   )
r2   dict	argumentsr   r   hasattrr`   rk   r   ra   )r"   rF   r`   ra   r   r#   r#   r$   r%   N  s    


z_RequestProxy.__init__r&   c                 C  s   | j S r   )r   r'   r#   r#   r$   r   e  s    z_RequestProxy.argumentsc                 C  s   | j S r   )r   r'   r#   r#   r$   r`   i  s    z_RequestProxy.cookiesc                 C  s   | j S r   )r   r'   r#   r#   r$   ra   m  s    z_RequestProxy.headersr   r   )namer   c                   s0   | ds$t| j|d }|d k	r$|S t |S )N_)
startswithgetattrr2   r;   __getattr__)r"   r   valr<   r#   r$   r   q  s
    
z_RequestProxy.__getattr__)NN)r-   r.   r/   rI   r%   r0   r   r`   ra   r   rJ   r#   r#   r<   r$   rl   H  s   
  rl   )*r   
__future__r   logging	getLoggerr-   rY   r   typingr   r   r   r   r   r   r	   Ztornador
   Ztornado.httputilr   Ztornado.ioloopr   Zapplication.applicationr   r   r7   r   Zprotocol.exceptionsr   Z
util.tokenr   r,   r   r   Z
core.typesr   r   __all__r   r   r   rl   r#   r#   r#   r$   <module>   s0   
$5 7