
    NwgU              	       D   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 d dlm	Z	m
Z
mZmZmZmZmZm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$ d dl%m&Z&m'Z'm(Z( d dl)m*Z* d dl+m,Z, d dl-m.Z. d dl/m0Z0 d dl1m2Z2 d dl3m4Z4 d dl5m6Z6 d dl7m8Z8 d dl9m:Z; ddl<m=Z=m>Z> ddl?m@Z@mAZAmBZBmCZC ddlDmEZEmFZFmGZGmHZH 	 d dlImJZK e	rej                  ZPneQZPi ZRd ZSd ZTd  ZU G d! d"      ZVd# ZW G d$ d%e&      ZX G d& d'e'      ZY G d( d)e$      ZZd* Z[d+ Z\ G d, d-      Z] G d. d/eP      Z^ ed01       G d2 d3             Z_ee
e_eee`ee
e_f   f      f   Za ed01       G d4 d5             Zb ed01       G d6 d7             Zcy# eL$ r	 d dlMmNZK Y w xY w)8    N)	dataclass)partial)TYPE_CHECKINGAnyDictIterableListSequenceTypeUnion)apps)settings)admin)get_user_model)ImproperlyConfiguredObjectDoesNotExist)models)ManyToManyField)OrderWrt)
ForeignKey)ForwardManyToOneDescriptorReverseManyToOneDescriptor"create_reverse_many_to_one_manager)QuerySet)m2m_changed)model_to_dict)reverse)timezone)	smart_str)cached_property)format_lazy)gettext_lazy   )
exceptionsutils) SIMPLE_HISTORY_REVERSE_ATTR_NAMEHistoricalQuerySetHistoryDescriptorHistoryManager)"post_create_historical_m2m_recordspost_create_historical_record!pre_create_historical_m2m_recordspre_create_historical_record)Local)localc                 :    	 | j                   S # t        $ r Y y w xY wN)userAttributeError)requestkwargss     L/var/www/horilla/myenv/lib/python3.12/site-packages/simple_history/models.py_default_get_userr7   =   s#    || s    	c                     | j                   y t               }	 |j                  j                  | j                         S # |j                  $ r Y y w xY w)Npk)history_user_idr   objectsgetDoesNotExist)historical_instanceUsers     r6   _history_user_getterrA   D   sU    **2D||#6#F#FGG s   %? AAc                 ,    ||j                   | _        y y r1   )r:   r;   )r?   r2   s     r6   _history_user_setterrC   N   s    .2gg+     c                   F   e Zd ZdZ e       xZZi Zddej                  fddddddde
ddddeeddd e       deeddej                  ffdZd	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Ze d        Z!d Z"d Z#d#dZ$d#dZ%d Z&d Z'd Z(d#d Z)d! Z*d" Z+y)$HistoricalRecords
HistoricalN+FT _history_m2m_fieldsc                    || _         || _        || _        || _        || _        || _        || _        |	| _        |
| _        || _	        || _
        || _        || _        || _        || _        || _        || _        || _        || _        || _        || _        || _        t-        |t.              r|g}|| _        |g }|| _        |i }|| _        	 t-        |t.              rt6        t8        ft;        |      z   | _        	 t-        |t.              rt6        t8        ft;        |      z   | _        y # t6        $ r t7        d      w xY w# t6        $ r t7        d      w xY w)Nz-The `bases` option must be a list or a tuple.z1The `m2m_bases` option must be a list or a tuple.) user_set_verbose_nameuser_set_verbose_name_pluraluser_related_nameuser_db_constraint
table_nameinherithistory_id_fieldhistory_change_reason_field
user_modelget_usercascade_delete_historycustom_model_nameappuser_id_fielduser_getteruser_setterrelated_nameuse_base_model_dbhistory_managerhistorical_queryset
m2m_fieldsm2m_fields_model_field_name
isinstancestrno_db_indexexcluded_fieldsexcluded_field_kwargs	TypeErrorHistoricalChangestuplebases	m2m_bases)selfverbose_nameverbose_name_pluralrj   rN   rP   rQ   re   rR   rS   rT   rU   rV   rW   rX   history_user_id_fieldhistory_user_getterhistory_user_setterr\   r]   rO   rd   rf   r^   r_   r`   ra   rk   s                               r6   __init__zHistoricalRecords.__init__Y   s|   < &2",?)!2"4$ 0+F($ &<#!22..(!2.#6 $+F(k3'&-K&" O. ($&!%:"	M%%+-e<DJ	Q)S)/1E)4DDDN  	MKLL	M  	QOPP	Qs   .D* ;.E *D?Ec                    || _         |j                  | _        || _        t        j
                  j                  j                  | j                  d       | j                  |       |j                  j                  rM| j                  s@dj                  | j                  j                        }t        j                   |t"               y y y )NF)weakzCHistoricalRecords added to abstract model ({}) without inherit=True)manager_name
__module__moduleclsr   signalsclass_preparedconnectfinalizeadd_extra_methods_metaabstractrQ   format__name__warningswarnUserWarning)rl   rx   namemsgs       r6   contribute_to_classz%HistoricalRecords.contribute_to_class   s     nn%%--dmm%-Hs#99dll%vdhh&7&78  MM#{+ '3rD   c                 $    d }t        |d|       y )Nc                 L    d| _         	  | j                  |i |}| ` |S # | ` w xY w)z
            Save model without saving a historical record

            Make sure you know what you're doing before you use this method.
            T)skip_history_when_savingsave)rl   argsr5   rets       r6   save_without_historical_recordzKHistoricalRecords.add_extra_methods.<locals>.save_without_historical_record   s;     -1D)2dii001J 1s    #r   )setattr)rl   rx   r   s      r6   r}   z#HistoricalRecords.add_extra_methods   s    	 	57UVrD   c                 <   d}| j                   |ur'| j                  xr t        || j                         }|sy t        |j                  d      rMt        j                  dj                  |j                  j                  |j                  j                              | j                  ||      }|r t        j                  |j                        }nt        j                  | j                        }t        ||j                   |       t"        j$                  j&                  j)                  | j&                  |d       t"        j$                  j*                  j)                  | j*                  |d       | j-                  |      }|D ]M  }t/        j(                  t1        | j.                  |j2                        |j4                  j6                  d       O t9        || j:                  | j<                        }t        || j>                  |       | j>                  |j                  _         |D ]p  }| jC                  ||j4                  j6                        }	|	| jD                  |<   t        ||	j                   |	       t9        |	      }
