U
    Lk7g                     @   s   d dl Z d dlZd dlZd dlmZ d dlZd dlmZmZm	Z	m
Z
 d dlmZ d dlmZ d dlmZmZmZmZmZ d dlmZ d dlmZ d d	lmZmZmZmZmZ d d
lm Z  dZ!dZ"z
ej#Z#W n e$k
r   dZ#Y nX G dd dZ%dS )    N)partial)SONDBRefObjectId	json_util)signals)get_document)BaseDictBaseListEmbeddedDocumentListLazyReference
StrictDict)ComplexBaseField_import_class)FieldDoesNotExistInvalidDocumentErrorLookUpErrorOperationErrorValidationError)LEGACY_JSON_OPTIONS)BaseDocumentNON_FIELD_ERRORS__all__c                       s  e Zd ZdZdZdZdZdd Z fddZ fdd	Z	d
d Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# ZdQd%d&ZdRd'd(Zd)d* ZedSd+d,Zd-d. Zd/d0 Zd1d2 Zed3d4 Z ed5d6 Z!d7d8 Z"d9d: Z#ed;d< Z$edTd=d>Z%ed?d@ Z&edAdB Z'edUdDdEZ(edVdFdGZ)edHdI Z*edWdKdLZ+dMdN Z,dOdP Z-  Z.S )Xr   )_changed_fields_initialised_created_data_dynamic_fieldsZ_auto_id_field_db_field_map__weakref__FTc                 O   s  d| _ d| _|rtd|dd}|dd}tjj| j| |d | js| j	
dds\|rt| tt| j dd	d
dg  }|rd| d| j d}t|| jr| jstj| jd | _ni | _t | _| jD ]&}||krqt| |d}t| || qd
|kr| j| _i }	td}
| D ]|\}}| j
|}|sL|dkr|rx|dk	rx|rxt||
sx||}t| || n| jr||	|< n
|| j|< q(|   | jrd| _ |	 D ]\}}t| || qd| _ || _tj!j| j| d dS )a   
        Initialise a document or an embedded document.

        :param values: A dictionary of keys and values for the document.
            It may contain additional reserved keywords, e.g. "__auto_convert".
        :param __auto_convert: If True, supplied values will be converted
            to Python-type values via each field's `to_python` method.
        :param _created: Indicates whether this is a brand new document
            or whether it's already been persisted before. Defaults to true.
        FTzuInstantiating a document with positional arguments is not supported. Please use `field_name=value` keyword arguments.__auto_convertr   )documentvaluesstrictidpk_cls_text_scorezThe fields "z " do not exist on the document "")Zallowed_keysN	FileField)r%   r&   r'   )r"   )"r   r   	TypeErrorpopr   Zpre_initsend	__class___dynamic_metagetsetkeyslist_fields_class_namer   STRICTr   create_fields_orderedr   r   r   getattrsetattrr'   r   items
isinstance	to_python _BaseDocument__set_field_display_dynamic_lockZ	post_init)selfargsr#   Z_BaseDocument__auto_convertr   Z_undefined_fieldsmsg
field_namevalueZdynamic_datar*   keyfield rH   =/tmp/pip-unpacked-wheel-n1etwkgt/mongoengine/base/document.py__init__A   s^    



