B
    \w7                 @   s   d Z ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlm	Z
 dd	lmZ d
dlmZ d
dlmZ d
dlm	Z	 ejejjddG dd dejZG dd dejZG dd deZG dd deeZdd ZG dd deZdS )zDynamic collection API.

Dynamic collections act like Query() objects for read operations and support
basic add/delete mutation.

   )
attributes)exc)object_mapper)object_session)
properties)
strategies)util)Query   )logdynamic)Zlazyc               @   s   e Zd Zdd ZdS )
DynaLoaderc          	   C   sF   d| _ | jstd| j tj| j|dt| jj| jj	| jj
d d S )NTztOn relationship %s, 'dynamic' loaders cannot be used with many-to-one/one-to-one relationships and/or uselist=False.)Z	useobjectZ
impl_classtarget_mapperorder_byquery_class)Zis_class_levelZuselistr   ZInvalidRequestErrorZparent_propertyr   Z_register_attributeDynamicAttributeImplmapperr   r   )selfr    r   5lib/python3.7/site-packages/sqlalchemy/orm/dynamic.pyinit_class_attribute   s    
zDynaLoader.init_class_attributeN)__name__
__module____qualname__r   r   r   r   r   r      s   r   c                   s  e Zd ZdZdZdZdZdZd& fdd	Ze	j
fddZde	jfdd	Zejd
d Zejdd Zd'ddZd(ddZdd Zde	j
dddfddZdd Zdd Ze	j
fddZe	jfddZe	j
fddZe	j
fd d!Ze	j
fd"d#Ze	j
fd$d%Z  ZS ))r   TFNc       	         sT   t t| j||||f| || _|| _|s2t| _nt| krF|| _n
t	|| _d S )N)
superr   __init__r   r   AppenderQueryr   AppenderMixinmromixin_user_query)	r   Zclass_keyZtypecallabledispatchr   r   r   kw)	__class__r   r   r   9   s    
zDynamicAttributeImpl.__init__c             C   s*   |t j@ s| |t jjS | | |S d S )N)r   SQL_OK_get_collection_historyPASSIVE_NO_INITIALIZEadded_itemsr   )r   statedict_passiver   r   r   getP   s    
zDynamicAttributeImpl.getc             C   s.   |t j@ s| ||jS | ||}|jS d S )N)r   r$   r%   r'   added_plus_unchanged)r   r(   r)   Z	user_datar*   historyr   r   r   get_collectionX   s    
z#DynamicAttributeImpl.get_collectionc             C   s   t | t jS )N)r   EventZ	OP_APPEND)r   r   r   r   _append_tokene   s    z"DynamicAttributeImpl._append_tokenc             C   s   t | t jS )N)r   r/   Z	OP_REMOVE)r   r   r   r   _remove_tokeni   s    z"DynamicAttributeImpl._remove_tokenc             C   sh   |d kr|  ||}|| x"| jjD ]}||||p:| j}q(W | jrd|d k	rd| t||d d S )NT)	_modified_event	add_addedr!   appendr0   trackparentsethasparentr   instance_state)r   r(   r)   value	initiatorcollection_historyfnr   r   r   fire_append_eventm   s    
z&DynamicAttributeImpl.fire_append_eventc             C   sh   |d kr|  ||}|| | jr@|d k	r@| t||d x"| jjD ]}||||p\| j qJW d S )NF)	r2   add_removedr5   r6   r   r7   r!   remover1   )r   r(   r)   r8   r9   r:   r;   r   r   r   fire_remove_event{   s    
z&DynamicAttributeImpl.fire_remove_eventc             C   sD   | j |jkrt| ||j| j < ||| tj d|| j < |j| j  S )NT)r    committed_stateCollectionHistoryr2   r   Z	NEVER_SET)r   r(   r)   r   r   r   r2      s
    
z$DynamicAttributeImpl._modified_eventc	             C   s   |r|j | j krd S |r$|d kr$d S |}	t|	}
|jrHt| ||}| ||}|jsb|j}n||j}tj}|	|
}||

