
    /~hR                        d dl Z d dlZd dl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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! d dl"m#Z# d dl"m$Z% dD  ci c]  } | d| z  
 c} Z&e&jO                         D ci c]  \  }}| e(|       c}}Z) eddjU                  e)D cg c]  }|dd 	 c}      z        Z+ G d de,      Z-d Z.d Z/d3dZ0d Z1d Z2d Z3d Z4d  Z5d! Z6 G d" d#e      Z7d$ Z8d4d%Z9d4d&Z:d' Z;d5d(Z<d) Z=d* Z>d6d+Z? G d, d-e,      Z@d. ZAd/ ZBd0 ZCd1 ZDd2 ZEyc c} w c c}}w c c}w )7    N)defaultdict)reduce)or_)FieldDoesNotExist)modelsrouter)
LOOKUP_SEP)	Collector)pretty_name)NoReverseMatchreverse)formatstimezone)make_hashable)format_html)_lazy_re_compile)capfirst)ngettext)overrides   ":/_#?;@&=+$,"[]<>%
\z_%02Xz_(?:%s)|   c                       e Zd ZdZy)FieldIsAForeignKeyColumnNamez/A field is a foreign key attname, i.e. <FK>_id.N)__name__
__module____qualname____doc__     c/var/www/peopleoo.sandbox-dev.co.uk/venv/lib/python3.12/site-packages/django/contrib/admin/utils.pyr   r      s    9r   r   c                 ,   |j                  t              }|D ]k  }|dk(  r| j                  j                  }	 | j	                  |      }t        |d      s=|j                  }|d   j                  } t        d |D              sk y y# t        $ r Y zw xY w)zA
    Return True if the given lookup path spawns duplicates.
    pk
path_infosc              3   4   K   | ]  }|j                     y wN)m2m).0paths     r    	<genexpr>z+lookup_spawns_duplicates.<locals>.<genexpr>4   s     6Dtxx6s   TF)
splitr	   r"   name	get_fieldhasattrr#   to_optsanyr   )optslookup_pathlookup_fields
field_namefield	path_infos         r    lookup_spawns_duplicatesr7   !   s      %%j1M#  
J	 NN:.E
 ul+!,,	 },,6I66  ! "  ! 		s   B	BBc                 R    | j                  |      }t        |t              r|d   S |S )Nr$   )get
isinstancelist)
parameterskeyvalues      r    get_last_value_from_parametersr?   ;   s(    NN3E"5$/59:U:r   c                     t        |t              r|D cg c]  }t        | ||       c}S | j                  d      r|j	                  |      }|S | j                  d      r|j                         dv}|S c c}w )zJ
    Return a lookup value prepared to be used in queryset filtering.
    )	separator__in__isnull) false0)r:   r;   prepare_lookup_valueendswithr+   lower)r=   r>   rA   vs       r    rG   rG   @   st     %KPQa$S!yAQQ
||FI& L 
j	!%77L Rs   A6c                     t        j                         }| j                         D ]!  \  }|t        t        fd|D              z  }# |S )Nc              3   L   K   | ]  }t        j                  |f        y wr&   )r   Q)r(   itemparams     r    r*   z8build_q_object_from_lookup_parameters.<locals>.<genexpr>R   s      UT5$-!8 Us   !$)r   rM   itemsr   r   )r<   q_objectparam_item_listrO   s      @r    %build_q_object_from_lookup_parametersrS   O   sI    xxzH","2"2"4 WF3 U_ UVVWOr   c                 P    t        | t              r| j                  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.
    )r:   str	translate	QUOTE_MAPss    r    quoterZ   V   s!     &03%71;;y!>Q>r   c                 0    t         j                  d |       S )zUndo the effects of quote().c                     t         | d      S )Nr   )UNQUOTE_MAP)ms    r    <lambda>zunquote.<locals>.<lambda>b   s    K!$5 r   )
