U
    8ÄT_#M  ã                   @   sÈ  d dl Z d dlZd dlm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 d dlmZm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mZ dd„ dD ƒZdd„ e  ¡ D ƒZ!edd "dd„ e!D ƒ¡ ƒZ#G dd„ de$ƒZ%dd„ Z&dd„ Z'dd„ Z(dd„ Z)d d!„ Z*d"d#„ Z+d$d%„ Z,G d&d'„ d'eƒZ-d(d)„ Z.dEd*d+„Z/dFd,d-„Z0d.d/„ Z1dGd1d2„Z2d3d4„ Z3d5d6„ Z4dHd7d8„Z5G d9d:„ d:e$ƒZ6d;d<„ Z7d=d>„ Z8d?d@„ Z9dAdB„ Z:dCdD„ Z;dS )Ié    N)Údefaultdict)ÚFieldDoesNotExist)ÚmodelsÚrouter)Ú
LOOKUP_SEP)Ú	Collector)Úpretty_name)ÚNoReverseMatchÚreverse)ÚformatsÚtimezone)Úformat_html)Ú_lazy_re_compile)Úcapfirst)ÚngettextÚoverridec                 C   s   i | ]}|d | “qS )z_%02X© )Ú.0Úir   r   ú>/tmp/pip-unpacked-wheel-dv63caxw/django/contrib/admin/utils.pyÚ
<dictcomp>   s      r   s   ":/_#?;@&=+$,"[]<>%
\c                 C   s   i | ]\}}|t |ƒ“qS r   )Úchr)r   ÚkÚvr   r   r   r      s      z_(?:%s)ú|c                 C   s   g | ]}|d d… ‘qS )é   Nr   )r   Úxr   r   r   Ú
<listcomp>   s     r   c                   @   s   e Zd ZdZdS )ÚFieldIsAForeignKeyColumnNamez/A field is a foreign key attname, i.e. <FK>_id.N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r      s   r   c              	   C   s„   |  t¡}|D ]p}|dkr"| jj}z|  |¡}W n tk
rH   Y qY qX t|dƒr| ¡ }|d j} t	dd„ |D ƒƒr dS qdS )zT
    Return True if 'distinct()' should be used to query the given lookup path.
    ÚpkÚget_path_infoéÿÿÿÿc                 s   s   | ]}|j V  qd S ©N)Zm2m)r   Úpathr   r   r   Ú	<genexpr>.   s     z(lookup_needs_distinct.<locals>.<genexpr>TF)
Úsplitr   r#   ÚnameÚ	get_fieldr   Úhasattrr$   Úto_optsÚany)ÚoptsZlookup_pathZlookup_fieldsÚ
field_nameÚfieldZ	path_infor   r   r   Úlookup_needs_distinct   s    



r2   c                 C   s0   |   d¡r| d¡}n|   d¡r,| ¡ dk}|S )zJ
    Return a lookup value prepared to be used in queryset filtering.
    Z__inú,Z__isnull)Ú ÚfalseÚ0)Úendswithr)   Úlower)ÚkeyÚvaluer   r   r   Úprepare_lookup_value4   s
    

r;   c                 C   s   t | tƒr|  t¡S | S )a*  
    Ensure that primary key values do not confuse the admin URLs by escaping
    any '/', '_' and ':' and similarly problematic characters.
    Similar to urllib.parse.quote(), except that the quoting is slightly
    different so that it doesn't get automatically unquoted by the Web browser.
    )Ú
isinstanceÚstrÚ	translateÚ	QUOTE_MAP©Úsr   r   r   ÚquoteA   s    rB   c                 C   s   t  dd„ | ¡S )zUndo the effects of quote().c                 S   s   t | d  S )Nr   )ÚUNQUOTE_MAP)Úmr   r   r   Ú<lambda>M   ó    zunquote.<locals>.<lambda>)Ú
UNQUOTE_REÚsubr@   r   r   r   ÚunquoteK   s    rI   c                 C   s6   g }| D ](}t |ttfƒr&| |¡ q| |¡ q|S )zS
    Return a list which is a single level of flattening of the original list.
    )r<   ÚlistÚtupleÚextendÚappend)ÚfieldsZflatr1   r   r   r   ÚflattenP   s    rO   c                 C   s(   g }| D ]\}}|  t|d ƒ¡ q|S )z?Return a list of field names from an admin fieldsets structure.rN   )rL   rO   )Z	fieldsetsÚfield_namesr*   r/   r   r   r   Úflatten_fieldsets]   s    