zBaseDocument.__init__c                    sL   |d }|| j kr:| j | j}t|r,| }t| || nt j|| dS )zHandle deletions of fieldsr   N)r5   defaultcallabler;   super__delattr__)rA   rB   kwargsrD   rK   r.   rH   rI   rN      s    
zBaseDocument.__delattr__c                    s`  | j r| js|| jkrT|dsTtd}||dd}||_|| j|< |  j|f7  _|dsj| ||}|| jkr|| j|< t	| dr| 
| z
| j}W n tk
r   d}Y nX | jr|s|| jdt kr| j||krd| }t|z
| j}W n tk
r   d}Y nX | jrN|rN|rN|| jd	krNt d
d t || d S )N_DynamicFieldT)db_fieldnullr   Z	shard_keyz,Shard Keys are immutable. Tried to update %sFid_fieldr   )r/   r@   r9   
startswithr   namer   $_BaseDocument__expand_dynamic_valuesr   hasattr_mark_as_changedr   AttributeError_is_documentr0   r1   tupler   r   rM   __setattr__)rA   rW   rE   rR   rG   Zself__createdrC   Zself__initialisedrP   rH   rI   r^      sR    









zBaseDocument.__setattr__c                 C   s6   i }dD ]}t | |rt| |||< q|  |d< |S )N)r   r   r   r   r9   r   )rY   r:   to_mongo)rA   datakrH   rH   rI   __getstate__   s    
zBaseDocument.__getstate__c                 C   s   t |d tr$| j|d j|d< dD ]}||kr(t| |||  q(d|krp| jr`|d | _nt| j}|| _|	dp~t }|
 D ]}t| ||d 	| qd S )Nr   )r   r   r   r   r   r9   r   )r=   r   r.   	_from_sonr   r;   r/   r9   typer1   r3   )rA   r`   ra   Z_super_fields_orderedZdynamic_fieldsrH   rH   rI   __setstate__   s    
zBaseDocument.__setstate__c                 C   s
   t | jS N)iterr9   rA   rH   rH   rI   __iter__   s    zBaseDocument.__iter__c                 C   s<   z|| j krt| |W S W n tk
r.   Y nX t|dS )zADictionary-style field access, return a field's value if present.N)r9   r:   r[   KeyError)rA   rW   rH   rH   rI   __getitem__   s    
zBaseDocument.__getitem__c                 C   s$   | j s|| jkrt|t| ||S )z3Dictionary-style field access, set a field's value.)r/   r5   rj   r;   )rA   rW   rE   rH   rH   rI   __setitem__  s    zBaseDocument.__setitem__c                 C   s0   zt | |}|d k	W S  tk
r*   Y dS X d S )NF)r:   r[   )rA   rW   valrH   rH   rI   __contains__  s
    

zBaseDocument.__contains__c                 C   s
   t | jS rf   )lenr   rh   rH   rH   rI   __len__  s    zBaseDocument.__len__c              	   C   sX   z|   }W n ttfk
r(   d}Y nX |d kr6tnt|}|d| jj d| dS )Nz[Bad Unicode data]<z: >)__str__UnicodeEncodeErrorUnicodeDecodeErrorstrrd   r.   __name__)rA   uZ	repr_typerH   rH   rI   __repr__  s    
zBaseDocument.__repr__c                 C   s   t | dr|  S d| jj S )N__unicode__z	%s object)rY   rz   r.   rw   rh   rH   rH   rI   rs     s    
zBaseDocument.__str__c                 C   sf   t || jr,t|dr,|jd k	r,| j|jkS t |trP|  |jkoN| j|jkS | jd krb| |kS dS )Nr%   F)r=   r.   rY   r%   r   _get_collection_name
collectionrA   otherrH   rH   rI   __eq__#  s    


zBaseDocument.__eq__c                 C   s   |  | S rf   )r   r}   rH   rH   rI   __ne__2  s    zBaseDocument.__ne__c                 C   s   dS )aI  
        Hook for doing document level data cleaning (usually validation or assignment)
        before validation is run.

        Any ValidationError raised by this method will not be associated with
        a particular field; it will have a special-case association with the
        field defined by NON_FIELD_ERRORS.
        NrH   rh   rH   rH   rI   clean5  s    	zBaseDocument.cleanc                 C   s   d| j krtd| j d S )z0
        Get text score from text query
        r(   ziThis document is not originally built from a text query (or text_score was not set on search_text() call))r   r   rh   rH   rH   rI   get_text_score@  s
    
zBaseDocument.get_text_scoreNc                    sD  |pg }t  }d|d< | j|d< dd |D }| D ]}|rD||krDq2| j|d}| j|}|dkrx| jrx| j|}|dk	r|jjj	}i }	|rd|krd|   fdd	|D }
|
|	d< d
|kr||	d
< |j|f|	}|dkr|j
r| }|| j|< |dk	s
|jr2|r|||j< q2|||j< q2| jds@|d |S )z@
        Return as SON data ready for use with MongoDB.
        N_idr'   c                 S   s   h | ]}| d d qS ).r   )split.0frH   rH   rI   	<setcomp>W  s     z(BaseDocument.to_mongo.<locals>.<setcomp>fields%s.c                    s"   g | ]}|  r| d qS ) )rV   replace)r   irF   rH   rI   
<listcomp>h  s    
 z)BaseDocument.to_mongo.<locals>.<listcomp>use_db_fieldallow_inheritance)r   r6   r   r1   r5   r/   r   r_   __code__co_varnames	_auto_gengeneraterT   rS   rW   r0   r,   )rA   r   r   r`   Zroot_fieldsrD   rE   rG   Zf_inputsZex_varsZembedded_fieldsrH   r   rI   r_   L  sD    




