U
    /e;                     @  s  d Z ddlmZ ddlZee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mZmZ ddlmZmZ dd	lmZ dd
lmZmZmZmZ ddlmZ ddl m!Z! ddlm"Z"m#Z#m$Z$m%Z% ddl&m'Z' er,ddl(m)Z) ddl*m+Z+ ddlm,Z, ddl-m.Z. ddl/m0Z0 ddlm1Z1m2Z2m3Z3 dZ4eg df Z5edef Z6eegdf Z7eegdf Z8G dd dZ9ddddddZ:d d!dd"d#d$Z;dd%d%dd&d'Z<dS )(zX Encapulate the management of Document callbacks with a
DocumentCallbackManager class.

    )annotationsN)defaultdictwraps)TYPE_CHECKINGAnyCallableDictListSetType   )
HoldPolicyHoldPolicyType)Unknown)_CONCRETE_EVENT_CLASSESDocumentEventEvent
ModelEvent)Model)_check_callback   )DocumentPatchedEventModelChangedEventSessionCallbackAddedSessionCallbackRemoved)UnlockedDocumentProxy)SessionDestroyedCallback)Setter)	EventJson)SessionCallback)Document)DocumentChangeCallbackDocumentChangedEventInvoker)DocumentCallbackManagerinvoke_with_curdoc.c                
   @  s  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Zded< ded< ddddZeddddZed
dddZ	e	j
d
dd d!dZ	d"d#d$d"d%d&d'Zddd(d)Zdgd+dd,d-d.Zeddd/d0Zdhd1d2d3d3d4d5d6dd7d8d9Zd1d:d;dd<d=d>Zd?dd d@dAZdBddCdDdEZdFdGddHdIdJZd2dKddLdMdNZdOdd dPdQZdBdd dRdSZd2dKddTdUdVZd"ddWdXdYZd2d1ddZd[d\Zd]dd^d_d`ZdaddbdcddZdddedfZdS )ir%   z Manage and provide access to all of the models that belong to a Bokeh
    Document.

    The set of "all models" means specifically all the models reachable from
    references form a Document's roots.

    zweakref.ReferenceType[Document]	_documentz!Dict[Any, DocumentChangeCallback]_change_callbackszDict[str, List[EventCallback]]_event_callbacksz Dict[str, List[MessageCallback]]_message_callbackszSet[SessionDestroyedCallback]_session_destroyed_callbackszSet[SessionCallback]_session_callbacksz,Dict[str, Set[weakref.ReferenceType[Model]]]_subscribed_modelsNzHoldPolicyType | None_holdList[DocumentChangedEvent]_held_eventsr!   )documentc                 C  s^   t || _i | _tt| _tt| _t | _	t | _
tt| _d| _g | _| d| j dS )z

        Args:
            document (Document): A Document to manage models for
                A weak reference to the Document will be retained

        NZbokeh_event)weakrefrefr'   r(   r   listr)   r*   setr+   r,   r-   r.   r0   
on_messagetrigger_json_event)selfr1    r9   </tmp/pip-unpacked-wheel-f5fndrjf/bokeh/document/callbacks.py__init__k   s    


z DocumentCallbackManager.__init__zList[SessionCallback]returnc                 C  s
   t | jS )zA A list of all the session callbacks for this document.

        )r4   r,   r8   r9   r9   r:   session_callbacks   s    z)DocumentCallbackManager.session_callbacksc                 C  s   | j S )zN A list of all the on_session_destroyed callbacks for this document.

        r+   r>   r9   r9   r:   session_destroyed_callbacks   s    z3DocumentCallbackManager.session_destroyed_callbacksNone)	callbacksr=   c                 C  s
   || _ d S Nr@   )r8   rC   r9   r9   r:   rA      s    r    Callbackbool)callback_objcallbackone_shotr=   c                   sp     }|dkrtd|r@t dd fdd}|}n }t||_j t| S )a   Internal implementation for adding session callbacks.

        Args:
            callback_obj (SessionCallback) :
                A session callback object that wraps a callable and is
                passed to ``trigger_on_change``.

            callback (callable) :
                A callable to execute when session events happen.

            one_shot (bool) :
                Whether the callback should immediately auto-remove itself
                after one execution.

        Returns:
            SessionCallback : passed in as ``callback_obj``.

        Raises:
            ValueError, if the callback has been previously added

        Nz@Attempting to add session callback to already-destroyed DocumentrB   r<   c                     s   j kr   S rD   )r,   remove_session_callbackr9   rH   rG   r8   r9   r:   remove_then_invoke   s    