ÿrQ   c           	         s¦   z| d }W n" t k
r.   g i tƒ g f Y S X t |jj¡}t|d�}| | ¡ tƒ ‰‡ ‡‡fdd„‰| ˆ¡}‡fdd„|j	D ƒ}dd„ |j
 ¡ D ƒ}||ˆ|fS )	a  
    Find all objects related to ``objs`` that should also be deleted. ``objs``
    must be a homogeneous iterable of objects (e.g. a QuerySet).

    Return a nested list of strings suitable for display in the
    template with the ``unordered_list`` filter.
    r   )Úusingc                    s¨   | j }|ˆ jk}| j}dt|jƒ| f }|r ˆ j|  ˆ| ¡sJˆ |j¡ z(tdˆ j|j	|j
f d t| jƒfƒ}W n tk
rŠ   | Y S X tdt|jƒ|| ƒS |S d S )Nz%s: %sz%s:%s_%s_changez{}: <a href="{}">{}</a>)Ú	__class__Ú	_registryÚ_metar   Úverbose_nameZhas_delete_permissionÚaddr
   r*   Ú	app_labelÚ
model_namerB   r#   r	   r   )ÚobjÚmodelZ	has_adminr/   Zno_edit_linkZ	admin_url)Ú
admin_siteÚperms_neededÚrequestr   r   Úformat_callbacky   s2    
þÿ 
ü
ýz,get_deleted_objects.<locals>.format_callbackc                    s   g | ]}ˆ |ƒ‘qS r   r   )r   rZ   )r_   r   r   r   ™   s     z'get_deleted_objects.<locals>.<listcomp>c                 S   s   i | ]\}}|j jt|ƒ“qS r   )rU   Úverbose_name_pluralÚlen)r   r[   Úobjsr   r   r   r   š   s      z'get_deleted_objects.<locals>.<dictcomp>)Ú
IndexErrorÚsetr   Zdb_for_writerU   r[   ÚNestedObjectsÚcollectÚnestedÚ	protectedÚ
model_objsÚitems)	rb   r^   r\   rZ   rR   Ú	collectorZ	to_deleterh   Zmodel_countr   )r\   r_   r]   r^   r   Úget_deleted_objectsg   s    


rl   c                       sX   e Zd Z‡ fdd„Zdd„ Zd‡ fdd„	Z‡ fdd	„Zd
d„ Zddd„Zdd„ Z	‡  Z
S )re   c                    s*   t ƒ j||Ž i | _tƒ | _ttƒ| _d S r&   )ÚsuperÚ__init__Úedgesrd   rh   r   ri   ©ÚselfÚargsÚkwargs©rS   r   r   rn       s    zNestedObjects.__init__c                 C   s   | j  |g ¡ |¡ d S r&   )ro   Ú
setdefaultrM   )rq   ÚsourceÚtargetr   r   r   Úadd_edge¦   s    zNestedObjects.add_edgeNc              
      sä   |D ]\}|r@|  d¡s@||jj|jjdœ }|  t||ƒ|¡ n|  d |¡ | j|jj  |¡ qzt	ƒ j
