B
    CVvg…0  ã               @   sô   d Z ddlZddlZddlZddlZddlmZ ddlmZm	Z	 ddl
mZ ddlmZ ddlmZ edd	ƒZG d
d„ deƒZG dd„ deed�Zdd„ ZG dd„ dejƒZG dd„ dƒZG dd„ dƒZd dd„Zdd„ Zdd„ ZG dd„ dƒZdS )!zî
Various data structures used in query construction.

Factored out from django.db.models.query to avoid making the main module very
large and/or so that they can be used by other modules without getting into
circular import difficulties.
é    N)Ú
namedtuple)ÚFieldDoesNotExistÚ
FieldError)Ú
LOOKUP_SEP)Útree)ÚRemovedInDjango40WarningÚPathInfozGfrom_opts to_opts target_fields join_field m2m direct filtered_relationc                   s<   e Zd Zedd„ ƒZdd„ Z‡ fdd„Z‡ fdd„Z‡  ZS )	ÚInvalidQueryTypec             C   s   t tfS )N)r   r   )Úself© r   ú@/tmp/pip-install-o3oxmrkh/Django/django/db/models/query_utils.pyÚ_subclasses   s    zInvalidQueryType._subclassesc             C   s   t jdtdd� d S )Nz\The InvalidQuery exception class is deprecated. Use FieldDoesNotExist or FieldError instead.é   )ÚcategoryÚ
stacklevel)ÚwarningsÚwarnr   )r
   r   r   r   Z__warn   s    zInvalidQueryType.__warnc                s    |   ¡  t|| jƒptƒ  |¡S )N)Ú_InvalidQueryType__warnÚ
isinstancer   ÚsuperÚ__instancecheck__)r
   Úinstance)Ú	__class__r   r   r   &   s    z"InvalidQueryType.__instancecheck__c                s    |   ¡  t|| jƒptƒ  |¡S )N)r   Ú
issubclassr   r   Ú__subclasscheck__)r
   Úsubclass)r   r   r   r   *   s    z"InvalidQueryType.__subclasscheck__)	Ú__name__Ú
__module__Ú__qualname__Úpropertyr   r   r   r   Ú__classcell__r   r   )r   r   r	      s   r	   c               @   s   e Zd ZdS )ÚInvalidQueryN)r   r   r   r   r   r   r   r!   /   s   r!   )Ú	metaclassc             c   s*   | V  x|   ¡ D ]}t|ƒE d H  qW d S )N)Ú__subclasses__Ú
subclasses)Úclsr   r   r   r   r$   3   s    r$   c                   sj   e Zd ZdZdZdZeZdZdddœ‡ fdd	„
Zd
d„ Z	dd„ Z
dd„ Zdd„ Zddd„Zdd„ Z‡  ZS )ÚQze
    Encapsulate filters as objects that can then be combined logically (using
    `&` and `|`).
    ÚANDÚORTNF)Ú
_connectorÚ_negatedc               s"   t ƒ j|t| ¡ ƒ•||d� d S )N)ÚchildrenÚ	connectorÚnegated)r   Ú__init__ÚsortedÚitems)r
   r)   r*   ÚargsÚkwargs)r   r   r   r.   D   s    z
Q.__init__c             C   s˜   t |tƒs"t|ddƒdks"t|ƒ‚| sBt|dƒr8| ¡ S t |¡S t |tƒrl|sl|  ¡ \}}}t| ƒ||ŽS t| ƒƒ }||_| 	| |¡ | 	||¡ |S )NÚconditionalFTÚcopy)
r   r&   ÚgetattrÚ	TypeErrorÚhasattrr4   ÚdeconstructÚtyper,   Úadd)r
   ÚotherÚconnÚ_r1   r2   Úobjr   r   r   Ú_combineG   s    
z
Q._combinec             C   s   |   || j¡S )N)r?   r(   )r
   r;   r   r   r   Ú__or__W   s    zQ.__or__c             C   s   |   || j¡S )N)r?   r'   )r
   r;   r   r   r   Ú__and__Z   s    z	Q.__and__c             C   s$   t | ƒƒ }| | | j¡ | ¡  |S )N)r9   r:   r'   Únegate)r
   r>   r   r   r   Ú
__invert__]   s    
zQ.__invert__c             C   s&   |j | ||ddd�\}}| |¡ |S )NF)Úallow_joinsZ
split_subqZcheck_filterable)Z_add_qZpromote_joins)r
   ÚqueryrD   ÚreuseZ	summarizeZfor_saveZclauseZjoinsr   r   r   Úresolve_expressionc   s
    