|}|
|}x(|
D ] }||kr| j|||d |d qW x |D ]}| j|||d |d qW d S )N)r:   )Zparent_tokenlisthas_identityr   ZIdentitySetr+   r2   r'   unionintersection
differencer<   r?   )r   r(   r)   r8   r9   r*   Z	check_oldpopZ_adaptiterableZ
new_valuesZold_collectionr:   ZidsetZ	constantsZ	additionsZremovalsmemberr   r   r   set   s@    



zDynamicAttributeImpl.setc             O   s
   t  d S )N)NotImplementedError)r   argskwargsr   r   r   delete   s    zDynamicAttributeImpl.deletec             C   s   t dd S )Nz7Dynamic attributes don't support collection population.)rK   )r   r(   r)   r8   r   r   r   set_committed_value   s    z(DynamicAttributeImpl.set_committed_valuec             C   s   |  ||}| S )N)r%   
as_history)r   r(   r)   r*   cr   r   r   get_history   s    z DynamicAttributeImpl.get_historyc             C   s   |  ||}dd |jD S )Nc             S   s   g | ]}t ||fqS r   )r   r7   ).0xr   r   r   
<listcomp>   s    z8DynamicAttributeImpl.get_all_pending.<locals>.<listcomp>)r%   	all_items)r   r(   r)   r*   rQ   r   r   r   get_all_pending   s    z$DynamicAttributeImpl.get_all_pendingc             C   sJ   | j |jkr|j| j  }n
t| |}|jrB|tj@ rBt| ||dS |S d S )N)apply_to)r    r@   rA   rC   r   ZINIT_OK)r   r(   r*   rQ   r   r   r   r%      s    
z,DynamicAttributeImpl._get_collection_historyc             C   s   || k	r|  |||| d S )N)r<   )r   r(   r)   r8   r9   r*   r   r   r   r4      s    zDynamicAttributeImpl.appendc             C   s   || k	r|  |||| d S )N)r?   )r   r(   r)   r8   r9   r*   r   r   r   r>      s    zDynamicAttributeImpl.removec             C   s   | j |||||d d S )N)r*   )r>   )r   r(   r)   r8   r9   r*   r   r   r   rG      s    zDynamicAttributeImpl.pop)N)N)N)r   r   r   Zuses_objectsZdefault_accepts_scalar_loaderZsupports_populationZ
collectionr   r   r   ZPASSIVE_OFFr+   r&   r.   r   Zmemoized_propertyr0   r1   r<   r?   r2   rJ   rN   rO   rR   rW   r%   r4   r>   rG   __classcell__r   r   )r#   r   r   2   s6   


-r   c                   sp   e Zd ZdZ fddZdd Zeedd Zdd	 Zd
d Zdd Z	dddZ
dd Zdd Zdd Z  ZS )r   Nc                s~   t t| |jd  |  | _}|| _t|}|j| jj	 }|j
d k	rX|jj|j
f| _|j|dd| _| jjrz| jj| _d S )NF)Zalias_secondary)r   r   r   r   objinstanceattrr   Z_propsr    Z	secondaryr   Z
selectable	_from_objZ_with_parent
_criterionr   	_order_by)r   r\   r(   r[   r   Zprop)r#   r   r   r      s    
zAppenderMixin.__init__c             C   sH   t | j}|d k	r0| jr0|jr0| j|kr0|  t| js@d S |S d S )N)r   r[   	autoflushflushorm_utilrC   )r   sessr   r   r   session  s    