t        ||j2                  |
       r y )NF simple_history_manager_attributez5{}.{} registered multiple times for history tracking.)senderrt   )attr)managerqueryset)#rx   rQ   
issubclasshasattrr~   r$   MultipleRegistrationsErrorr   	app_labelobject_namecreate_history_model	importlibimport_modulerv   rw   r   r   r   ry   	post_saver{   post_deleteget_m2m_fields_from_modelr   r   r   remote_fieldthroughr(   r^   r_   ru   r   create_history_m2m_model
m2m_models)rl   r   r5   	inheritedhistory_modelrw   r`   field
descriptor	m2m_modelm2m_descriptors              r6   r|   zHistoricalRecords.finalize   s   	886!EFDHH)EI6<<!CD77GNNLL**FLL,D,D 
 11&)D,,]-E-EFF,,T[[9F..> 	  ((U(S""**4+;+;FQV*W33F;
 	E((uzz:))11	 '((--


 	)):68<8I8I5 		?E55u1199I &/DOOE"FI..	:.y9NM5::~>		?rD   c                    | j                   s$| j                   |j                  j                   S t	        | j                         r&| j                  |j                  j                        }n| j                   }|j                         |j                  j                  j                         k(  r|j                  | j                  k(  s|S t        dj                  | j                               )Nz|The 'custom_model_name' option '{}' evaluates to a name that is the same as the model it is tracking. This is not permitted.)
rW   DEFAULT_MODEL_NAME_PREFIXr~   r   callablelowerrv   rw   
ValueErrorr   )rl   modelr   s      r6   get_history_model_namez(HistoricalRecords.get_history_model_name   s    %%445ekk6M6M5NOOD**+))%++*A*ABD ))D JJLEKK3399;;  DKK/KBBH&&&C
 	
rD   c           	         i }| j                  |      }|j                  |       |j                  | j                  |||             | j                  |      }|t        |j
                  j                  <   |j                  t        dd| j                  |                   t        t        |      | j                  |      }|S )NMetarI   r   )copy_fieldsupdateget_extra_fields_m2mr   registered_modelsr~   db_tabletypeget_meta_options_m2mrc   rk   )rl   r   through_modelattrsfieldsr   m2m_history_models          r6   r   z*HistoricalRecords.create_history_m2m_model  s    !!-0VT..umVLM**=9:G---667$vr4+D+D]+STU TDNNEB  rD   c           	      l   | j                   | j                  | j                  |      | j                  |      d}d|j                  j
                  z  }|r|j                  |d<   np|j                  | j                   k7  r| j                   |d<   nG|| j                   k7  r8t        j                  |j                  j
                     }|j                  }||d<   | j                  |      }|j                  |       |j                  | j                  ||             |j                  t        dd| j                  |                   |s | j                  | j                  |d   _        | j#                  |      }|t$        |j                  j                   <   t        t'        |      | j(                  |      }	|	S )zR
        Creates a historical model to associate with the model provided.
        )rv   _history_excluded_fieldsrJ   tracked_fieldsz	%s.modelsrv   r   rI   r   )rw   re   r   fields_includedr~   r   rv   r   app_configsr   r   r   get_extra_fieldsr   get_meta_optionsrP   r   r   r   rc   rj   )
rl   r   r   r   
app_modulerX   models_moduler   r   r   s
             r6   r   z&HistoricalRecords.create_history_model!  so   
 ++(,(<(<#'#A#A%#H"2259	
 !5;;#8#88
"'"2"2E,,"&++E,4;;&""5;;#8#89CHHM"/E,!!%(VT**5&9:$vr4+@+@+GHIT__8%)__E&M" **5127%++../SY

E:rD   c                     g }|j                   j                  D ],  }|j                  | j                  vs|j	                  |       . |S r1   )r~   r   r   re   append)rl   r   r   r   s       r6   r   z!HistoricalRecords.fields_includedI  sE    [['' 	%Ezz!5!55e$	% rD   c                 ^    | j                   j                  |j                  t                     S )z=
        Find the excluded kwargs for a given field.
        )rf   r=   r   set)rl   r   s     r6   field_excluded_kwargsz'HistoricalRecords.field_excluded_kwargsP  s#     ))--ejj#%@@rD   c                    i }| j                  |      D ]  }t        j                  |      }t        j                  |j                        |_        t        |t              rt
        j                  |_        t        |t
        j                        r|}|j                  }d|_	        	 |j                         \  }}}}	||_	        t        |dd      st        |t
        j                        rt
        j                  }
nt        |      }
| j                  |      D ]  }|	j                  |d        |	j!                  dd      dk(  r|j"                  |	d<   |	j%                  ddddddddt
        j&                  	        |
|i |	}|j(                  |_        nt+        |       |j(                  | j,                  v rd|_        |||j(                  <    |S # ||_	        w xY w)	z
        Creates copies of the model's original fields, returning
        a dictionary mapping field name to copied field object.
        F
one_to_oneNtorl   rH   T)	db_constraintr\   nullblankprimary_keydb_index	serializeunique	on_delete)r   copyr   rb   r   r   IntegerField	__class__r   	swappabledeconstructgetattrOneToOneFieldr   r   popr=   r   r   
DO_NOTHINGr   transform_fieldrd   r   )rl   r   r   r   	old_fieldold_swappable_name_pathr   
field_args	FieldTypeexclude_args               r6   r   zHistoricalRecords.copy_fieldsV  s   
 ))%0 8	'EIIe$E!%5+=+=!>E%*"("5"5%!2!23!	 ) 3 3&+	#85>5J5J5L2E5$
*7I'9lE:jv33? !' 1 1I $YI
 $(#=#=i#H 6KNN;56 >>$-7'0Jt$ !!"'!$ %!" $// " 
 "46:6&^^
& zzT---!&!&F5::q8	'r Y +8I's   'G	Gc                     | j                   r| j                   }|S t        t        dd      rt        j                  d      }|S t        j
                  dd      }|S )N3SIMPLE_HISTORY_HISTORY_CHANGE_REASON_USE_TEXT_FIELDFT)r   d   )
max_lengthr   )rS   r   r   r   	TextField	CharField)rl   rS   s     r6    _get_history_change_reason_fieldz2HistoricalRecords._get_history_change_reason_field  sh    ++*.*J*J' +* KU
 +1*:*:*E'
 +* +1*:*:cPT*U'**rD   c                    | j                   r*| j                   j                         }d|_        d|_        |S t	        t
        dd      r(t        j                  dt        j                  d      }|S t        j                  d      }|S )NTF"SIMPLE_HISTORY_HISTORY_ID_USE_UUID)r   defaulteditable)r   )rR   cloner   r   r   r   r   	UUIDFielduuiduuid4	AutoField)rl   rR   s     r6   _get_history_id_fieldz'HistoricalRecords._get_history_id_field  s      #44::<+/((-%   XCUK%// $**u     &//DArD   c                 6   | j                   /t        | j                  | j                        | j                   d}|S | j                  xs t        t        dd      }dt        j                  |d| j                  t        j                  | j                        i}|S )N)history_userr;   AUTH_USER_MODELz	auth.Userr   T)r   r\   r   r   )rY   propertyrZ   r[   rT   r   r   r   r   rN   SET_NULLrO   )rl   history_user_fieldsrT   s      r6   _get_history_user_fieldsz*HistoricalRecords._get_history_user_fields  s    ) !))9)94;K;K L#'#5#5#& #"  G+[-J
  1 1!%!7!7$oo"&"9"9!# #"rD   c                     | j                   ra| j                  | j                   k(  rt        j                  d      dt	        j
                  |t        j                  | j                   d      iS i S )Nz=The related name must not be called like the history manager.history_relationF)r   r\   r   )r\   ru   r$   RelatedNameConflictErrorr   r   r   )rl   r   s     r6   _get_history_related_fieldz,HistoricalRecords._get_history_related_field  sp      D$5$55 99S  #F$5$5$//!%!2!2"'	%  IrD   c                     |j                   d t        j                  |dt        j                        || j	                         d}|S )zDReturn dict of extra fields added to the m2m historical record modelc                 v    dj                  | j                  j                  | j                  j                        S Nz{} as of {})r   r~   rm   historyhistory_daterl   s    r6   <lambda>z8HistoricalRecords.get_extra_fields_m2m.<locals>.<lambda>  s*    M$8$8

'')B)B% rD   F)r   r   )rv   __str__r	  instance_typem2m_history_id)rv   r   r   r   r   )rl   r   r   r   extra_fieldss        r6   r   z&HistoricalRecords.get_extra_fields_m2m  sQ      ** ((# ++
 +"88:
 rD   c                 :    fd}fd}d }d } fd} j                         t        j                   j                  du        j	                         t        j
                  dd	t        d
      fdt        d      fdt        d      ff      t         j                              t        |      t        |      t        |      |d t        |      d}|j                   j                               |j                   j                                |S )z@Return dict of extra fields added to the historical record modelc                     j                   }|j                  |j                  }}t        t        j
                  j                   d| d| dt        | |j                  j                        | j                  g      S )z.URL for this change in the default admin site.:__simple_history)r   )r~   r   
model_namer   r   siter   r   r:   attname
history_id)rl   optsr   r  r   s       r6   
revert_urlz6HistoricalRecords.get_extra_fields.<locals>.revert_url  sd    ;;D$(NNDOOzI::??#1YKqOLdDGGOO4dooF rD   c                    j                         D ci c]#  }|j                  t        | |j                        % }}| j                  r| j                  D cg c]P  }t	        j
                  j                  |      t              s%j
                  j                  |      j                  R }}	  j                  j                  t        | j
                  j                  j                              j                   | j                         }|j                  |        di |}t        |t        |        |S c c}w c c}w # t        $ r Y 0w xY w)Nr9   rI   )valuesr  r   r   rb   r~   	get_fieldr   r<   filterr:   r=   r   r   r   r&   )rl   r   r   excluded_attnamesr  resultr   r   s         r6   get_instancez8HistoricalRecords.get_extra_fields.<locals>.get_instance  s+   IO@EwtU]];;E  ,,
 "&!>!>%%ekk&;&;E&BOT KK))%088%! %
	) ,,ekknn>T>T0U,V!24  LL(^U^FF<dCM1% * s   (D;AE 0AE 	EEc                     t        j                  |       }|j                  | j                        j	                  d      j                         S )zW
            Get the next history record for the instance. `None` if last.
            )history_date__gtr
  )r%    get_history_manager_from_historyr  r
  order_byfirstrl   r	  s     r6   get_next_recordz;HistoricalRecords.get_extra_fields.<locals>.get_next_record  s>     <<TBG0A0AB.)rD   c                     t        j                  |       }|j                  | j                        j	                  d      j                         S )z\
            Get the previous history record for the instance. `None` if first.
            )history_date__ltr
  )r%   r%  r  r
  r&  lastr(  s     r6   get_prev_recordz;HistoricalRecords.get_extra_fields.<locals>.get_prev_record"  s>     <<TBG0A0AB.)rD   c                 &    j                  |       S )z~
            Returns the user specified by `get_user` method for manually creating
            historical objects
            )get_history_user)instancerl   s    r6   get_default_history_userzDHistoricalRecords.get_extra_fields.<locals>.get_default_history_user-  s    
 ((22rD   T)r   r#   rH   Created~Changed-Deleted)r   choicesc                 N    dj                  | j                  | j                        S r  )r   history_objectr
  r  s    r6   r  z4HistoricalRecords.get_extra_fields.<locals>.<lambda>D  s"    M$8$8##T%6%6% rD   )r  r
  history_change_reasonhistory_typer9  r0  r  next_recordprev_recordr  r  r1  )r   r   DateTimeField_date_indexingr   r   r  HistoricalObjectDescriptorr   r   staticmethodr   r  r  )	rl   r   r   r  r"  r)  r-  r1  r  s	   ```      r6   r   z"HistoricalRecords.get_extra_fields  s   		6					3 446"00$:M:MQU:UV%)%J%J%L",,q|,sAiL.AC9CVW 9t++E2 !."#O4#O4$ )55M(N'