zQ.resolve_expressionc             C   sf   d| j j| j jf }| d¡r*| dd¡}t| jƒ}i }| j| jkrN| j|d< | j	r\d|d< |||fS )Nz%s.%szdjango.db.models.query_utilszdjango.db.modelsr)   Tr*   )
r   r   r   Ú
startswithÚreplaceÚtupler+   r,   Údefaultr-   )r
   Úpathr1   r2   r   r   r   r8   m   s    


zQ.deconstruct)NTNFF)r   r   r   Ú__doc__r'   r(   rK   r3   r.   r?   r@   rA   rC   rG   r8   r    r   r   )r   r   r&   9   s   

r&   c               @   s*   e Zd ZdZdd„ Zd	dd„Zdd„ ZdS )
ÚDeferredAttributez„
    A wrapper for a deferred-loading field. When the value is read from this
    object the first time, the query is executed.
    c             C   s
   || _ d S )N)Úfield)r
   rO   r   r   r   r.      s    zDeferredAttribute.__init__Nc             C   sT   |dkr| S |j }| jj}||krL|  |¡}|dkrD|j|gd� n|||< || S )zx
        Retrieve and caches the value from the datastore on the first lookup.
        Return the cached value.
        N)Úfields)Ú__dict__rO   ÚattnameÚ_check_parent_chainZrefresh_from_db)r
   r   r%   ÚdataÚ
field_nameÚvalr   r   r   Ú__get__‚   s    
zDeferredAttribute.__get__c             C   s6   |j }| | jj¡}| jjr2| j|kr2t||jƒS dS )zÁ
        Check if the field value can be fetched from a parent field already
        loaded in the instance. This can be done if the to-be fetched
        field is a primary key field.
        N)Ú_metaZget_ancestor_linkrO   ÚmodelÚprimary_keyr5   rR   )r
   r   ÚoptsZ
link_fieldr   r   r   rS   •   s
    z%DeferredAttribute._check_parent_chain)N)r   r   r   rM   r.   rW   rS   r   r   r   r   rN   z   s   
rN   c               @   st   e Zd Zedd„ ƒZeejdd�dd„ ƒƒZdd„ Zd	d
„ Z	e
dd„ ƒZedd„ ƒZeddd„ƒZeddd„ƒZdS )ÚRegisterLookupMixinc             C   s   |   ¡  |d ¡S )N)Úget_lookupsÚget)r%   Úlookup_namer   r   r   Ú_get_lookup¤   s    zRegisterLookupMixin._get_lookupN)Úmaxsizec             C   s   dd„ t  | ¡D ƒ}|  |¡S )Nc             S   s   g | ]}|j  d i ¡‘qS )Úclass_lookups)rQ   r^   )Ú.0Úparentr   r   r   ú
<listcomp>«   s    z3RegisterLookupMixin.get_lookups.<locals>.<listcomp>)ÚinspectÚgetmroÚmerge_dicts)r%   rb   r   r   r   r]   ¨   s    zRegisterLookupMixin.get_lookupsc             C   sN   ddl m} |  |¡}|d kr4t| dƒr4| j |¡S |d k	rJt||ƒsJd S |S )Nr   )ÚLookupÚoutput_field)Údjango.db.models.lookupsri   r`   r7   rj   Ú
get_lookupr   )r
   r_   ri   Úfoundr   r   r   rl   ®   s    
zRegisterLookupMixin.get_lookupc             C   sN   ddl m} |  |¡}|d kr4t| dƒr4| j |¡S |d k	rJt||ƒsJd S |S )Nr   )Ú	Transformrj   )rk   rn   r`   r7   rj   Úget_transformr   )r
   r_   rn   rm   r   r   r   ro   ·   s    
z!RegisterLookupMixin.get_transformc             C   s$   i }xt | ƒD ]}| |¡ qW |S )z«
        Merge dicts in reverse to preference the order of the original list. e.g.,
        merge_dicts([a, b]) will preference the keys in 'a' over those in 'b'.
        )ÚreversedÚupdate)ZdictsZmergedÚdr   r   r   rh   À   s    zRegisterLookupMixin.merge_dictsc             C   s    xt | ƒD ]}|j ¡  q
W d S )N)r$   r]   Úcache_clear)r%   r   r   r   r   Ú_clear_cached_lookupsË   s    z)RegisterLookupMixin._clear_cached_lookupsc             C   s4   |d kr|j }d| jkri | _|| j|< |  ¡  |S )Nrb   )r_   rQ   rb   rt   )r%   Úlookupr_   r   r   r   Úregister_lookupÐ   s    