zAppenderMixin.sessionc             C   s   d S )Nr   )srT   r   r   r   <lambda>!  s    zAppenderMixin.<lambda>c             C   s>   | j }|d kr,t| jt| jtjjS t| 	|S d S )N)
rd   iterr\   r%   r   r7   r[   r&   r'   _clone)r   rc   r   r   r   __iter__#  s    
zAppenderMixin.__iter__c             C   s@   | j }|d kr,| jt| jtj|S | |	|S d S )N)
rd   r\   r%   r   r7   r[   r&   indexedrh   __getitem__)r   indexrc   r   r   r   rk   /  s    
zAppenderMixin.__getitem__c             C   s>   | j }|d kr,t| jt| jtjjS | 	|
 S d S )N)rd   lenr\   r%   r   r7   r[   r&   r'   rh   count)r   rc   r   r   r   rn   9  s    
zAppenderMixin.countc             C   s~   | j }|d kr:t|}|d kr:tdt|| jjf | jrT| j| jj	|d}n|
| jj	}| j|_| j|_| j|_|S )NzParent instance %s is not bound to a Session, and no contextual session is established; lazy load operation of attribute '%s' cannot proceed)rd   )r[   r   orm_excZDetachedInstanceErrorrb   Zinstance_strr\   r    r   r   queryr^   r]   r_   )r   rc   r[   rp   r   r   r   rh   E  s    zAppenderMixin._clonec             C   s4   x.|D ]&}| j t| jt| j|d  qW d S )N)r\   r4   r   r7   r[   instance_dict)r   iteratoritemr   r   r   extend_  s    


zAppenderMixin.extendc             C   s&   | j t| jt| j|d  d S )N)r\   r4   r   r7   r[   rq   )r   rs   r   r   r   r4   h  s
    

zAppenderMixin.appendc             C   s&   | j t| jt| j|d  d S )N)r\   r>   r   r7   r[   rq   )r   rs   r   r   r   r>   p  s
    

zAppenderMixin.remove)N)r   r   r   r   r   rd   propertyri   rk   rn   rh   rt   r4   r>   rY   r   r   )r#   r   r      s   

	r   c               @   s   e Zd ZdZdS )r   zBA dynamic query that supports basic collection storage operations.N)r   r   r   __doc__r   r   r   r   r   y  s   r   c             C   s   d| j  }t|t| fd| iS )zAReturn a new class with AppenderQuery functionality layered over.ZAppenderr   )r   typer   )clsnamer   r   r   r   }  s    
r   c               @   sR   e Zd ZdZdddZedd Zedd Zd	d
 Zdd Z	dd Z
dd ZdS )rA   zDOverrides AttributeHistory to receive append/remove events directly.Nc             C   s`   |r8t ||d}t|| _|j| _|j| _d| _n$t | _t | _t | _d| _d S )NFT)r   r`   r   ZOrderedIdentitySetunchanged_itemsr'   deleted_items_reconcile_collection)r   r\   r(   rX   Zcollr   r   r   r     s    


zCollectionHistory.__init__c             C   s   t | j| jS )N)rB   r'   rD   rz   )r   r   r   r   r,     s    z&CollectionHistory.added_plus_unchangedc             C   s   t | j| j| jS )N)rB   r'   rD   rz   r{   )r   r   r   r   rV     s    zCollectionHistory.all_itemsc             C   s`   | j r0| j| j}| j| j}| j|}n| j| j| j  }}}tt|t|t|S )N)	r|   r'   rF   rz   r{   rE   r   ZHistoryrB   )r   ZaddedZdeletedZ	unchangedr   r   r   rP     s    zCollectionHistory.as_historyc             C   s   t | j| S )N)rB   r'   )r   rl   r   r   r   rj     s    zCollectionHistory.indexedc             C   s   | j | d S )N)r'   add)r   r8   r   r   r   r3     s    zCollectionHistory.add_addedc             C   s(   || j kr| j | n| j| d S )N)r'   r>   r{   r}   )r   r8   r   r   r   r=     s    
zCollectionHistory.add_removed)N)r   r   r   rv   r   ru   r,   rV   rP   rj   r3   r=   r   r   r   r   rA     s   
rA   N)rv    r   r   ro   r   r   r   r   r   rb   rp   r	   r   Zclass_loggerZRelationshipPropertyZstrategy_forZAbstractRelationshipLoaderr   ZAttributeImplr   objectr   r   r   rA   r   r   r   r   <module>   s(    I