B
    KLc*                 @   s   d Z ddlmZ ddlZddlmZ ddlmZ ddlmZ dd	lm	Z	 e	
eZd
d ZG dd deZG dd deZG dd deZdd Zdd ZG dd de	eeZG dd deZG dd deZG dd deZdS )a  Base implementation classes.

The public-facing ``Events`` serves as the base class for an event interface;
its public attributes represent different kinds of events.   These attributes
are mirrored onto a ``_Dispatch`` class, which serves as a container for
collections of listener functions.   These collections are represented both
at the class level of a particular ``_Dispatch`` class as well as within
instances of ``_Dispatch``.

    )absolute_importN   )_ClsLevelDispatch)_EmptyListener)_JoinedListener   )utilc             C   s   |  d r| dkp|  dS )N_dispatchZ	_sa_event)
startswith)name r   4lib/python3.7/site-packages/sqlalchemy/event/base.py_is_event_name   s    r   c               @   s   e Zd ZdZdd ZdS )_UnpickleDispatchzSerializable callable that re-generates an instance of
    :class:`_Dispatch` given a particular :class:`.Events` subclass.

    c             C   s8   x2|j D ] }d|jkr|jd j|S qW tdd S )Nr
   z*No class with a 'dispatch' member present.)__mro____dict__r
   
_for_classAttributeError)self_instance_clsclsr   r   r   __call__/   s
    

z_UnpickleDispatch.__call__N)__name__
__module____qualname____doc__r   r   r   r   r   r   )   s   r   c               @   sx   e Zd ZdZdZe ZdddZdd Z	e
dd	 Ze
d
d Zdd Zdd Zdd Zdd ZdddZdd ZdS )	_Dispatcha;  Mirror the event listening definitions of an Events class with
    listener collections.

    Classes which define a "dispatch" member will return a
    non-instantiated :class:`._Dispatch` subclass when the member
    is accessed at the class level.  When the "dispatch" member is
    accessed at the instance level of its owner, an instance
    of the :class:`._Dispatch` class is returned.

    A :class:`._Dispatch` class is generated for each :class:`.Events`
    class defined, by the :func:`._create_dispatcher_class` function.
    The original :class:`.Events` classes remain untouched.
    This decouples the construction of :class:`.Events` subclasses from
    the implementation used by the event internals, and allows
    inspecting tools like Sphinx to work in an unsurprising
    way against the public API.

    )_parentr   r   _empty_listenersNc                sb   || _  | _ rXy| j  | _W q^ tk
rT    fdd|jD  | _| j < Y q^X ni | _d S )Nc                s   i | ]}t | |jqS r   )r   r   ).0ls)instance_clsr   r   
<dictcomp>]   s   z&_Dispatch.__init__.<locals>.<dictcomp>)r   r   _empty_listener_regr   KeyError_event_descriptors)r   parentr"   r   )r"   r   __init__S   s    
z_Dispatch.__init__c             C   sB   y| j | }W n tk
r*   t|Y nX t| |j| |S d S )N)r   r%   r   setattrr   )r   r   r!   r   r   r   __getattr__d   s    z_Dispatch.__getattr__c             c   s    x| j D ]}t| |V  qW d S )N)_event_namesgetattr)r   kr   r   r   r&   o   s    z_Dispatch._event_descriptorsc             C   s   | j jS )N)_events_listen)r   r   r   r   r/   v   s    z_Dispatch._listenc             C   s   |  | |S )N)	__class__)r   r"   r   r   r   r   z   s    z_Dispatch._for_classc             C   s   |j }| |S )N)r0   r   )r   instancer"   r   r   r   _for_instance}   s    z_Dispatch._for_instancec             C   s<   d| j jkr0td| j j tfd| ji}|| j _| | |S )zCreate a 'join' of this :class:`._Dispatch` and another.

        This new dispatcher will dispatch events to both
        :class:`._Dispatch` objects.

        _joined_dispatch_clszJoined%s	__slots__)r0   r   typer   _JoinedDispatcherr+   r3   )r   otherr   r   r   r   _join   s    
z_Dispatch._joinc             C   s   t  | jffS )N)r   r   )r   r   r   r   
__reduce__   s    z_Dispatch.__reduce__Tc             C   s<   x6|j D ],}t|trqt| |j| j||d qW dS )zIPopulate from the listeners in another :class:`_Dispatch`
        object.)only_propagateN)r&   
isinstancer   r,   r   
for_modify_update)r   r7   r:   r!   r   r   r   r=      s
    
z_Dispatch._updatec             C   s"   x| j D ]}||   qW d S )N)r&   r<   clear)r   r!   r   r   r   _clear   s    z_Dispatch._clear)N)T)r   r   r   r   r4   weakrefWeakKeyDictionaryr$   r(   r*   propertyr&   r/   r   r2   r8   r9   r=   r?   r   r   r   r   r   9   s   


r   c               @   s   e Zd ZdZdd ZdS )
_EventMetazKIntercept new Event subclasses and create
    associated _Dispatch classes.c             C   s"   t | ||| t| ||| d S )N)_create_dispatcher_classr5   r(   )r   	classnamebasesdict_r   r   r   r(      s    z_EventMeta.__init__N)r   r   r   r   r(   r   r   r   r   rC      s   rC   c             C   s  t | dr| jj}nt}dd |D }td| |fd|i}||_| | |}x2|jD ](}t||t| ||  t	| 