, 	D;;EBCD99;<rD   c                     t        t        dd      }d}t        |t              r|j	                         }|dvrd}nt        |t
              sd}|st        d      |S )z,False, True, or 'composite'; default is TrueSIMPLE_HISTORY_DATE_INDEXT)	compositeFzCSIMPLE_HISTORY_DATE_INDEX must be one of (False, True, 'Composite'))r   r   rb   rc   r   boolr   )rl   r!  valids      r6   r?  z HistoricalRecords._date_indexingO  sc     #>Efc"\\^F^+FD)E&U  rD   c                 f    | j                  |      }d|i}| j                  r| j                  |d<   |S )z
        Returns a dictionary of fields that will be added to
        the Meta inner class of the m2m historical record model.
        rm   r   )r   rX   )rl   r   r   meta_fieldss       r6   r   z&HistoricalRecords.get_meta_options_m2m`  s9    
 **=9%t,88'+xxK$rD   c                    ddd}| j                   r| j                   }n)t        dt        |j                  j                              }| j
                  r| j
                  }n)t        dt        |j                  j                              }||d<   ||d<   | j                  r| j                  |d<   | j                  dk(  r:t        j                  d	|j                  j                  j                  f
      f|d<   |S )z
        Returns a dictionary of fields that will be added to
        the Meta inner class of the historical record model.
        )z-history_datez-history_id)r
  r  )orderingget_latest_byzhistorical {}rm   rn   r   rD  r
  r   indexes)rL   r!   r   r~   rm   rM   rn   rX   r?  r   Indexr:   r  )rl   r   rH  r   plural_names        r6   r   z"HistoricalRecords.get_meta_optionsn  s     9;
 %%--D	%++:R:R0STD,,;;K%5;;+J+J!KK '+N#-8)*88'+xxK$+-^U[[^^5K5K$LM&K	" rD   c                     t        t        dd      sy |st        |d      ry |j                  dd      s| j	                  ||xr dxs d|       y y )	NSIMPLE_HISTORY_ENABLEDTr   rawFrH   r3  using)r   r   r   r=   create_historical_record)rl   r0  createdrT  r5   s        r6   r   zHistoricalRecords.post_save  sT    x!94@78-GHzz%'))(GO4JsRW)X (rD   c                     t        t        dd      sy | j                  rDt        || j                        }|j	                  |      j                         j                          y | j                  |d|       y )NrQ  Tr5  rS  )r   r   rV   ru   rT  alldeleterU  )rl   r0  rT  r5   r   s        r6   r   zHistoricalRecords.post_delete  s`    x!94@&&h(9(9:GMM% $$&--/))(Cu)ErD   c                 ,    t        j                  |      S )z
        Get change reason for object.
        Customize this method to automatically fill change reason from context.
        )r%   get_change_reason_from_object)rl   r0  r;  rT  s       r6   get_change_reason_for_objectz.HistoricalRecords.get_change_reason_for_object  s    
 228<<rD   c                 p    t        t        dd      sy t        |d      ry |dv r| j                  |d       y y )NrQ  Tr   )post_addpost_remove
