U
    Lk7gL                     @   s   d dl mZ d dlZd dlmZmZ d dlmZ d dlm	Z	 d dl
mZ d dlmZ dZd	Zd
ZdZdZee e e Zdd ZdddZdddZdd Zdd Zdd ZdS )    )defaultdictN)SONObjectId)DBRef)UPDATE_OPERATORS)_import_class)InvalidQueryError)queryupdateSTRING_OPERATORS)negtgteltlteinninmodallsizeexistsnot	elemMatchtype)within_distancewithin_spherical_distance
within_boxwithin_polygonnearnear_spheremax_distancemin_distance
geo_withingeo_within_boxgeo_within_polygongeo_within_centergeo_within_spheregeo_intersects)containsZ	icontains
startswithZistartswithendswithZ	iendswithexactZiexactregexZiregexZ	wholewordZ
iwholeword)matchc                 C   sL   |   D ]>\}}||kr"|||< q||krt|| tr|| | qdS )z(Combine a raw query with an existing oneN)items
isinstancedictr
   )valuemongo_queryopv r5   B/tmp/pip-unpacked-wheel-n1etwkgt/mongoengine/queryset/transform.pyhandle_raw_queryA   s
    
r7   c                    s  i }t t}t| D ]\}}|dkr6t|| q|d}dd t|D }dd |D }d}t|dkr|d tkr|	 }t|dkr|d d	kr|	  d
}	t|dkr|d dkr|	  d}	| rVz| 
|}
W n, tk
r } zt|W 5 d}~X Y nX g }td}td}g }|
D ]n}d}t|trN|| d
}n8t||rz|
d |krz|d|j  n||j |r*|| q*|d }dddddddg}|t7 }||kr|||}t||r|r|d }n"|dkrt|tst|||}t||rVt|tr:|d  d7  < nt|trV|d  d7  < |r
|tkrtt|||}n|dkrtd}td}t|trt||rt|j|rt|jjf|}n|||}d|i}n.|tkrtd|  n|tkr
d| |i}|	rd|i}|D ]\}}||| qd  |}||krR|||< qt|| trt|tr|| !| || }d!|ksd"|krd#|ksd$|krt" }| D ]*\ } d!ks d"krڐq|| < qd
}d%D ]`}t|#|trt"|| ||< d!|kr.|d! || d!< d"|krH|d" || d"< d}q|sd!|krl|d! |d!< d"|kr|d" |d"< |||< q|| | q| D ]f\ }|  |   | = t|tr fd&d|D }d'|$ kr |d' %| n||d'< q|S )(z;Transform a query from Django-style format to Mongo format.__raw____c                 S   s    g | ]\}}|  r||fqS r5   isdigit).0ipr5   r5   r6   
<listcomp>U   s      zquery.<locals>.<listcomp>c                 S   s   g | ]}|  s|qS r5   r:   )r<   partr5   r5   r6   r?   V   s      N    Fr   TCachedReferenceFieldGenericReferenceFieldz%s._idr   r   r   r   r   Z_id)r   r   r   r   z._refz	._ref.$id)r-   r   	ListFieldEmbeddedDocumentFieldz
$elemMatchz+Custom method "%s" has not been implemented$z$not.$maxDistance$minDistance$near$nearSphere)rL   rM   c                    s   g | ]} |iqS r5   r5   )r<   valkr5   r6   r?      s     z$and)&r   listsortedr.   r7   rsplit	enumeratelenMATCH_OPERATORSpop_lookup_field	Exceptionr   r   r/   strappenddb_fieldr   prepare_query_valuer0   _prepare_query_for_iterabler   r   GEO_OPERATORS_geo_operatorfieldr	   Zdocument_typeCUSTOM_OPERATORSNotImplementedErrorinsertjoinr
   r   getkeysextend)_doc_clskwargsr2   Zmerge_querykeyr1   partsindicesr3   negatefieldserD   rE   cleaned_fieldsra   append_fieldZsingular_opsrF   rG   r=   r@   Z
value_dictZ	value_sonr4   Znear_embeddedZnear_opr5   rO   r6   r	   K   s    


















r	   c                    s  i }|  D ]\}}|dkr*t|| q|d}t|dk rX|d tkrX|dd d|d tkr|dddd	d
dd}dkr| }|d}t|dkrn4t|dkr|d tkr| }|d dkr| }| rz| 	|}W n, t
k
r" }	 zt|	W 5 d}	~	X Y nX g }g }
d}|D ]p d}t trf dkrVd |  d}n| j |r4d}|
  t dr4|
 j d}q4|r|
d  n|
d  td}t |r܈ |}dkr* js|dk	r|dkrt|tst |}n |}ndkr\t|tttfr\ fdd|D }ndkr jsx|dk	r |}ndkr fdd|D }nxd krt|tttfr؇ fd!d|D }n js|dk	r |}n&d"krd}nd	kr |}|r4d| }||i}d#|}dkrd#|krdkrdtd$d%d |
D }|  td&}td'}||ks||kr||kr|}n|}t|
|| }d#|d| }||d }|d| |  |D ]}||i}qnȈd
kr0t|tr0|d(|ii}nd)kr|d  rd#|dd }t|d }t|tttfs~|g}|||d*i}n<dkrdt|tttfs|g}|d(|ii}n||i}n||i}d }||kr|||< q||krt|| tr||  | q|S )+zKTransform an update spec from Django-style format to Mongo
    format.
    r8   r9      r   setNpushAllpullAllincaddToSetsetOnInsert)Zpush_allZpull_alldecZ
add_to_setZset_on_insertrz   rA   rB   rC   FTSrH   ra   GeoJsonBaseFieldpull)r   r   pushc                    s   g | ]}  |qS r5   r]   r<   r4   ra   r3   r5   r6   r?   S  s     zupdate.<locals>.<listcomp>)Nrt   r   )ru   rv   c                    s   g | ]}  |qS r5   r   r   r   r5   r6   r?   X  s     )rx   ry   c                    s   g | ]}  |qS r5   r   r   r   r5   r6   r?   [  s     ZunsetrI   z4pullAll operations only support a single field depthc                 S   s   g | ]
}|j qS r5   )	__class__)r<   cr5   r5   r6   r?   s  s     rF   EmbeddedDocumentListField$each)r   ru   )r   z	$position)!r.   r7   splitrU   r   rd   rW   rf   COMPARISON_OPERATORSrX   rY   r   r/   rZ   r[   r\   hasattrra   r   Zto_mongorequiredr0   r^   r]   rQ   tuplert   re   reverseindexr;   intr
   )ri   r
   Zmongo_updaterk   r1   rl   Zoperator_mapr-   ro   rp   rq   Zappended_sub_fieldrr   r}   Zfield_classesrF   r   Z_check_fieldZlast_listFieldpositionr5   r   r6   r
      s    





















r
   c                 C   sx  |dkrd|i}n`|dkr(d|i}nL| j tjkr|dkrJdd|ii}nr|dkr`dd	|ii}n\|d
krvdd|ii}nF|dkrd|i}n4|dkrd|i}n"|dkrdd|ii}ntd| n|dkrdt|i}n|dkrdd|ii}n|dkrdd|ii}nr|dkrdd|ii}nZ|dkr2dd	|ii}nB|dkrJdt|i}n*|dkrbdt|i}ntd|| j|S )z1Helper to return the query for a given geo query.r    rJ   r!   rK   r   z$withinz$centerr   z$centerSpherer   z$polygonr   rL   r   rM   r   z$boxz<Geo method "%s" has not been implemented for a GeoPointFieldr"   z
$geoWithinr#   r$   r%   r&   r'   z$geoIntersectsz2Geo method "{}" has not been implemented for a {} )Z
_geo_indexpymongoZGEO2Drc   _infer_geometryformat_name)ra   r3   r1   r5   r5   r6   r`     sR    






 r`   c              	   C   s   t | tr8d| kr| S d| kr.d| kr.d| iS tdnt | ttfrz | d d d  dd| diW S  ttfk
r~   Y nX z| d d  dd| diW S  ttfk
r   Y nX z| d  dd	| diW S  ttfk
r   Y nX td
dS )zQHelper method that tries to infer the $geometry shape for a
    given value.
    z	$geometrycoordinatesr   zBInvalid $geometry dictionary should have type and coordinates keysr   ZPolygon)r   r   Z
LineStringZPointzUInvalid $geometry data. Can be either a dictionary or (nested) lists of coordinate(s)N)r/   r0   r   rQ   rt   	TypeError
IndexError)r1   r5   r5   r6   r     s6    
r   c                    s@   t d}t||rtdt|ds,td fdd|D S )NBaseDocumentzWhen using the `in`, `nin`, `all`, or `near`-operators you can't use a `Document`, you must wrap your object in a list (object -> [object]).__iter__zYThe `in`, `nin`, `all`, or `near`-operators must be applied to an iterable (e.g. a list).c                    s   g | ]}  |qS r5   r   r   r   r5   r6   r?     s     z/_prepare_query_for_iterable.<locals>.<listcomp>)r   r/   r   r   )ra   r3   r1   r   r5   r   r6   r^     s    

r^   )N)N)collectionsr   r   Zbsonr   r   Z
bson.dbrefr   Zmongoengine.baser   Zmongoengine.commonr   Zmongoengine.errorsr   __all__r   r_   r   rb   rV   r7   r	   r
   r`   r   r^   r5   r5   r5   r6   <module>   s*   

 $
 8/'