zHDocumentCallbackManager.add_session_callback.<locals>.remove_then_invoke)	r'   RuntimeErrorr   _wrap_with_curdocZ	_callbackr,   addtrigger_on_changer   )r8   rG   rH   rI   docrL   Zactual_callbackr9   rK   r:   add_session_callback   s    z,DocumentCallbackManager.add_session_callbackc                 C  s.   | j   | ` | j  | `| j  | `dS )z6 Clean up references to the Documents models

        N)r(   clearr)   r*   r>   r9   r9   r:   destroy   s    


zDocumentCallbackManager.destroycombiner   )policyr=   c                 C  sR   | j d k	r2| j |kr2td| j  d| d d S |tkrHtd| || _ d S )Nzhold already active with 'z', ignoring ''zUnknown hold policy )r.   logwarningr   
ValueError)r8   rV   r9   r9   r:   hold   s    zDocumentCallbackManager.holdc                 C  s   | j S rD   )r.   r>   r9   r9   r:   
hold_value   s    z"DocumentCallbackManager.hold_valuer   strr   zDocumentPatchedEvent | NonezSetter | NonezInvoker | None)modelattroldnewhintsettercallback_invokerr=   c              
   C  sp   |   }|dkrdS |dkr,|j||| |dkrF|||}	nd}	t||||||	|||	}
| |
 dS )z* Called by Model when it changes

        Nname)r'   modelsZupdate_namelookupZserializable_valuer   rP   )r8   r^   r_   r`   ra   rb   rc   rd   rQ   Zserializable_neweventr9   r9   r:   notify_change   s    z%DocumentCallbackManager.notify_changer   r$   )r^   rh   rd   r=   c                 C  s"   |   }|dkrdS t|| dS z


        N)r'   r&   )r8   r^   rh   rd   rQ   r9   r9   r:   notify_event   s    z$DocumentCallbackManager.notify_eventr"   c                 G  s.   |D ]$}|| j krqt|d || j |< qdS )zm Provide callbacks to invoke if the document or any Model reachable
        from its roots changes.

        rh   N)r(   r   r8   rC   rH   r9   r9   r:   	on_change   s
    

z!DocumentCallbackManager.on_changer   )receiverr=   c                   s     | j kr fdd| j  < d S )Nc                   s
   |   S rD   )dispatchrl   ro   r9   r:   <lambda>      z?DocumentCallbackManager.on_change_dispatch_to.<locals>.<lambda>r(   )r8   ro   r9   rq   r:   on_change_dispatch_to  s    
z-DocumentCallbackManager.on_change_dispatch_tozstr | Type[Event]EventCallback)rh   rC   r=   c                 G  sr   t |tst|tr|j}|tkr0td| tt| tsFtd|D ]}t|ddd qJ| j	| 
| dS )zD Provide callbacks to invoke if a bokeh event is received.

        zUnknown event zDocument.on_event may only be used to subscribe to events of type DocumentEvent. To subscribe to a ModelEvent use the Model.on_event method.rl   zEvent callback)whatN)
isinstancer]   
issubclassr   
event_namer   rZ   r   r   r)   extend)r8   rh   rC   rH   r9   r9   r:   on_event	  s    z DocumentCallbackManager.on_eventMessageCallback)msg_typerC   r=   c                 G  s   | j | | d S rD   )r*   r{   )r8   r~   rC   r9   r9   r:   r6     s    z"DocumentCallbackManager.on_messager   c                 G  s$   |D ]}t |d | j| qdS )za Provide callbacks to invoke when the session serving the Document
        is destroyed

        )Zsession_contextN)r   r+   rO   rm   r9   r9   r:   on_session_destroyed   s    
z,DocumentCallbackManager.on_session_destroyedc                 G  s   |D ]}| j |= qdS )z Remove a callback added earlier with ``on_change``.

        Raises:
            KeyError, if the callback was never added

        Nrt   rm   r9   r9   r:   remove_on_change)  s    z(DocumentCallbackManager.remove_on_change)r~   rH   r=   c                 C  s,   | j |d}|dk	r(||kr(|| dS rj   )r*   getremove)r8   r~   rH   Zmessage_callbacksr9   r9   r:   remove_on_message3  s    z)DocumentCallbackManager.remove_on_message)rG   r=   c                 C  sf   z|g}| j | W n tk