post_clearr3  )r   r   r   rU  )rl   r0  actionr   pk_setr   r  s          r6   r   zHistoricalRecords.m2m_changed  s>    x!94@878>>))(C8 ?rD   c           	          |j                   D ]t  }| j                  |   }|j                  }t        ||j                        j
                  }|j                  j                  D cg c]  }|j                   }}|j                  j                  D cg c]  }t        |t              s|j                  ! }	}g }
t        j                  |      } |j                  j                  di ||i} |j                  |	 }|D ]3  }d|i}|D ]  }t        ||      ||<    |
j                   |di |       5 t!        j"                  ||
|||       |j                  j%                  |
      }t'        j"                  |||||       w y c c}w c c}w )Nr	  )r   rowshistory_instancer0  r   )r   created_rowsre  r0  r   rI   )rJ   r   r0  r   r   r   r~   r   rb   r   r%   get_m2m_field_namer<   r  select_relatedr   r,   sendbulk_creater*   )rl   re  r0  r   r   original_instancer   fthrough_model_field_namesthrough_model_fk_field_namesinsert_rowsthrough_field_namerd  row
insert_row
field_namerf  s                    r6   create_historical_record_m2msz/HistoricalRecords.create_historical_record_m2ms  s   %99 #	E $ 6 0 9 9#$5uzzBJJM9F9L9L9S9S(TA(T%(T - 3 3 : :,jJ>W,( , K!&!9!9%!@/=((//Q3Ex2PQD&4&&(DED D')9:
"; FJ-4S*-EJz*F""#4#Bz#BCD .22( !1! -44@@ML.33()!1!;#	 )U,s   $FF'Fc           	         | j                   r|nd }t        |dt        j                               }| j	                  |      }| j                  |||      }t        || j                        }i }| j                  |      D ]%  }	t        ||	j                        ||	j                  <   ' t        |j                  dd       }
|
||d<    |j                  d||||d|}t        j                  |j                  ||||||       |j                  |       | j                  ||       t        j                  |j                  ||||||       y )N_history_dater  )r
  r;  r   r:  )r   r0  r
  r   r:  re  rT  rS  )r   r0  re  r
  r   r:  rT  rI   )r]   r   r   nowr/  r\  ru   r   r  r   r-   ri  r   rt  r+   )rl   r0  r;  rT  r
  r   r:  r   r   r   relation_fieldre  s               r6   rU  z*HistoricalRecords.create_historical_record  sa   //Tx(,,.I,,X6 $ A AlE!
 (D$5$56))(3 	DE#*8U]]#CE%-- 	D !0BDI%(0E$%(7== 
%%%"7	

 
 	%))==%%"7-	
 	E***+;XF%**==-%%"7	