|fd|i|—ŽW S  tjk
r® } z| j |j¡ W 5 d }~X Y n2 tjk
rÞ } z| j |j¡ W 5 d }~X Y nX d S )Nú+)ÚclassrX   Úsource_attr)r7   rU   rY   rX   rx   Úgetattrri   r[   rW   rm   rf   r   ZProtectedErrorrh   ÚupdateZprotected_objectsZRestrictedErrorZrestricted_objects)rq   rb   rv   r{   rs   rZ   Úrelated_nameÚert   r   r   rf   ©   s    þzNestedObjects.collectc                    s$   t ƒ  |||¡}|jdd„ |D ƒŽ S )Nc                 S   s   g | ]
}|j ‘qS r   )r*   )r   Zrelated_fieldr   r   r   r   ½   s     z1NestedObjects.related_objects.<locals>.<listcomp>)rm   Úrelated_objectsZselect_related)rq   Úrelated_modelZrelated_fieldsrb   Úqsrt   r   r   r€   »   s    zNestedObjects.related_objectsc                 C   sj   ||krg S |  |¡ g }| j |d¡D ]}| |  |||¡¡ q(|rR||ƒg}n|g}|rf| |¡ |S )Nr   )rW   ro   ÚgetrL   Ú_nestedrM   )rq   rZ   Úseenr_   ÚchildrenÚchildÚretr   r   r   r„   ¿   s    

zNestedObjects._nestedc                 C   s6   t ƒ }g }| j dd¡D ]}| |  |||¡¡ q|S )z4
        Return the graph as a nested list.
        Nr   )rd   ro   rƒ   rL   r„   )rq   r_   r…   ÚrootsÚrootr   r   r   rg   Î   s
    zNestedObjects.nestedc                 O   s   dS )z�
        We always want to load the objects into memory so that we can display
        them to the user in confirm page.
        Fr   rp   r   r   r   Úcan_fast_deleteØ   s    zNestedObjects.can_fast_delete)NN)N)r   r    r!   rn   rx   rf   r€   r„   rg   r‹   Ú__classcell__r   r   rt   r   re   Ÿ   s   

re   c                 C   sF   t | tjtjjfƒr| j}nt | tjjƒr4| jj}n| }|j	|j
dœS )zË
    Return a `dict` with keys 'verbose_name' and 'verbose_name_plural',
    typically for use with string formatting.

    `obj` may be a `Model` instance, `Model` subclass, or `QuerySet` instance.
    )rV   r`   )r<   r   ZModelÚbaseZ	ModelBaserU   ÚqueryÚQuerySetr[   rV   r`   )rZ   r/   r   r   r   Úmodel_format_dictà   s    