r2   tdY nX |  }|dkrHdS |D ]}| t|| qLdS )z Remove a callback added earlier with ``add_periodic_callback``,
        ``add_timeout_callback``, or ``add_next_tick_callback``.

        Returns:
            None

        Raises:
            KeyError, if the callback was never added

        zDcallback already ran or was already removed, cannot be removed againN)r,   r   KeyErrorrZ   r'   rP   r   )r8   rG   Zcallback_objsrQ   r9   r9   r:   rJ   ;  s    z/DocumentCallbackManager.remove_session_callback)keyr^   r=   c                 C  s   | j | t| d S rD   )r-   rO   r2   r3   )r8   r   r^   r9   r9   r:   	subscribeT  s    z!DocumentCallbackManager.subscriber   )jsonr=   c                 C  s   zt |}W n" tk
r0   td|  Y nX t|trj| j|j 	 }|D ]}| }|rP|
| qP| j|jg D ]}|| qzd S )NzCould not decode event json: %s)r   Zdecode_jsonrZ   rX   rY   rx   r   r-   rz   copyZ_trigger_eventr)   r   )r8   r   rh   Z
subscribedZ	model_refr^   cbr9   r9   r:   r7   W  s    
z*DocumentCallbackManager.trigger_json_eventr#   )rh   r=   c                   s     }|d krd S jdkr.j  d S jdkrHt j d S  jd k	r^t| j dd fdd}t|| d S )NZcollectrU   rB   r<   c                    s   j  D ]} |   q
d S rD   )r(   values)r   rh   r8   r9   r:   invoke_callbacksw  s    zCDocumentCallbackManager.trigger_on_change.<locals>.invoke_callbacks)r'   r.   r0   append_combine_document_eventsrd   r&   )r8   rh   rQ   r   r9   r   r:   rP   h  s    


z)DocumentCallbackManager.trigger_on_changec                 C  s<   | j dkrdS d| _ t| j}g | _|D ]}| | q(dS )zo Turn off any active document hold and apply any collected events.

        Returns:
            None

        N)r.   r4   r0   rP   )r8   eventsrh   r9   r9   r:   unhold|  s    

zDocumentCallbackManager.unhold)rU   )NNN)__name__
__module____qualname____doc____annotations__r.   r;   propertyr?   rA   rc   rR   rT   r[   r\   ri   rk   rn   ru   r|   r6   r   r   r   rJ   r   r7   rP   r   r9   r9   r9   r:   r%   U   sN   
,     	
r%   r!   zCallable[[], None]rB   )rQ   fr=   c              
   C  sJ   ddl m} t|ddr t| n| }|| | W  5 Q R  S Q R X d S )Nr   )patch_curdocZnolockF)Zio.docr   getattrr   )rQ   r   r   Zcurdocr9   r9   r:   r&     s    
r&   r#   r/   )	new_event
old_eventsr=   c                 C  s,   t |D ]}|| r dS q||  dS )a   Attempt to combine a new event with a list of previous events.

    The ``old_event`` will be scanned in reverse, and ``.combine(new_event)``
    will be called on each. If a combination can be made, the function
    will return immediately. Otherwise, ``new_event`` will be appended to
    ``old_events``.

    Args:
        new_event (DocumentChangedEvent) :
            The new event to attempt to combine

        old_events (list[DocumentChangedEvent])
            A list of previous events to attempt to combine new_event with

            **This is an "out" parameter**. The values it contains will be
            modified in-place.

    Returns:
        None

    N)reversedrU   r   )r   r   rh   r9   r9   r:   r     s    
r   zCallable[..., Any]c                   s$   t dddd fdd}|S )Nr   rB   )argskwargsr=   c                    s(   t dd fdd}t|S )Nr   r<   c                     s
    S rD   r9   r9   )r   r   r   r9   r:   invoke  s    z2_wrap_with_curdoc.<locals>.wrapper.<locals>.invoke)r   r&   )r   r   r   rQ   r   )r   r   r:   wrapper  s    z"_wrap_with_curdoc.<locals>.wrapperr   )rQ   r   r   r9   r   r:   rN     s    rN   )=r   
__future__r   logging	getLoggerr   rX   r2   collectionsr   	functoolsr   typingr   r   r   r	   r
   r   r   Z
core.enumsr   r   Z
core.typesr   r   r   r   r   r   r^   r   Zutil.callback_managerr   r   r   r   r   Zlockingr   Zapplication.applicationr   Zcore.has_propsr   r   Zserver.callbacksr    r1   r!   r"   r#   r$   __all__rE   Z
Originatorr}   rv   r%   r&   r   rN   r9   r9   r9   r:   <module>   s@   
$  ?