rD   c                    	 |j                   S # t        $ rV d}	 | j                  j                  j                  j
                  r| j                  j                  }n# t        $ r Y nw xY wY nw xY w| j                  ||      S )z3Get the modifying user from instance or middleware.N)r0  r4   )_history_userr3   contextr4   r2   is_authenticatedrU   )rl   r0  r4   s      r6   r/  z"HistoricalRecords.get_history_user  s{    	))) 	G<<'',,=="ll22G! 	 }}h}@@s3    A-A AA-	A'$A-&A''A-,A-c                 H   t        | j                        }	 |j                  t        || j                               |D cg c]   }t        |t              r|n|j                  " }}|D cg c]  }t        ||      j                   c}S # t
        $ r Y Zw xY wc c}w c c}w r1   )
r   r`   r   r   ra   r3   rb   rc   r   r   )rl   r   r`   r   field_namesrs  s         r6   r   z+HistoricalRecords.get_m2m_fields_from_model  s    )
	geT-M-MNO JT
@EZs+E;
 
 DOOZz*00OO  		
 Ps   %B  %B+B	BBr1   ),r   rv   __qualname__r   LocalContextthreadr{  r   r   Modelr7   rA   rC   listr)   r'   rr   r   r}   r|   r   r   r   r   r   r   r   r   r  r  r   r   r   r?  r   r   r   r   r\  r   rt  rU  r/  r   rI   rD   r6   rF   rF   S   s     ,#~%FWJ  ||o$("$"00F"&.$9<</9KQZ,W 5?n