zBaseDocument.to_mongoc                    s  i }|r@z    W n* tk
r> } z||t< W 5 d}~X Y nX  fdd jD }td}td}|D ]\}}|dk	rz,t|||fr|j||d n
|| W nd tk
r } z|jp|||j< W 5 d}~X Y n4 t	t
tfk
r
 } z|||j< W 5 d}~X Y nX qh|jrht|ddshtd	|jd
||j< qh|rd}	t drT j}	n jrrt jdrr jj}	d j d|	 d}
t|
|ddS )zEnsure that all fields' values are valid and that required fields
        are present.

        Raises :class:`ValidationError` if any of the fields' values are found
        to be invalid.
        Nc                    s.   g | ]&} j | j| j|fqS rH   )r5   r1   r   r   )r   rW   rh   rH   rI   r     s   
z)BaseDocument.validate.<locals>.<listcomp>EmbeddedDocumentFieldGenericEmbeddedDocumentField)r   r   FzField is required)rD   Noner&   zValidationError (:z) )errors)r   r   r   r9   r   r=   	_validater   rW   
ValueErrorr[   AssertionErrorrequiredr:   rY   r&   Z	_instancer6   )rA   r   r   errorr   r   r   rG   rE   r&   messagerH   rh   rI   validate  sJ    

   zBaseDocument.validatec                 O   s@   | dd}d|kr(tdt t|d< tj| |f||S )zConvert this document to JSON.

        :param use_db_field: Serialize field names as they appear in
            MongoDB (as opposed to attribute names on this document).
            Defaults to True.
        r   Tjson_options  No 'json_options' are specified! Falling back to LEGACY_JSON_OPTIONS with uuid_representation=PYTHON_LEGACY. For use with other MongoDB drivers specify the UUID representation to use. This will be changed to uuid_representation=UNSPECIFIED in a future release.)r,   warningswarnDeprecationWarningr   r   dumpsr_   )rA   rB   rO   r   rH   rH   rI   to_json  s    zBaseDocument.to_jsonc                 K   s4   d|krt dt t|d< | jtj|f||dS )a  Converts json data to a Document instance.

        :param str json_data: The json data to load into the Document.
        :param bool created: Boolean defining whether to consider the newly
            instantiated document as brand new or as persisted already:
            * If True, consider the document as brand new, no matter what data
              it's loaded with (i.e., even if an ID is loaded).
            * If False and an ID is NOT provided, consider the document as
              brand new.
            * If False and an ID is provided, assume that the object has
              already been persisted (this has an impact on the subsequent
              call to .save()).
            * Defaults to ``False``.
        r   r   )created)r   r   r   r   rc   r   loads)clsZ	json_datar   rO   rH   rH   rI   	from_json  s    zBaseDocument.from_jsonc                    s   t |tttfs|S t |t}|r@d|kr@t|d }|f |S |r\fdd| D }n fdd|D }td}t |ttfrt |tstt	|rt
| }qt| }n t |trt |tst| }|S )z:Expand any dynamic values to their correct types / values.r'   c                    s   i | ]\}}|  ||qS rH   rX   r   ra   vrh   rH   rI   
<dictcomp>  s      z8BaseDocument.__expand_dynamic_values.<locals>.<dictcomp>c                    s   g | ]}  |qS rH   r   )r   r   rW   rA   rH   rI   r     s     z8BaseDocument.__expand_dynamic_values.<locals>.<listcomp>EmbeddedDocumentListField)r=   dictr4   r]   r   r<   r   r
   
