a
    KDf?.                     @  sF  d Z ddlmZ ddlZeeZddlZddlZddl	m	Z	 ddl
mZ ddlmZmZmZmZmZ ddlmZ erd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	dl"m#Z$ ddlm%Z%m&Z& ddl'm(Z( dZ)edZ*ededef dZ+dddddZ,ddddZ-G d d! d!Z.dS )"z( Provides the ``ServerSession`` class.

    )annotationsN)copywraps)TYPE_CHECKINGAny	AwaitableCallableTypeVar)locks)IOLoop   )ConnectionLost)generate_jwt_token   )DocumentCallbackGroup)ID)Document)DocumentPatchedEvent)messages)CallbackSessionCallback)ServerConnection)current_timeServerSessionTF.)bound)funcreturnc                   s   t  dd fdd}|S )zDecorator that adds the necessary locking and post-processing
       to manipulate the session's document. Expects to decorate a
       method on ServerSession and transforms it into a coroutine
       if it wasn't already.
    r   selfc              	     s   | j rtd d S |   z| j I d H  | jd urBtdg | _z: | g|R i |}t	|rt|I d H }W | j}d | _n| j}d | _0 |D ]}|I d H  qW d    n1 s0    Y  |W | 
  S | 
  0 d S )Nz6Ignoring locked callback on already-destroyed session.zUinternal class invariant violated: _pending_writes should be None if lock is not held)	destroyedlogdebugblock_expiration_lockacquire_pending_writesRuntimeErrorinspectisawaitableunblock_expiration)r!   argskwargsresultZpending_writespr    a/nfs/NAS7/SABIOD/METHODE/ermites/ermites_venv/lib/python3.9/site-packages/bokeh/server/session.py_needs_document_lock_wrapperM   s.    


*z:_needs_document_lock.<locals>._needs_document_lock_wrapperr   )r   r4   r2   r1   r3   _needs_document_lockG   s     r5   floatr   c                   C  s   t  d S )zWReturn the time in milliseconds since the epoch as a floating
       point number.
    i  )time	monotonicr2   r2   r2   r3   r   t   s    r   c                   @  s,  e Zd ZU dZded< ded< ded< 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	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ddd'd(Zddd)d*Zd+dd,d-d.Zd+dd,d/d0Zed dd1d2Zed3dd4d5Zed6d7d7d8d9d:d;Zd<d<d=d>d?Zd@d@d=dAdBZdCddDdEdFZedGd+dHdIdJdKZd@dLdMdNZdOdP ZedGd+dHdIdQdRZedSd+dTdIdUdVZ edSd+dTdIdWdXZ!edYd+dTdIdZd[Z"edYd+dTdId\d]Z#ddd^d_Z$dS )ar   z^ Hosts an application "instance" (an instantiated Document) for one or more connections.

    zset[ServerConnection]_subscribed_connectionszServerConnection | None_current_patch_connectionzlist[Awaitable[None]] | Noner(   Nr   r   zIOLoop | Nonez
str | NoneNone)
session_iddocumentio_looptokenr   c                   s   |d u rt d|d u r t d| _| _| _| _t  _t  _t	
  _d  _ jj  t| _d  _d _d _d _ fdd jjD } j| d S )NzSessions must have an idzSessions must have a documentFr   c                   s   g | ]}  |qS r2   )_wrap_session_callback).0cbr    r2   r3   
<listcomp>       z*ServerSession.__init__.<locals>.<listcomp>)
ValueError_id_token	_documentZ_loopsetr:   r   _last_unsubscribe_timer   Lockr&   r;   	callbacksZon_change_dispatch_tor   
_callbacksr(   
_destroyed_expiration_requested_expiration_blocked_countZsession_callbacksZadd_session_callbacks)r!   r=   r>   r?   r@   Zwrapped_callbacksr2   r    r3   __init__   s(    

zServerSession.__init__r7   c                 C  s   | j S N)rI   r    r2   r2   r3   r>      s    zServerSession.documentc                 C  s   | j S rS   )rG   r    r2   r2   r3   id   s    zServerSession.idstrc                 C  s   | j r| j S t| jS )z* A JWT token to authenticate the session. )rH   r   rT   r    r2   r2   r3   r@      s    zServerSession.tokenboolc                 C  s   | j S rS   )rO   r    r2   r2   r3   r"      s    zServerSession.destroyedc                 C  s   | j S rS   rP   r    r2   r2   r3   expiration_requested   s    z"ServerSession.expiration_requestedc                 C  s
   | j dkS )Nr   rQ   r    r2   r2   r3   expiration_blocked   s    z ServerSession.expiration_blockedintc                 C  s   | j S rS   rY   r    r2   r2   r3   expiration_blocked_count   s    z&ServerSession.expiration_blocked_countc                 C  s(   d| _ | j|  | `| j  | `d S )NT)rO   rI   destroyrN   Zremove_all_callbacksr    r2   r2   r3   r]      s
    