,! &PA?B+ #0"&]~   :YF=9$L.
`A	PrD   rF   c                 Z   | j                   | _        t        | t        j                        rt        j
                  | _        nt        | t        j                        rt        j                  | _        nVt        | t        j                        r<t        t        dd      rt        j                  | _        nt        j                  | _        d| _        d| _        d| _        | j"                  s| j$                  r7d| _        t&        j(                  dk\  rd| _        d| _        d| _        d| _        yy)z9Customize field appropriately for use in historical model%SIMPLE_HISTORY_FILEFIELD_TO_CHARFIELDFN)   r#   T)r  r   rb   r   BigAutoFieldBigIntegerFieldr   r   r   	FileFieldr   r   r   r   auto_nowauto_now_adddb_collationr   r   djangoVERSION_uniquer   r   r   s    r6   r   r     s    EJ%,,- 00	E6++	, --	E6++	,8DeL$..EO$..EO ENE EELL " >>V# EL  )rD   c                   (     e Zd ZdZdef fdZ xZS )"HistoricForwardManyToOneDescriptor
    Overrides get_queryset to provide historic query support, should the
    instance be historic (and therefore was generated by a timepoint query)
    and the other side of the relation also uses a history manager.
    returnc                 z   |j                  d      }|rt        |t        d       }t        | j                  j                  j
                  t        | j                  j                  j
                  j                  dd      d       }|r(|r&|j                  t        |d|j                              S t        | (  di |S )Nr0  r   	_notthere_as_ofrI   )r=   r   r&   r   r   r   r~   as_ofr
  superget_queryset)rl   hintsr0  r	  histmgrr   s        r6   r  z/HistoricForwardManyToOneDescriptor.get_querysetJ  s    99Z(h(H$OG

''--JJ++11776
 G 7}}WWh@T@T%UVVw#,e,,rD   )r   rv   r  __doc__r   r  __classcell__r   s   @r6   r  r  C  s    -x - -rD   r  c                        e Zd ZdZed        Zy)"HistoricReverseManyToOneDescriptorr  c                     | j                   j                  } G d d|j                  j                        }t	        || j                         S )Nc                        e Zd Z fdZ xZS )\HistoricReverseManyToOneDescriptor.related_manager_cls.<locals>.HistoricRelationModelManagerc           	         	 | j                   j                  | j                  j                  j	                            S # t
        t        f$ r t        | j                   t        d       }t        | j                  t        | j                  j                  dd      d       }|r)|r'|j                  t        |d|j                              }nt        | 9         }| j                  |      cY S w xY w)Nr   r  r  )r0  _prefetched_objects_cacher   r   get_cache_namer3   KeyErrorr   r&   r   r~   r  r
  r  r  _apply_rel_filters)rl   r	  r  r   r   s       r6   r  ziHistoricReverseManyToOneDescriptor.related_manager_cls.<locals>.HistoricRelationModelManager.get_queryseth  s    ===BB

//>>@  '1 =%'GG &

 JJ,,>'
 G 7#*==#GXw7K7KL$ $)7#7#9228<<'=s   :> B*C+*C+)r   rv   r  r  r  r  s   @r6   HistoricRelationModelManagerr  g  s    = =rD   r  )relrelated_model_default_managerr   r   )rl   r  r  s      r6   related_manager_clsz6HistoricReverseManyToOneDescriptor.related_manager_clsc  sA    ..	==+I+I+S+S 	=6 2($((
 	
rD   N)r   rv   r  r  r    r  rI   rD   r6   r  r  \  s      
  
rD   r  c                       e Zd ZdZeZeZy)HistoricForeignKeya  
    Allows foreign keys to work properly from a historic instance.

    If you use as_of queries to extract historical instances from
    a model, and you have other models that are related by foreign
    key and also historic, changing them to a HistoricForeignKey
    field type will allow you to naturally cross the relationship
    boundary at the same point in time as the origin instance.

    A historic instance maintains an attribute ("_historic") when
    it is historic, holding the historic record instance and the
    timepoint used to query it ("_as_of").  HistoricForeignKey
    looks for this and uses an as_of query against the related
    object so the relationship is assessed at the same timepoint.
    N)r   rv   r  r  r  forward_related_accessor_classr  related_accessor_classrI   rD   r6   r  r    s      &H"?rD   r  c                     t        |       duS )zL
    Returns True if the instance was acquired with an as_of timepoint.
    N)to_historicr0  s    r6   is_historicr    s     x ,,rD   c                 $    t        | t        d      S )zn
    Returns a historic model instance if the instance was acquired with
    an as_of timepoint, or None.
    N)r   r&   r  s    r6   r  r    s    
 8=tDDrD   c                       e Zd Zd Zd Zy)r@  c                      || _         || _        y r1   )r   r   )rl   r   r   s      r6   rr   z#HistoricalObjectDescriptor.__init__  s    
.rD   c                     || S | j                   D ci c]#  }|j                  t        ||j                        % }} | j                  di |S c c}w )NrI   )r   r  r   r   )rl   r0  ownerrl  r  s        r6   __get__z"HistoricalObjectDescriptor.__get__  sT    KCGCWCWXa!))WXqyy99XXtzz#F## Ys   (AN)r   rv   r  rr   r  rI   rD   r6   r@  r@    s    /$rD   r@  c            
           e Zd Z	 	 ddddd dee   dee   ddfd	Zdd d
ee   deded   fdZdd dee   deded   fdZ	y)rh   NF)foreign_keys_are_objsold_historyre   included_fieldsr  
ModelDeltac                   t        |t        |             s$t        dt        |        dt        |       d      |
t               }|j                  D ch c]  }|j
                   }}|1|j                  D ch c]  }|j                  s|j
                   }}n|j                  |      }t        |      j                  |      j                  |      }t        |      j                  |      }	g | j                  |||      | j                  ||	|      }
|
j                  d        |
D cg c]  }|j                   }}t        |
|||       S c c}w c c}w c c}w )an  
        :param old_history:
        :param excluded_fields: The names of fields to exclude from diffing.
               This takes precedence over ``included_fields``.
        :param included_fields: The names of the only fields to include when diffing.
               If not provided, all history-tracked fields will be included.
        :param foreign_keys_are_objs: If ``False``, the returned diff will only contain
               the raw PKs of any ``ForeignKey`` fields.
               If ``True``, the diff will contain the actual related model objects
               instead of just the PKs; deleted related objects will be instances of
               ``DeletedObject``.
               Note that passing ``True`` will necessarily query the database if the
               related objects have not been prefetched (using e.g.
               ``select_related()``).
        z"unsupported type(s) for diffing: 'z' and ''c                     | j                   S r1   r  )changes    r6   r  z0HistoricalChanges.diff_against.<locals>.<lambda>  s
     rD   )key)rb   r   rg   r   rJ   r   r   r   intersection
difference_get_field_changes_for_diff_get_m2m_field_changes_for_diffsortr   r  )rl   r  re   r  r  r   included_m2m_fieldsrl  r   r`   changesr  changed_fieldss                r6   diff_againstzHistoricalChanges.diff_against  si   . +tDz2$ZL[(9':!=  "!eO7B7V7VWeuzzWW"/:/I/IX!QZZqvvXOX"5"B"B?"S  Z+,Z( 	
 ,-88I

--V%:
 11Z)>	
 	455<=6&,,=='>;EE1 XX* >s   E9EE/Er   r  ModelChangec                 6   g }t        ||      }t        | |      }|D ]u  |   }|   }||k7  s| j                  j                        |r(t        t              rfd}	 |	||      } |	| |      }t        ||      }
|j                  |
       w |S )%Helper method for ``diff_against()``.rL  c                 t    	 t        |       }|t        j                  |      }|S # t        $ r d }Y 'w xY wr1   )r   r   DeletedObjectr  )recordforeign_keyvaluer   