issubclassrd   r   r	   )rA   rW   rE   Zis_dictr   r   rH   r   rI   Z__expand_dynamic_values  s"    

z$BaseDocument.__expand_dynamic_valuesc                 C   s   t | dsdS d|krD|dd\}}| j||}| d| }n| j||}|| jkr|dd }}|t|krd|d| | jkrq|d7 }ql| j| d|d| d }| jj}| jdd D ]}|	|r|| qdS )z-Mark a key as explicitly changed by the user.r   Nr      )
rY   r   r   r1   r   ro   joinappendremoverV   )rA   rF   restlevelsidxlevelr   rG   rH   rH   rI   rZ   	  s&    



zBaseDocument._mark_as_changedc              
   C   s  t d}t d}|  D ]}|d}| }|D ]}t|trhz|t| }W q tk
rd   d}Y qX n2t|tr||d}n|j	||}t
||d}t|tst|drt
|ddrq.g |_q.t|tttfr.t|drt|j||frq.t| q.qg | _dS )	zdUsing _get_changed_fields iterate and remove any fields that
        are marked as changed.
        ReferenceFieldGenericReferenceFieldr   Nr   r\   FrG   )r   _get_changed_fieldsr   r=   r4   int
IndexErrorr   r1   _reverse_db_field_mapr:   r   rY   r   r]   rG   r   $_nestable_types_clear_changed_fields)rA   r   r   changedpartsr`   partrD   rH   rH   rI   _clear_changed_fields$  s<    


  z"BaseDocument._clear_changed_fieldsc                 C   sn   t d}t| dst| }n|  }|D ]@\}}t|drNt||sN|  q(t|tttfr(t	
| q(dS )zaInspect nested data for changed fields

        :param data: data to inspect for changes
        Documentr<   r   N)r   rY   	enumerater<   r=   r   r4   r]   r   r   r   )r`   r   iteratorZ_index_or_keyrE   rH   rH   rI   r   J  s    

 
z1BaseDocument._nestable_types_clear_changed_fieldsc                    s   t |dst|}n| }|D ]p\}}| | d  dd | krHq t |drr| }|  fdd|D 7 } q t|tttfr t	|  | q dS )zInspect nested data for changed fields

        :param changed_fields: Previously collected changed fields
        :param base_key: The base key that must be used to prepend changes to this data
        :param data: data to inspect for changes
        r<   r   Nr   c                    s   g | ]}|r  | qS rH   rH   r   ra   Zitem_keyrH   rI   r   y  s      z?BaseDocument._nestable_types_changed_fields.<locals>.<listcomp>)
rY   r   r<   r   r=   r4   r]   r   r   _nestable_types_changed_fields)changed_fieldsZbase_keyr`   r   Zindex_or_keyrE   r   rH   r   rI   r   a  s     



  z+BaseDocument._nestable_types_changed_fieldsc                    s<  t d}t d}t d}t d}t d}t d}g }|t| dg 7 }| jD ]}| j||}	d|	 | j|d	}
| j| |	|krqJt |rqJt|
|r|
 }|fd
d|D 7 }qJt|
t	t
tfrJt drt j||||frqJn8t |r( jr(t fdd|
D r(||	 qJ| ||
 qJ|S )z>Return a list of all fields that have explicitly been changed.EmbeddedDocumentLazyReferenceFieldr   GenericLazyReferenceFieldr   SortedListFieldr   r   Nc                    s   g | ]}|r  | qS rH   rH   r   r   rH   rI   r     s      z4BaseDocument._get_changed_fields.<locals>.<listcomp>rG   c                 3   s   | ]} j |jkV  qd S rf   )	_orderingr   )r   drG   rH   rI   	<genexpr>  s     z3BaseDocument._get_changed_fields.<locals>.<genexpr>)r   r:   r9   r   r1   r   r5   r=   r   r4   r]   r   rY   rG   r   anyr   r   )rA   r   r   r   r   r   r   r   rD   db_field_namer`   r   rH   )rG   rF   rI   r     sH    


	