z#RegisterLookupMixin.register_lookupc             C   s   |dkr|j }| j|= dS )zn
        Remove given lookup from cls lookups. For use in tests only as it's
        not thread-safe.
        N)r_   rb   )r%   ru   r_   r   r   r   Ú_unregister_lookupÚ   s    z&RegisterLookupMixin._unregister_lookup)N)N)r   r   r   Úclassmethodr`   Ú	functoolsÚ	lru_cacher]   rl   ro   Ústaticmethodrh   rt   rv   rw   r   r   r   r   r\   ¢   s   			r\   Fc             C   sŽ   | j s
dS | j jr|sdS |rD|r2|  ¡ |kr2dS |sD| j|krDdS |sR| jrRdS |rŠ| j|krŠ|rŠ| j|krŠd| jjj| jf }t	|ƒ‚dS )au  
    Return True if this field should be used to descend deeper for
    select_related() purposes. Used by both the query construction code
    (sql.query.fill_related_selections()) and the model instance creation code
    (query.get_klass_info()).

    Arguments:
     * field - the field to be checked
     * restricted - a boolean field, indicating if the field list has been
       manually restricted using a requested clause)
     * requested - The select_related() dictionary.
     * load_fields - the set of fields to be loaded on this model
     * reverse - boolean, True if we are checking a reverse select related
    FzXField %s.%s cannot be both deferred and traversed using select_related at the same time.T)
Zremote_fieldZparent_linkZrelated_query_nameÚnameÚnullrR   rY   rX   Zobject_namer   )rO   Z
restrictedÚ	requestedZload_fieldsÚreverseÚmsgr   r   r   Úselect_related_descendå   s$    

r�   c             C   sV   xPt dt| ƒd ƒD ]:}t | d|… ¡}||kr|| r|| | |d… fS qW dS )zÕ
    Check if the lookup_parts contains references to the given annotations set.
    Because the LOOKUP_SEP is contained in the default annotation names, check
    each prefix of the lookup_parts for a match.
    é   r   N)Fr   )ÚrangeÚlenr   Újoin)Zlookup_partsÚannotationsÚnZlevel_n_lookupr   r   r   Úrefs_expression
  s
    rˆ   c                s,   ‡ fdd„}||ƒp*t |ddƒo*||jjƒS )zÞ
    Check that self.model is compatible with target_opts. Compatibility
    is OK if:
      1) model and opts match (where proxy inheritance is removed)
      2) model is parent of opts' model or the other way around
    c                s*   ˆ j j| jkp(| jˆ j  ¡ kp(ˆ |  ¡ kS )N)rX   Zconcrete_modelZget_parent_list)r[   )rY   r   r   Úcheck  s    z-check_rel_lookup_compatibility.<locals>.checkrZ   F)r5   rY   rX   )rY   Ztarget_optsrO   r‰   r   )rY   r   Úcheck_rel_lookup_compatibility  s    rŠ   c               @   s@   e Zd ZdZeƒ dœdd„Zdd„ Zdd„ Zd	d
„ Zdd„ Z	dS )ÚFilteredRelationz7Specify custom filtering in the ON clause of SQL joins.)Ú	conditionc            C   s:   |st dƒ‚|| _d | _t|tƒs*t dƒ‚|| _g | _d S )Nzrelation_name cannot be empty.z*condition argument must be a Q() instance.)Ú
ValueErrorÚrelation_nameÚaliasr   r&   rŒ   rL   )r
   rŽ   rŒ   r   r   r   r.   6  s    
zFilteredRelation.__init__c             C   s4   t || jƒstS | j|jko2| j|jko2| j|jkS )N)r   r   ÚNotImplementedrŽ   r�   rŒ   )r
   r;   r   r   r   Ú__eq__@  s
    zFilteredRelation.__eq__c             C   s,   t | j| jd�}| j|_| jd d … |_|S )N)rŒ   )r‹   rŽ   rŒ   r�   rL   )r
   Úcloner   r   r   r’   I  s    zFilteredRelation.clonec             O   s   t dƒ‚dS )zz
        QuerySet.annotate() only accepts expression-like arguments
        (with a resolve_expression() method).
        z0FilteredRelation.resolve_expression() is unused.N)ÚNotImplementedError)r
   r1   r2   r   r   r   rG   O  s    z#FilteredRelation.resolve_expressionc             C   s&   |j }|j| jt| jƒd�}| |¡S )N)rF   )rE   Zbuild_filtered_relation_qrŒ   ÚsetrL   Úcompile)r
   ÚcompilerÚ
connectionrE   Úwherer   r   r   Úas_sqlV  s    zFilteredRelation.as_sqlN)
r   r   r   rM   r&   r.   r‘   r’   rG   r™   r   r   r   r   r‹   3  s   
	r‹   )F)rM   r4   ry   rf   r   Úcollectionsr   Zdjango.core.exceptionsr   r   Zdjango.db.models.constantsr   Zdjango.utilsr   Zdjango.utils.deprecationr   r   r9   r	   Ú	Exceptionr!   r$   ÚNoder&   rN   r\   r�   rˆ   rŠ   r‹   r   r   r   r   Ú<module>   s(   
A(C
%