þr�   c                 C   sN   t | tjjƒr$|dkr|  ¡ }| j} t| ƒ}|d |d  }}t|||pJdƒS )a-  
    Return the appropriate `verbose_name` or `verbose_name_plural` value for
    `obj` depending on the count `n`.

    `obj` may be a `Model` instance, `Model` subclass, or `QuerySet` instance.
    If `obj` is a `QuerySet` instance, `n` is optional and the length of the
    `QuerySet` is used.
    NrV   r`   r   )r<   r   rŽ   r�   Úcountr[   r�   r   )rZ   ÚnÚdZsingularÚpluralr   r   r   Úmodel_ngettextó   s    	r•   c              	   C   s¤   |j }zt|| ƒ}W nv ttfk
rŠ   t| ƒr>| }||ƒ}nDt|| ƒrd| dkrdt|| ƒ}||ƒ}nt|| ƒ}t|ƒr~|ƒ }n|}d }Y nX d }t|| ƒ}|||fS )NÚ__str__)rU   Ú_get_non_gfk_fieldr   r   Úcallabler,   r|   )r*   rZ   Úmodel_adminr/   ÚfÚattrr:   r   r   r   Úlookup_field  s$    





rœ   c                 C   sR   |   |¡}|jr(|jr|jr"|jr(tƒ ‚|jrN|jsNt|dƒrN|j|krNt	ƒ ‚|S )a  
    For historical reasons, the admin app relies on GenericForeignKeys as being
    "not found" by get_field(). This could likely be cleaned up.

    Reverse relations should also be excluded as these aren't attributes of the
    model (rather something like `foo_set`).
    Úattname)
r+   Úis_relationZmany_to_oner�   Zone_to_manyr   Zmany_to_manyr,   r�   r   )r/   r*   r1   r   r   r   r—     s    
þþþ r—   Fc           	      C   s²  d}z<t |j| ƒ}z
|j}W n tk
r:   |jjj}Y nX W �nZ tk
�rz   | dkrnt|jjƒ}t}�nt| ƒr|| }n†t|| ƒr’t	|| ƒ}npt|| ƒr¨t	|| ƒ}nZ|rÂ| |j
krÂ|j
|  }n@d| |jjf }|ræ|d|jj 7 }|rú|d|jj 7 }t|ƒ‚t|dƒ�r|j}n`t|tƒ�rFt|dƒ�rFt|jdƒ�rF|jj}n0t|ƒ�rn|jdk�rbd}n
t|jƒ}nt| ƒ}Y n" tk
�rš   t| ƒ}| }Y nX |�rª||fS |S dS )	ak  
    Return a sensible label for a field name. The name can be a callable,
    property (but not created with @property decorator), or the name of an
    object's attribute, as well as a model field. If return_attr is True, also
    return the resolved attribute (which could be a callable). This will be
    None if (and only if) the name refers to a field.
    Nr–   zUnable to lookup '%s' on %sz or %sÚshort_descriptionÚfgetz<lambda>z--)r—   rU   rV   ÚAttributeErrorr�   r   r=   r˜   r,   r|   rN   Zobject_namerS   r   rŸ   r<   Úpropertyr    r   r   )	r*   r[   r™   Zreturn_attrÚformr›   r1   ÚlabelÚmessager   r   r   Úlabel_for_field4  sX    


ÿ
þ


r¦   c              	   C   sB   d}zt |j| ƒ}W n ttfk
r,   Y nX t|dƒr>|j}|S )Nr4   Ú	help_text)r—   rU   r   r   r,   r§   )r*   r[   r§   r1   r   r   r   Úhelp_text_for_fieldp  s    
r¨   c                 C   s(  ddl m} t|dd ƒr*t|jƒ | |¡S t|tjƒr>|| ƒS | d krJ|S t|tj	ƒrft
 t | ¡¡S t|tjtjfƒr‚t
 | ¡S t|tjƒrœt
 | |j¡S t|tjtjfƒr¸t
 | ¡S t|tjƒrÖ| rÖtd| j| ƒS t|tjƒ�r| �rz| | ¡W S  tk
�r   t| |ƒ Y S X n
t| |ƒS d S )Nr   ©Ú_boolean_iconÚflatchoicesz<a href="{}">{}</a>)Ú,django.contrib.admin.templatetags.admin_listrª   r|   Údictr«   rƒ   r<   r   ZBooleanFieldZDateTimeFieldr   Úlocalizer   Útemplate_localtimeZ	DateFieldZ	TimeFieldZDecimalFieldÚnumber_formatZdecimal_placesZIntegerFieldZ
FloatFieldZ	FileFieldr   ÚurlZ	JSONFieldZget_prep_valueÚ	TypeErrorÚdisplay_for_value)r:   r1   Úempty_value_displayrª   r   r   r   Údisplay_for_field|  s.    

rµ   c                 C   s¸   ddl m} |r|| ƒS | d kr$|S t| tƒr6t| ƒS t| tjƒrRt t 	| ¡¡S t| tj
tjfƒrnt | ¡S t| ttjtfƒrŠt | ¡S t| ttfƒr¬d dd„ | D ƒ¡S t| ƒS d S )Nr   r©   z, c                 s   s   | ]}t |ƒV  qd S r&   )r=   )r   r   r   r   r   r(   ª  s     z$display_for_value.<locals>.<genexpr>)r¬   rª   r<   Úboolr=   Údatetimer   r®   r   r¯   ÚdateÚtimeÚintÚdecimalÚDecimalÚfloatr°   rJ   rK   Újoin)r:   r´   Úbooleanrª   r   r   r   r³   š  s     