z BaseDocument._get_changed_fieldsc                 C   s:  |   }|  }i }t| dri }|D ]}|d}|}g }|D ]V}	t|ttfrX qn4t|trx|	 rx|t	|	 }nt|dr|
|	}||	 q@d|}|||< q&n|}d|kr|d= t| D ]b\}}
|
st|
tjtfrq|d}| jr(t|r(|d | jkr(||= d||< qd}|| jkrF| j| j}n| }| }|D ]f}	t|tr~|	 r~|t	|	 }n<t|drt|ts|j
|	|	}t||}n
|
|	}qVt|d	r|j
||}||jkr|j
|j}nd}|dk	rt|r| n|}|
|kr"q||= d||< q||fS )
zReturns the delta (set, unset) of the changes for a document.
        Gets any values that have been explicitly changed.
        r   r   r1   r   r   r   N__getattribute__r5   )r_   r   rY   r   r=   r   r   r4   isdigitr   r1   r   r   r<   numbersNumberboolr/   ro   r   r5   rK   r,   r   r   r:   rL   )rA   docZ
set_fieldsZ
unset_dataset_datapathr   r   new_pathprE   rK   r   	real_pathrD   rH   rH   rI   _delta  sx    




 
" 


zBaseDocument._deltac                 C   s   | j ddS )zTReturn the collection name for this class. None for abstract
        class.
        r|   N)r0   r1   r   rH   rH   rI   r{     s    z!BaseDocument._get_collection_namec                    s  |rt |tstdt| |d j}i }| D ]&\}}t|} j||}|||< q8| jkrrt	| i } j
}	|st|	}	|	 D ]\}
}|| |j|kr||j }z0|dkr|n||||
< |
|jkr||j= W q ttfk
r } z|||
< W 5 d}~X Y qX q|rPddd | D }d j|}t| jrn fdd	| D } f d
|d|}g |_|s|	|_
|S )zECreate an instance of a Document (subclass) from a PyMongo SON (dict)zEThe source SON object needs to be of type 'dict' but a '%s' was foundr'   N
c                 S   s    g | ]\}}d | d| qS )zField 'z' - rH   r   rH   rH   rI   r   >  s     z*BaseDocument._from_son.<locals>.<listcomp>z*Invalid data to create a `{}` instance.
{}c                    s    i | ]\}}| j kr||qS rH   )r5   r   r   rH   rI   r   G  s     
  z*BaseDocument._from_son.<locals>.<dictcomp>F)r!   r   )r=   r   r   rd   r1   r6   r<   rv   r   r   r5   copydeepcopyZset_auto_dereferencingrS   r>   r[   r   formatr   r7   r   )r   ZsonZ_auto_dereferencer   
