U
    [h&!                     @   s   d Z ddlmZ ddlZddlZddlZddlmZ ddlmZ e	e
Ze	e
Zdd Zd	d
 Zdd Zdd Zdd ZG dd deZdS )aJ  Provides managed registration services on behalf of :func:`.listen`
arguments.

By "managed registration", we mean that event listening functions and
other objects can be added to various collections in such a way that their
membership in all those collections can be revoked at once, based on
an equivalent :class:`._EventKey`.

    )absolute_importN   )exc)utilc                 C   sT   t r| t krd S t | }| D ],}|tkr"t| }||  |s"t| q"d S N)_collection_to_keypopvalues_key_to_collection)reflistener_to_keykeydispatch_reg r   =/tmp/pip-unpacked-wheel-joqu7d3y/sqlalchemy/event/registry.py_collection_gced5   s    

r   c                 C   sH   | j }t| }|j}t| j}||kr,dS |||< t| }|||< dS )NFT)_keyr
   r   weakref
_listen_fnr   )	event_keyownerr   r   	owner_ref
listen_refr   r   r   r   _stored_in_collectionC   s    r   c                 C   sT   | j }t| }t| j}|j}||d  |s6t|= |tkrPt| }|| d S r   )r   r
   r   r   r   r   r   )r   r   r   r   r   r   r   r   r   r   _removed_from_collectionV   s    r   c           	   	   C   s   |sd S |j }| j } t| }t|  }|D ]}t |}z|| }W n tk
rZ   Y q(Y nX zt| }W n tk
r   Y q(Y nX | |kr||  |kstn||| < |||< q(d S r   )r   r   r   KeyErrorr
   AssertionError)	ZnewownerZoldownerelementsZold_listener_to_keyZnew_listener_to_key	listen_fnr   r   r   r   r   r   _stored_in_collection_multig   s(    


r   c                 C   sT   |sd S | j } t|  }|D ]4}t |}|| }t| }|| d  |st|= qd S r   )r   r   r   r
   r   )r   r   r   r   r   r   r   r   r   r   _clear   s    
r    c                   @   s   e Zd ZdZdZdddZedd Zdd	 Zd
d Z	dd Z
dd Zdd ZdddZedd Zdd Zdd Zdd ZdS )	_EventKeyz$Represent :func:`.listen` arguments.)target
identifierfnfn_keyfn_wrapdispatch_targetNc                 C   sP   || _ || _|| _t|tjr6t|jt|jf| _	n
t|| _	|| _
|| _d S r   )r"   r#   r$   
isinstancetypes
MethodTypeid__func____self__r%   r&   r'   )selfr"   r#   r$   r'   _fn_wrapr   r   r   __init__   s    
z_EventKey.__init__c                 C   s   t | j| j| jfS r   )r+   r"   r#   r%   r.   r   r   r   r      s    z_EventKey._keyc                 C   s,   || j kr| S t| j| j| j| j|dS d S N)r/   )r   r!   r"   r#   r$   r'   )r.   r&   r   r   r   with_wrapper   s    
z_EventKey.with_wrapperc                 C   s,   || j kr| S t| j| j| j|| jdS d S r2   )r'   r!   r"   r#   r$   r&   )r.   r'   r   r   r   with_dispatch_target   s    
z_EventKey.with_dispatch_targetc                 O   s   | dd}| dd}| dd}| j| j| j  }}}t|j|}	|	||}
| |
} t| jjj| j}t	|dr|
  |s|r| tj| j|dj|| n| jjj| f|| d S )NonceFZ_once_unless_exceptionnamed_sa_warn)retry_on_exception)r   r'   r#   r   getattrdispatchZ_adjust_fn_specr3   Z_eventshasattrr7   r   Z	only_oncelistenZ_listen)r.   argskwr5   Zonce_unless_exceptionr6   r"   r#   r$   dispatch_collectionZadjusted_fnZstub_functionr   r   r   r<      s6    

 
  z_EventKey.listenc                 C   st   | j }|tkr(td| j| j| jf t|}| D ]4\}}| }| }|d k	r:|d k	r:|	| 
| q:d S )Nz*No listeners found for event %s / %r / %s )r   r
   r   ZInvalidRequestErrorr"   r#   r$   r   itemsremover3   )r.   r   r   Zcollection_refZlistener_refZ
collectionZlistener_fnr   r   r   rA      s    
z_EventKey.removec                 C   s
   | j tkS )z6Return True if this event key is registered to listen.)r   r
   r1   r   r   r   contains   s    z_EventKey.containsFc           
      C   sT   | j | j }}t|j|}||j}	|r2|	  |rD|	| | n|	| | d S r   )r'   r#   r9   r:   
for_modifyZ_set_asyncioinsertappend)
r.   	propagaterD   r6   retvalZasyncior"   r#   r?   rC   r   r   r   base_listen   s    	z_EventKey.base_listenc                 C   s   | j p
| jS r   )r&   r$   r1   r   r   r   r     s    z_EventKey._listen_fnc                 C   s"   t | |r|| j dS dS d S NTF)r   rE   r   r.   r   list_r   r   r   append_to_list  s    
z_EventKey.append_to_listc                 C   s   t | | || j d S r   )r   rA   r   rJ   r   r   r   remove_from_list   s    
z_EventKey.remove_from_listc                 C   s"   t | |r|| j dS dS d S rI   )r   
appendleftr   rJ   r   r   r   prepend_to_list$  s    
z_EventKey.prepend_to_list)N)FFFNF)__name__
__module____qualname____doc__	__slots__r0   propertyr   r3   r4   r<   rA   rB   rH   r   rL   rM   rO   r   r   r   r   r!      s*   	

      

r!   )rS   
__future__r   collectionsr)   r    r   r   defaultdictdictr
   r   r   r   r   r   r    objectr!   r   r   r   r   <module>   s   


 