zServerSession.destroyc                 C  s
   d| _ dS )zK Used in test suite for now. Forces immediate expiration if no connections.TNrW   r    r2   r2   r3   request_expiration   s    z ServerSession.request_expirationc                 C  s   |  j d7  _ d S )Nr   rY   r    r2   r2   r3   r%      s    zServerSession.block_expirationc                 C  s$   | j dkrtd|  j d8  _ d S )Nr   z0mismatched block_expiration / unblock_expirationr   )rQ   r)   r    r2   r2   r3   r,      s    
z ServerSession.unblock_expirationr   )
connectionr   c                 C  s   | j | dS )zgThis should only be called by ``ServerConnection.subscribe_session`` or our book-keeping will be brokenN)r:   addr!   r_   r2   r2   r3   	subscribe   s    zServerSession.subscribec                 C  s   | j | t | _dS )ziThis should only be called by ``ServerConnection.unsubscribe_session`` or our book-keeping will be brokenN)r:   discardr   rK   ra   r2   r2   r3   unsubscribe   s    zServerSession.unsubscribec                 C  s
   t | jS rS   )lenr:   r    r2   r2   r3   connection_count   s    zServerSession.connection_countr6   c                 C  s   t  | j S rS   )r   rK   r    r2   r2   r3   #milliseconds_since_last_unsubscribe   s    z1ServerSession.milliseconds_since_last_unsubscribezCallable[..., T]r   r   )r   r-   r.   r   c                 O  s   ||i |S )zH Asynchronously locks the document and runs the function with it locked.r2   )r!   r   r-   r.   r2   r2   r3   with_document_locked   s    z"ServerSession.with_document_lockedr   )callbackr   c                   s*   t  ddr S ddd fdd}|S )NZnolockFr   r-   r.   c                    s   j  g| R i |S rS   )rh   rj   ri   r!   r2   r3   wrapped_callback   s    z?ServerSession._wrap_document_callback.<locals>.wrapped_callback)getattr)r!   ri   rl   r2   rk   r3   _wrap_document_callback   s    z%ServerSession._wrap_document_callbackr   c                 C  s   t |}| |j|_|S rS   )r   rn   ri   Z	_callback)r!   ri   wrappedr2   r2   r3   rA      s    z$ServerSession._wrap_session_callbackr   )eventr   c                 C  sN   |j | u }| jd u rtd| jD ]&}|r6|| ju r6q"| j|| q"d S )Nzv_pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes)setterr(   r)   r:   r;   appendZsend_patch_document)r!   rp   Zmay_suppressr_   r2   r2   r3   _document_patched   s    


zServerSession._document_patchedzmsg.pull_doc_reqzmsg.pull_doc_reply)messager_   r   c                 C  s*   t d| j |jd|jd | jS )Nz$Sending pull-doc-reply from session zPULL-DOC-REPLYmsgid)r#   r$   rT   protocolcreateheaderr>   r!   rt   r_   r2   r2   r3   _handle_pull   s    zServerSession._handle_pull)rp   c                 C  s   |  |j}| j| d S rS   )rA   ri   rN   Zadd_session_callback)r!   rp   ro   r2   r2   r3   _session_callback_added  s    z%ServerSession._session_callback_addedc                 C  s   | j |j d S rS   )rN   Zremove_session_callbackri   )r!   rp   r2   r2   r3   _session_callback_removed  s    z'ServerSession._session_callback_removedc                 C  s   |j ||S )z? Handle a PULL-DOC, return a Future with work to be scheduled. )sessionrz   clsrt   r_   r2   r2   r3   pull
  s    zServerSession.pullzmsg.push_doczmsg.okc                 C  s(   t d| j || j ||S )Nzpushing doc to session )r#   r$   rT   Zpush_to_documentr>   okry   r2   r2   r3   _handle_push  s    zServerSession._handle_pushc                 C  s   |j ||S )z? Handle a PUSH-DOC, return a Future with work to be scheduled. )r}   r   r~   r2   r2   r3   push  s    zServerSession.pushzmsg.patch_docc                 C  s2   || _ z|| j|  W d | _ nd | _ 0 ||S rS   )r;   Zapply_to_documentr>   r   ry   r2   r2   r3   _handle_patch  s
    zServerSession._handle_patchc                 C  s   |j ||S )z@ Handle a PATCH-DOC, return a Future with work to be scheduled. )r}   r   r~   r2   r2   r3   patch$  s    zServerSession.patchc                 C  s   | j jt  dS )z3 Notify the document that the connection was lost. N)r>   rM   Ztrigger_eventr   r    r2   r2   r3   notify_connection_lost)  s    z$ServerSession.notify_connection_lost)NN)%__name__
__module____qualname____doc____annotations__rR   propertyr>   rT   r@   r"   rX   rZ   r\   r]   r^   r%   r,   rb   rd   rf   rg   r5   rh   rn   rA   rs   rz   r{   r|   classmethodr   r   r   r   r   r   r2   r2   r2   r3   r   z   sb   
		r   )/r   
__future__r   logging	getLoggerr   r#   r*   r8   r   	functoolsr   typingr   r   r   r	   r
   Ztornador   Ztornado.ioloopr   eventsr   Z
util.tokenr   rM   r   Z
core.typesr   Zdocument.documentr   Zdocument.eventsr   rv   r   msgr   r   r_   r   __all__r   r   r5   r   r   r2   r2   r2   r3   <module>   s6   
		-