UNQUOTE_REsubrX   s    r    unquoterb   `   s    >>5q99r   c                     g }| D ];  }t        |t        t        f      r|j                  |       +|j	                  |       = |S )zS
    Return a list which is a single level of flattening of the original list.
    )r:   r;   tupleextendappend)fieldsflatr5   s      r    flattenri   e   sE     D edE]+KKKK	
 Kr   c                 X    g }| D ]"  \  }}|j                  t        |d                $ |S )z?Return a list of field names from an admin fieldsets structure.rg   )re   ri   )	fieldsetsfield_namesr,   r1   s       r    flatten_fieldsetsrm   r   s7    K 4
d74>234r   c                    	 | d   }t        j                  |j                  j                        }t        ||       }|j                  |        t               fd}|j                  |      }|j                  D cg c]
  } ||       }}|j                  j                         D 	 ci c]%  \  }	} |	j                  j                  t        |       ' }
}	} ||
|fS # t        $ r g i t               g fcY S w xY wc c}w c c} }	w )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   )usingoriginc                    | j                   }| j                  }t        |j                        d| }j	                  |      rj                  |      j                  |       sj                  |j                         	 t        j                  d|j                  d|j                  dd t        | j                        f      }t        dt        |j                        ||       S |S # t        $ r |cY S w xY w)Nz: :__changez{}: <a href="{}">{}</a>)	__class___metar   verbose_nameis_registeredget_model_adminhas_delete_permissionaddr   r,   	app_label
model_namerZ   r"   r   r   )objmodelr1   no_edit_link	admin_url
admin_siteperms_neededrequests        r    format_callbackz,get_deleted_objects.<locals>.format_callback   s    yy#+D,=,=#>D##E*--e4JJ   !2!23	$#!I366]$		 )8D4E4E+F	SV    " $##$s   AC- -C;:C;)r   db_for_writerv   r   
IndexErrorsetNestedObjectscollectnested	protected
model_objsrP   verbose_name_plurallen)objsr   r   r~   ro   	collectorr   	to_deleter   r   model_countr   s    ``        @r    get_deleted_objectsr   z   s   51g ##CIIOO4E$7Id5L >   1I1:1D1DE#%EIE %//557E4 	''T2K 
 k<::_  !2sub  !R Fs   C" C?/*D"C<;C<c                   N     e Zd Z fdZd Zd fd	Z fdZd Zd	dZd Z	 xZ
S )
r   c                 x    t        |   |i | i | _        t               | _        t        t              | _        y r&   )super__init__edgesr   r   r   r   )selfargskwargsru   s      r    r   zNestedObjects.__init__   s1    $)&)
%c*r   c                 Z    | j                   j                  |g       j                  |       y r&   )r   
setdefaultrf   )r   sourcetargets      r    add_edgezNestedObjects.add_edge   s!    

fb)008r   c                    |D ]  }|r^|j                  d      sM||j                  j                  |j                  j                  dz  }| j	                  t        ||      |       n| j	                  d |       | j                  |j                  j                     j                  |        	 t        | (  |fd|i|S # t        j                  $ r/}| j                  j                  |j                         Y d }~y d }~wt        j                   $ r/}| j                  j                  |j"                         Y d }~y d }~ww xY w)N+)classr|   source_attr)rH   rv   r}   r|   r   getattrr   r   r{   r   r   r   ProtectedErrorr   updateprotected_objectsRestrictedErrorrestricted_objects)	r   r   r   r   r   r~   related_nameeru   s	           r    r   zNestedObjects.collect   s    		6C;#7#7#<*#\\44!'!7!7.   gc<8#>dC(OOCIIOO,005		6	87?4K[KFKK$$ 	7NN!!!"5"566%% 	8NN!!!"6"677	8s$   .C   E%C==E%D==Ec                 ~    t         |   |||      } |j                  |D cg c]  }|j                   c} S c c}w r&   )r   related_objectsselect_relatedr,   )r   related_modelrelated_fieldsr   qsrelated_fieldru   s         r    r   zNestedObjects.related_objects   sB    W$]NDI r  6DE]m  E
 	
Es   :c                    ||v rg S |j                  |       g }| j                  j                  |d      D ]$  }|j                  | j	                  |||             & |r
 ||      g}n|g}|r|j                  |       |S )Nr   )r{   r   r9   re   _nestedrf   )r   r~   seenr   childrenchildrets          r    r   zNestedObjects._nested   s    $;IZZ^^C, 	HEOODLLoFG	H"3'(C%CJJx 
r   c                     t               }g }| j                  j                  dd      D ]$  }|j                  | j	                  |||             & |S )z4
        Return the graph as a nested list.
        Nr   )r   r   r9   re   r   )r   r   r   rootsroots        r    r   zNestedObjects.nested   sN     uJJNN4, 	DDLLdD/BC	Dr   c                      y)z
        We always want to load the objects into memory so that we can display
        them to the user in confirm page.
        Fr   )r   r   r   s      r    can_fast_deletezNestedObjects.can_fast_delete   s    
 r   )NNr&   )r   r   r   r   r   r   r   r   r   r   __classcell__)ru   s   @r    r   r      s&    +98$
r   r   c                 0   t        | t        j                  t        j                  j                  f      r| j
                  }n=t        | t        j                  j                        r| 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.
    )rw   r   )r:   r   Modelbase	ModelBaserv   queryQuerySetr   rw   r   )r~   r1   s     r    model_format_dictr      sl     #fkk&;&;<=yy	C..	/yy))#77 r   c                     t        | t        j                  j                        r|| j	                         }| j
                  } t        |       }|d   |d   }}t        |||xs d      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.
    rw   r   r   )r:   r   r   r   countr   r   r   )r~   ndsingularplurals        r    model_ngettextr     sb     #v||,,-9		Aii#A(!,A*BfHHfaf1--r   c                    |j                   }	 t        ||       }d }t        ||       }|||fS # t        t        f$ r t        |       r| } ||      }nt        ||       r| dk7  rt        ||       } ||      }nYt        ||       }t        |      r |       }n|}t        |d      r,t        |j                  |       rt        |j                  |       }d }Y w xY w)N__str__r   )rv   _get_non_gfk_fieldr   r   r   callabler.   r   )r,   r~   model_adminr1   fattrr>   s          r    lookup_fieldr     s    99D#tT*( T"dE>+ ;<  D>DIE[$'DI,=;-DIE3%D~{G,9J9JD1Q{00$7#s   - B&CCc                    | j                  |      }|j                  r.|j                  r|j                  r|j                  r
t               |j                  r1|j                  s%t        |d      r|j                  |k(  r
t               |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_relationmany_to_oner   one_to_manyr   many_to_manyr.   r   r   )r1   r,   r5   s      r    r   r   :  sw     NN4 E 

E$7$7E<M<M!! 	""E9%MMT!*,,Lr   c                 ,   d}	 t        |j                  |       }	 |j                  }|r||fS |S # t        $ r# |j                  j                  j                  }Y 3w xY w# t
        $ r | dk(  r't        |j                  j                        }t        }nct        |       r| }nt        ||       rt        ||       }nt        ||       rt        ||       }n|r| |j                  v r|j                  |    }ncd| d|j                  j                  }|r|d|j                  j                  z  z  }|r|d|j                  j                  z  z  }t        |      t        |d      r|j                  }nt        |t               r9t        |d      r-t        |j"                  d      r|j"                  j                  }n>t        |      r(|j                  dk(  rd	}n!t%        |j                        }nt%        |       }Y t&        $ r t%        |       }| }Y w xY w)
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 'z' on z or %sshort_descriptionfgetz<lambda>z--)r   rv   rw   AttributeErrorr   r   rU   r   r.   r   rg   object_nameru   r   r   r:   propertyr   r   r   )	r,   r   r   return_attrformr   r5   labelmessages	            r    label_for_fieldr   W  s    D0"5;;5	;&&E^ t}c  	;''--::E	;  &*9001ED~d+{D1%ud+$$++-{{4( KK++ x+*?*?*H*HHHGx$..*A*AAAG$W--t01..4*D&)DII':;		33$==J. E'6E#D)' D!s3   A / )AA AA FH:HHc                     d}	 t        |j                  |       }t        |d      r|j                  }|S # t        t
        f$ r Y |S w xY w)NrD   	help_text)r   rv   r.   r   r   r   )r,   r   r   r5   s       r    help_text_for_fieldr     sY    I("5;;5 5+&I ;<  s   4 AAc                 z   ddl m} t        |dd       r&	 t        |j                        j                  | |      S t        |t        j                        r ||       S | |S t        |t        j                        r(t        j                  t        j                  |             S t        |t        j                   t        j"                  f      rt        j                  |       S t        |t        j$                        r t        j&                  | |j(                        S t        |t        j*                  t        j,                  f      rt        j&                  |       S t        |t        j.                        r| rt1        d| j2                  |       S t        |t        j4                        r%| r#	 t7        j8                  | d|j:                        S t=        | |      S # t        $ r> t        |j                        }t        |       } t        |      j                  | |      cY S w xY w# t        $ r t=        | |      cY S w xY w)Nr   _boolean_iconflatchoicesz<a href="{}">{}</a>F)ensure_asciicls),django.contrib.admin.templatetags.admin_listr   r   dictr   r9   	TypeErrorr   r:   r   BooleanFieldDateTimeFieldr   localizer   template_localtime	DateField	TimeFieldDecimalFieldnumber_formatdecimal_placesIntegerField
FloatField	FileFieldr   url	JSONFieldjsondumpsencoderdisplay_for_value)r>   r5   empty_value_displayr   r   s        r    display_for_fieldr    s   JumT*	E))*..u6IJJ 
E6..	/U##	""	E6//	0 ; ;E BCC	EF,,f.>.>?	@&&	E6..	/$$UE,@,@AA	EF//1B1BC	D$$U++	E6++	,0%))UCC	E6++	,	A::e%U]]KK !(;<<9  	E'(9(9:K!%(E$((0CDD		E2  	A$U,?@@	As$   $G *!H" AHH"H:9H:c                 H   ddl m} |r ||       S | |S t        | t              rt	        |       S t        | t
        j
                        r(t        j                  t        j                  |             S t        | t
        j                  t
        j                  f      rt        j                  |       S t        | t        t        j                  t        f      rt        j                   |       S t        | t"        t$        f      rdj'                  d | D              S t	        |       S )Nr   r   z, c              3   2   K   | ]  }t        |        y wr&   )rU   )r(   rJ   s     r    r*   z$display_for_value.<locals>.<genexpr>  s     /AQ/s   )r   r   r:   boolrU   datetimer   r   r   r   datetimeintdecimalDecimalfloatr   r;   rd   join)r>   r  booleanr   s       r    r  r    s    JU##	""	E4	 5z	E8,,	- ; ;E BCC	EHMM8==9	:&&	EC%8	9$$U++	ED%=	)yy////5zr   c                       e Zd Zy)NotRelationFieldN)r   r   r   r   r   r    r  r    s    r   r  c                 l    t        | d      r#| j                  d   j                  j                  S t        )Nr#   r$   )r.   r#   r/   r   r  )r5   s    r    get_model_from_relationr    s/    ul##++111r   c                    g }| }|j                  t              }|D ]  }|j                  j                  |      }t	        |      t	        |      dz
  k(  r	 t        |       |j                  r?|j                  r|j                  r'|j                         }|j                  j                  }n"|j                  j                  }|j                  }|j!                  d|        |t        j"                  |      fS # t        $ r Y  #w xY w)zCreate 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	   rv   r-   r   r  r  r   auto_createdconcreterelated_query_nameremote_fieldr   r5   r,   r   insertr  )r   r)   reversed_pathparentpiecespiecer5   r   s           r    reverse_field_pathr"    s     MFZZ
#F .&&u-}Vq0'.
 e&8&8 335L''--F ;;++L((FQ-!." JOOM233 $ s   C88	DDc                     |j                  t              }g }|D ]?  }|rt        |d         }n| }|j                  |j                  j                  |             A |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  rf   rv   r-   )r   r)   r   rg   r!  r  s         r    get_fields_from_pathr$    s^     ZZ
#FF 5,VBZ8FFfll,,U345 Mr   c                 N   | j                   }t        d      5  t        | |      }ddd       g }|r|j                  di i       n!| j                   r|j                  ddii       |r"t        d      5  |D ]  }|j                  D ]>  }|j                  dt        |j                  j                        t        |      di       @ |j                  D ]Y  \  }}	|j                  dt        |j                  j                        t        |      t        |j                  d   |	      di       [ |j                  D ]>  }
|j                  dt        |
j                  j                        t        |
      di       @  	 ddd       |S |S # 1 sw Y   jxY w# 1 sw Y   |S xY w)	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changedrg   )r,   objectr   )r,   r(  rg   deleted)changed_datatranslation_override#_get_changed_field_labels_from_formrf   new_objectsrU   rv   rw   changed_objectsformsdeleted_objects)r   formsetsr{   r*  changed_field_labelschange_messageformsetadded_objectchanged_objectchanged_fieldsdeleted_objects              r    construct_change_messager9    s    $$L	d	# W  C4V	W N
wm,			y85I*JKL!$' 	# $+$7$7 L"))#(+L,>,>,K,K(L*-l*;& 7>6M6M 2NN"))%(+N,@,@,M,M(N*-n*=*M$+MM!$4n+"(
 '.&=&= N"))%(+N,@,@,M,M(N*-n*=(-	@ >YW W	@ s   F4DFFF$c                     g }|D ]:  }	 | j                   |   j                  xs |}|j                  t	        |             < |S # t        $ r |}Y +w xY wr&   )rg   r   KeyErrorrf   rU   )r   r*  r2  r4   verbose_field_names        r    r,  r,  U  sk    " =
	,!%Z!8!>!>!L* 	##C(:$;<=    	,!+	,s   AAA),r&   )NFN)F)Fr  r  r  collectionsr   	functoolsr   operatorr   django.core.exceptionsr   	django.dbr   r   django.db.models.constantsr	   django.db.models.deletionr
   django.forms.utilsr   django.urlsr   r   django.utilsr   r   django.utils.hashabler   django.utils.htmlr   django.utils.regex_helperr   django.utils.textr   django.utils.translationr   r   r+  rW   rP   chrr]   r  r`   	Exceptionr   r7   r?   rG   rS   rZ   rb   ri   rm   r   r   r   r   r   r   r   r   r  r  r  r  r"  r$  r9  r,  )ikrJ   xs   0000r    <module>rR     sH      #   4 $ 1 / * / * / ) 6 & - E%?@Q!^@	%.__%67TQq#a&y7i#((;3OaAabE3O*PPQ
	9 	4;
?:

9;x@I @F&.$8:>B	"=J*	y 	4>(6r  A73Os   7EE
E