r³   c                   @   s   e Zd ZdS )ÚNotRelationFieldN)r   r    r!   r   r   r   r   rÀ   ¯  s   rÀ   c                 C   s"   t | dƒr|  ¡ d jjS t‚d S )Nr$   r%   )r,   r$   r-   r[   rÀ   )r1   r   r   r   Úget_model_from_relation³  s    
rÁ   c              	   C   s°   g }| }|  t¡}|D ]Š}|j |¡}t|ƒt|ƒd krbzt|ƒ W n tk
r`   Y  q¢Y nX |jr†|jrt|j	r†| 
¡ }|jj}n|jj}|j}| d|¡ q|t |¡fS )z« Create a reversed field path.

    E.g. Given (Order, "user__groups"),
    return (Group, "user__order").

    Final field must be a related model, not a data field.
    r   r   )r)   r   rU   r+   ra   rÁ   rÀ   rž   Zauto_createdZconcreteZrelated_query_nameZremote_fieldr[   r1   r*   r�   Úinsertr¾   )r[   r'   Zreversed_pathÚparentÚpiecesÚpiecer1   r~   r   r   r   Úreverse_field_pathº  s"    

rÆ   c                 C   sD   |  t¡}g }|D ],}|r(t|d ƒ}n| }| |j |¡¡ q|S )a;   Return list of Fields given path relative to model.

    e.g. (ModelX, "user__groups__name") -> [
        <django.db.models.fields.related.ForeignKey object at 0x...>,
        <django.db.models.fields.related.ManyToManyField object at 0x...>,
        <django.db.models.fields.CharField object at 0x...>,
    ]
    r%   )r)   r   rÁ   rM   rU   r+   )r[   r'   rÄ   rN   rÅ   rÃ   r   r   r   Úget_fields_from_pathÙ  s    	
rÇ   c                 C   s  | j }tdƒ� t| |ƒ}W 5 Q R X g }|r<| di i¡ n| j rT| dd|ii¡ |�rtdƒ�¦ |D ]š}|jD ]$}| dt|jjƒt|ƒdœi¡ qr|jD ]6\}}	| dt|jjƒt|ƒt|j	d |	ƒdœi¡ qž|j
D ]$}
| dt|
jjƒt|
ƒdœi¡ qÜqhW 5 Q R X |S )	zÊ
    Construct a JSON structure describing changes from a changed object.
    Translations are deactivated so that strings are stored untranslated.
    Translation happens later on LogEntry access.
    NÚaddedÚchangedrN   )r*   Úobjectr   )r*   rÊ   rN   Zdeleted)Úchanged_dataÚtranslation_overrideÚ#_get_changed_field_labels_from_formrM   Znew_objectsr=   rU   rV   Zchanged_objectsZformsZdeleted_objects)r£   ZformsetsrW   rË   Úchanged_field_labelsZchange_messageZformsetZadded_objectZchanged_objectZchanged_fieldsZdeleted_objectr   r   r   Úconstruct_change_messageí  sD    	



þÿ
ýÿ

þÿrÏ   c              	   C   sN   g }|D ]@}z| j | jp|}W n tk
r8   |}Y nX | t|ƒ¡ q|S r&   )rN   r¤   ÚKeyErrorrM   r=   )r£   rË   rÎ   r0   Zverbose_field_namer   r   r   rÍ     s    
rÍ   )N)N)NFN)F)<r·   r»   Úcollectionsr   Zdjango.core.exceptionsr   Z	django.dbr   r   Zdjango.db.models.constantsr   Zdjango.db.models.deletionr   Zdjango.forms.utilsr   Zdjango.urlsr	   r
   Zdjango.utilsr   r   Zdjango.utils.htmlr   Zdjango.utils.regex_helperr   Zdjango.utils.textr   Zdjango.utils.translationr   r   rÌ   r?   rj   rC   r¾   rG   Ú	Exceptionr   r2   r;   rB   rI   rO   rQ   rl   re   r�   r•   rœ   r—   r¦   r¨   rµ   r³   rÀ   rÁ   rÆ   rÇ   rÏ   rÍ   r   r   r   r   Ú<module>   sN   

8A


<
1