class_namer`   rF   rE   Zerrors_dictr   rD   rG   er   rC   objrH   r   rI   rc   
  sZ    





zBaseDocument._from_sonc                    sB      }  } fdd|D }dd }|||}|||}|S )z(Generate and merge the full index specs.c                    s   g | ]}  |qS rH   )_build_index_spec)r   specr   rH   rI   r   U  s     z3BaseDocument._build_index_specs.<locals>.<listcomp>c                 S   sT   |s| S dd | D }|D ]4}| t|d }|dkrD| | q|| q| S )z&Helper method for merging index specs.c                 S   s   i | ]}t |d  |qS )r   )r]   )r   indexrH   rH   rI   r   ^  s     
 zNBaseDocument._build_index_specs.<locals>.merge_index_specs.<locals>.<dictcomp>r   N)r1   r]   r   update)index_specsindicesZspec_fieldsZ	new_index	candidaterH   rH   rI   merge_index_specsW  s    z:BaseDocument._build_index_specs.<locals>.merge_index_specs)_geo_indices_unique_with_indexes)r   Zmeta_indexesgeo_indicesZunique_indicesr   r   rH   r   rI   _build_index_specsP  s    

zBaseDocument._build_index_specsc           
   
   C   sZ  t |trd|gi}n.t |ttfr2dt|i}nt |trDt|}g }d}| jd}|o|dd o|ddod|d k}|o|ddp| jd	d}d|kr|d |d D ]R}t |ttfrqtj	}|
d
rtj}n|
drtj}nn|
drtj}nZ|
dr"tj}nF|
drVz
tj}W n tk
rR   tY nX n|
drhtj}|
dr|dd }|d}|dgdgdgfkrd}nZ| |}g }|D ]<}	z|	dkr|	j}	W n tk
r   Y nX ||	 qd|}|||f q|rH|tjtjfkrHtdks<|tkrH|dd |rV||d< |S )z9Build a PyMongo index spec from a MongoEngine index spec.r   Nr   sparseFr   Tr'   Z	index_cls-$#()*)+r   r  r   r   r   r   r   r   r&   r%   r   r   )r'   r   )r=   rv   r4   r]   r   r0   r1   r,   pymongo	ASCENDINGrV   Z
DESCENDINGZTEXTZHASHEDZ	GEOSPHEREGEOHAYSTACKr[   NotImplementedErrorZGEO2Dr   _lookup_fieldrS   r   r   insert)
r   r   Z
index_list	directionr   Zinclude_clsrF   r   r   rG   rH   rH   rI   r   q  s    




	







zBaseDocument._build_index_specr   c                    s$  g }| j  D ]\}}|j}|jr|jg}|jrt|jtrH|jg|_g }|jD ]V}|d}	| 	|	}	dd |	D }
|
d|
 d|	d _| o|	d j| jk}qR||7 } fdd|D }|d|d}|
| |jjdkr|j}|jjd	kr|j| krd
| }|j}|||7 }q|S )z;Find unique indexes in the document schema and return them.r   c                 S   s   g | ]
}|j qS rH   rS   )r   r   rH   rH   rI   r     s     z5BaseDocument._unique_with_indexes.<locals>.<listcomp>Tr   c                    s   g | ]}  | t jfqS rH   )r  r  r   	namespacerH   rI   r     s     )r   uniquer   >   r   	ListFieldr   r   r   )r5   r<   r   r  rS   unique_withr=   rv   r   r  r   r   r   rW   __dict__r.   rw   rG   document_typer   )r   r  Zunique_indexesrD   rG   r   Zunique_fieldsr  Z
other_namer   Z
name_partsr   r   Zfield_namespaceZdoc_clsrH   r  rI   r     s<    






z!BaseDocument._unique_with_indexesc           	      C   s   |pg }g }| |  d}tdd |D }| j D ]~}t||sFq6t|dr|j}||kr`q6t|dr||j||jd7 }q6|j	r6|j}|r| d| }| d||j	fgi q6|S )	N)r   ZGeoPointFieldZ
PointFieldZLineStringFieldZPolygonFieldc                 s   s   | ]}t |V  qd S rf   r   )r   rG   rH   rH   rI   r     s     z,BaseDocument._geo_indices.<locals>.<genexpr>r  r   )parent_fieldr   r   )
r   r]   r5   r#   r=   rY   r  r   rS   Z
_geo_index)	r   Z	inspectedr  r   Zgeo_field_type_namesZgeo_field_typesrG   Z	field_clsrD   rH   rH   rI   r     s.    



 
zBaseDocument._geo_indicesc              
   C   s  t d}t d}t|ttfs$|g}g }d}|D ]}| rTt||rT|| q0|dkr|dkrp| jd }|| jkr| j| }n| jr||d}n| j	ds| j	dd	r| 
 D ]@}z||gd
 }W n tk