|  qVW xP|jD ]F}	t|	tr|	tk	rx.|	jjjD ] }
t||
j|
 |j
|
j qW qW t| ddr| j}t |drd|jkrt| | j_nt| | j_dS )	zRCreate a :class:`._Dispatch` class corresponding to an
    :class:`.Events` class.r
   c             S   s   g | ]}t |r|qS r   )r   )r    r-   r   r   r   
<listcomp>   s    z,_create_dispatcher_class.<locals>.<listcomp>z
%sDispatchr4   _dispatch_targetN_slots_dispatch)hasattrr
   r0   r   r5   r+   _set_dispatchr)   r   _registrarsappend	__bases__
issubclassr.   r&   r   r,   rI   r4   slots_dispatcher
dispatcher)r   rE   rF   rG   Zdispatch_baseZevent_namesdispatch_clsZdispatch_instr-   Zsuper_r!   Zthe_clsr   r   r   rD      s,    

rD   c             C   s2   x,| j jD ] }t| |  t| s
t|= q
W d S )N)r
   r+   rM   remove)r   r-   r   r   r   _remove_dispatcher   s    rU   c               @   sN   e Zd ZdZedd Zedd ZedddZed	d
 Z	edd Z
dS )Eventsz>Define event listening functions for a particular target type.c             C   s   |d | _ | |_| j S )N)r
   r.   )r   rS   r   r   r   rL      s    
zEvents._set_dispatchc                sX    fdd} fdd}t  drT|| jjsP|t| jjsP|trT|| jjrT S d S )Nc                 s   t  fdd| D S )Nc             3   s   | ]}t  j|V  qd S )N)r;   r
   )r    t)targetr   r   	<genexpr>   s    z;Events._accept_with.<locals>.dispatch_is.<locals>.<genexpr>)all)types)rX   r   r   dispatch_is   s    z(Events._accept_with.<locals>.dispatch_isc                s   t  jj| S )N)r;   r
   r'   )rW   )rX   r   r   dispatch_parent_is   s    z/Events._accept_with.<locals>.dispatch_parent_isr
   )rK   r
   r0   r5   r6   )r   rX   r\   r]   r   )rX   r   _accept_with   s    
zEvents._accept_withFc             C   s   |j ||||d d S )N)	propagateinsertnamedasyncio)Zbase_listen)r   	event_keyr_   r`   ra   rb   r   r   r   r/      s    	zEvents._listenc             C   s   |   d S )N)rT   )r   rc   r   r   r   _remove  s    zEvents._removec             C   s   | j   d S )N)r
   r?   )r   r   r   r   r?     s    zEvents._clearN)FFFF)r   r   r   r   staticmethodrL   classmethodr^   r/   rd   r?   r   r   r   r   rV      s      rV   c               @   s<   e Zd ZdZdZdd Zdd Zedd Zed	d
 Z	dS )r6   z5Represent a connection between two _Dispatch objects.)localr'   r   c             C   s   || _ || _| j j| _d S )N)rg   r'   r   )r   rg   r'   r   r   r   r(     s    z_JoinedDispatcher.__init__c             C   s.   t | j|}t| j|j|}t| |j| |S )N)r,   rg   r   r'   r   r)   )r   r   r!   Zjlr   r   r   r*      s    z_JoinedDispatcher.__getattr__c             C   s   | j jS )N)r'   r/   )r   r   r   r   r/   (  s    z_JoinedDispatcher._listenc             C   s   | j jS )N)r'   r.   )r   r   r   r   r.   ,  s    z_JoinedDispatcher._eventsN)
r   r   r   r   r4   r(   r*   rB   r/   r.   r   r   r   r   r6     s   r6   c               @   s    e Zd ZdZdd Zdd ZdS )rR   zDescriptor used by target classes to
    deliver the _Dispatch class at the class level
    and produce new _Dispatch instances for target
    instances.

    c             C   s   |j | _ || _d S )N)r
   events)r   rh   r   r   r   r(   9  s    zdispatcher.__init__c          
   C   sh   |d kr| j S | j |}y||jd< W n: tk
rb } ztjtd|f |d W d d }~X Y nX |S )Nr
   zGtarget %r doesn't have __dict__, should it be defining _slots_dispatch?)Zreplace_context)r
   r2   r   r   r   Zraise_	TypeError)r   objr   dispZaer   r   r   __get__=  s    zdispatcher.__get__N)r   r   r   r   r(   rl   r   r   r   r   rR   1  s   rR   c               @   s   e Zd Zdd ZdS )rQ   c             C   s4   |d kr| j S t|dr|jS | j |}||_|S )NrJ   )r
   rK   rJ   r2   )r   rj   r   rk   r   r   r   rl   P  s    
zslots_dispatcher.__get__N)r   r   r   rl   r   r   r   r   rQ   O  s   rQ   )r   Z
__future__r   r@   attrr   r   r    r   defaultdictlistrM   r   objectr   r   r5   rC   rD   rU   Zwith_metaclassrV   r6   rR   rQ   r   r   r   r   <module>   s"   

k	)9