field_metas      r6   	get_valuez@HistoricalChanges._get_field_changes_for_diff.<locals>.get_value  sH    )$+FE$:E !=$1*2J2JK$XE$  2 )$(E)s   ) 77)r   r~   r  rb   r   r  r   )rl   r  r   r  r  
old_values
new_values	old_value	new_valuer  r  r   r  s              @@r6   r  z-HistoricalChanges._get_field_changes_for_diff  s     ";v>
"47
 	'E"5)I"5)II%!ZZ11%8
(Z
J-O
% !*+y AI )$	 :I$UIyAv&3	'6 rD   r`   c           	         g }|D ]c  }| j                   j                  j                  |      }t        j                  |      }t        ||      j                  |      }t        | |      j                  |      }	|	j                  j                  j                  D 
cg c](  }
|
j                  r|
j                  dvr|
j                  * c}
t         |j                         }t         |	j                         }||k7  s|rFD 
cg c]#  }
t        j                  |
      t              r|
% c}
fd} ||      } ||	      }t        |||      }|j!                  |       f |S c c}
w c c}
w )r  )idr  r	  c                     fd} | j                    D cg c]  }D ci c]  }| |||       c} c}}S c c}w c c}}w )Nc                     	 t        | |      }|=j                  |      }t        | |j                        }t	        |j
                  |      }|S # t        $ r d }Y Nw xY wr1   )r   r   r  r  r  r  )objthrough_fieldr  metar  m2m_through_model_optss        r6   r  zhHistoricalChanges._get_m2m_field_changes_for_diff.<locals>.rows_with_foreign_key_objs.<locals>.get_valueB  sh    -(/](C  %}'='G'G'V.5c4<<.H(5d6H6H+(V#(L $6 -(,-s   A AA)rh  )m2m_qsr  through_objr  	fk_fieldsr  through_model_fieldss       r6   rows_with_foreign_key_objszUHistoricalChanges._get_m2m_field_changes_for_diff.<locals>.rows_with_foreign_key_objsA  s_    )( 0Ev/D/Di/P 
 !, 6J$1 !.ym/T T   s   	A<AA)r  r~   r  r%   get_m2m_reverse_field_namer   r&  r   r   r   r   r  r  rb   r   r  r   )rl   r  r`   r  r  r   original_field_metareverse_field_name
old_m2m_qs
new_m2m_qsrl  old_rowsnew_rowsr  r  r  r  r  s                  @@@r6   r  z1HistoricalChanges._get_m2m_field_changes_for_diff  sz     :	'E"&"4"4":":"D"DU"K!&!A!ABU!V e4==>PQJ u-667IJJ%/%5%5%;%;" 066$::!&&0S"S $ 
 -J--/CDEH-J--/CDEH8#( "6!%&<&F&Fq&I:V !I0  :*EH9*EH$UHh?v&u:	'x a$!s    -E1(E6)NN)
r   rv   r  r   rc   r  rE  r	   r  r  rI   rD   r6   rh   rh     s     *.)-	7F $7F(7F "#7F "#	7F 
7Fr'(' '  $	'
 
m	'RE(E SME  $	E
 
m	ErD   rh   T)frozenc                   B    e Zd ZU eej
                     ed<   eed<   d Zy)r  r   r:   c                     t        d      d| j                  j                  j                  iz  }| d| j                   dS )NzDeleted %(type_name)s	type_namez (pk=))r  r   r~   rm   r:   )rl   deleted_model_strs     r6   r  zDeletedObject.__str__g  sG    56))66:
 
 $$E$''!44rD   N)	r   rv   r  r   r   r  __annotations__r   r  rI   rD   r6   r  r  b  s    G5rD   r  c                   ,    e Zd ZU eed<   eed<   eed<   y)r  r   oldnewN)r   rv   r  rc   r  ModelChangeValuerI   rD   r6   r  r    s    J		rD   r  c                   B    e Zd ZU ee   ed<   ee   ed<   eed<   eed<   y)r  r  r  
old_record
new_recordN)r   rv   r  r
   r  r  rc   rh   rI   rD   r6   r  r    s#    k""SM!!!!!rD   r  )dr   r   r   r   dataclassesr   	functoolsr   typingr   r   r   r   r	   r
   r   r   r  django.appsr   django.confr   django.contribr   django.contrib.authr   django.core.exceptionsr   r   	django.dbr   django.db.modelsr   django.db.models.fields.proxyr   django.db.models.fields.relatedr   +django.db.models.fields.related_descriptorsr   r   r   django.db.models.queryr   django.db.models.signalsr   django.forms.modelsr   django.urlsr   django.utilsr   django.utils.encodingr   django.utils.functionalr    django.utils.textr!   django.utils.translationr"   r   r$   r%   r   r&   r'   r(   r)   ry   r*   r+   r,   r-   asgiref.localr.   r  ImportError	threadingr/   r  ModelTypeHintobjectr   r7   rA   rC   rF   r   r  r  r  r  r  r@  rh   r  rc   r  r  r  rI   rD   r6   <module>r     s       !  R R R       . K  , 2 6 
 , 0 -  ! + 3 ) 6   03 LLMM 6
GP GPT#L-)C -2(
)C (
V@ @*-E	$ 	$h hV $5 5 54 mT$sE#}BT<U7U2V-WWX  $   $" " "m"  0/0s   F FF