r   Y qY nX |dk	r qqtd| ntd| nt d}t d}	t|||	frLtdd| tt|dddrn|j|}
n`| jrt||stt|ddddr||d}
n*t|dr||}
ntd||j|
st|tr|| q0n|
s td| |
}|| q0|S )a  Given the path to a given field, return a list containing
        the Field object associated with that field and all of its parent
        Field objects.

        Args:
            parts (str, list, or tuple) - path to the field. Should be a
            string for simple fields existing on this document or a list
            of strings for a field that exists deeper in embedded documents.

        Returns:
            A list of Field instances for fields that were found or
            strings for sub-fields that weren't.

        Example:
            >>> user._lookup_field('name')
            [<mongoengine.fields.StringField at 0x1119bff50>]

            >>> user._lookup_field('roles')
            [<mongoengine.fields.EmbeddedDocumentListField at 0x1119ec250>]

            >>> user._lookup_field(['roles', 'role'])
            [<mongoengine.fields.EmbeddedDocumentListField at 0x1119ec250>,
             <mongoengine.fields.StringField at 0x1119ec050>]

            >>> user._lookup_field('doesnt_exist')
            raises LookUpError

            >>> user._lookup_field(['roles', 'doesnt_exist'])
            [<mongoengine.fields.EmbeddedDocumentListField at 0x1119ec250>,
             'doesnt_exist']

        r  rR   Nr&   rU   r
  r   ZabstractFr   zCannot resolve field "%s"r   r   z"Cannot perform join in mongoDB: %s__rG   lookup_memberr  r/   z6Cannot resolve subfield or operator {} on the field {})r   r=   r4   r]   r   r   r0   r5   r/   r1   __subclasses__r  r   r   rY   r:   rG   r  r   rW   r   )r   r   r  rR   r   rG   rD   subclsr   r   Z	new_fieldrH   rH   rI   r  '  sx    %




 
 
zBaseDocument._lookup_fieldr   c                 C   s(   | |}dd | |D }d|S )z:Translate a field attribute name to a database field name.c                 S   s   g | ]
}|j qS rH   r
  r   rH   rH   rI   r     s     z6BaseDocument._translate_field_name.<locals>.<listcomp>r   )r   r  r   )r   rG   sepr   rH   rH   rI   _translate_field_name  s    
z"BaseDocument._translate_field_namec                 C   s@   dd | j  D }|D ]"\}}t| d| t| j|d qdS )z\For each field that specifies choices, create a
        get_<field>_display method.
        c                 S   s   g | ]\}}|j r||fqS rH   )choices)r   nr   rH   rH   rI   r     s      z4BaseDocument.__set_field_display.<locals>.<listcomp>zget_%s_displayr   N)r5   r<   r;   r    _BaseDocument__get_field_display)rA   Zfields_with_choices	attr_namerG   rH   rH   rI   Z__set_field_display  s    z BaseDocument.__set_field_displayc                    st   t |  j} jrpt jd ttfrp|dkr2dS t  dd} jjdkrN|n|g}| fdd|phg D S |S )z+Return the display value for a choice fieldr   NZdisplay_sep )r  r   c                    s"   g | ]}t t j||qS rH   )rv   r   r  r1   )r   rm   r   rH   rI   r     s     z4BaseDocument.__get_field_display.<locals>.<listcomp>)	r:   rW   r  r=   r4   r]   r.   rw   r   )rA   rG   rE   r  r#   rH   r   rI   Z__get_field_display  s    
z BaseDocument.__get_field_display)TN)T)F)TF)r   )NN)r   )/rw   
__module____qualname__	__slots__r/   r@   r7   rJ   rN   r^   rb   re   ri   rk   rl   rn   rp   ry   rs   r   r   r   r   r_   r   r   classmethodr   rX   rZ   r   staticmethodr   r   r   r   r{   rc   r   r   r   r   r  r  r?   r  __classcell__rH   rH   rP   rI   r   '   sj   U2	
8
6&

1S
E
 
Y6$
 r   )&r   r   r   	functoolsr   r  Zbsonr   r   r   r   Zmongoenginer   Zmongoengine.base.commonr   Zmongoengine.base.datastructuresr	   r
   r   r   r   Zmongoengine.base.fieldsr   Zmongoengine.commonr   Zmongoengine.errorsr   r   r   r   r   Zmongoengine.pymongo_supportr   r   r   r  r[   r   rH   rH   rH   rI   <module>   s&   

