
    NwgA                       d dl 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mZmZmZ d dlmZ d dlmZ d dlmZ er#d dlmZmZ d d	lmZ  G d
 dej4                        Z ed      Z G d dee         Z G d dee         Z G d de      Zd#dZ  G d de	e         Z! G d de!e         Z" G d d      Z# G d d      Z$ G d d      Z% G d de$      Z& G d  d!e%      Z'y")$    )annotations)deepcopywraps)TYPE_CHECKINGAnyGenericIterableProtocolTypeVarcastoverload)
FieldError)models)	FieldFile)CallableMapping)TracebackTypec                  "    e Zd ZU ded<   ded<   y)_AugmentedModelbool_instance_initializedset[str]_deferred_fieldsN)__name__
__module____qualname____annotations__     J/var/www/horilla/myenv/lib/python3.12/site-packages/model_utils/tracker.pyr   r      s    ##""r    r   Tc                      e Zd ZddZddZy)
Descriptorc                     y Nr   selfinstanceowners      r!   __get__zDescriptor.__get__        r    c                     y r&   r   )r(   r)   values      r!   __set__zDescriptor.__set__#   r,   r    N)r)   objectr*   ztype[object]returnr"   )r)   r0   r.   r"   r1   None)r   r   r   r+   r/   r   r    r!   r$   r$      s    r    r$   c                      e Zd ZddZy)FullDescriptorc                     y r&   r   )r(   r)   s     r!   
__delete__zFullDescriptor.__delete__(   r,   r    N)r)   r0   r1   r2   )r   r   r   r6   r   r    r!   r4   r4   '   s    r    r4   c                  $     e Zd ZdZd fdZ xZS )LightStateFieldFilea  
    FieldFile subclass with the only aim to remove the instance from the state.

    The change introduced in Django 3.1 on FieldFile subclasses results in pickling the
    whole instance for every field tracked.
    As this is done on the initialization of objects, a simple queryset evaluation on
    Django 3.1+ can make the app unusable, as CPU and memory usage gets easily
    multiplied by magnitudes.
    c                6    t         |          }d|v rd|d<   |S )zQ
        We don't need to deepcopy the instance, so nullify if provided.
        r)   N)super__getstate__)r(   state	__class__s     r!   r;   z LightStateFieldFile.__getstate__6   s)     $& $E*r    r1   dict[str, Any])r   r   r   __doc__r;   __classcell__)r=   s   @r!   r8   r8   ,   s     r    r8   c                    t        | t              r:t        t        t	        | j
                  | j                  | j                              } t        |       S )zZ
    Use our lightweight class to avoid copying the instance on a FieldFile deepcopy.
    )r)   fieldname)	
isinstancer   r   r"   r8   r)   rC   rD   r   )r.   s    r!   lightweight_deepcopyrF   @   sC     %#Q+^^++
 
 E?r    c                  b    e Zd Zd	dZed
d       Zedd       ZddZddZddZedd       Z	y)DescriptorWrapperc                .    || _         || _        || _        y r&   )
field_name
descriptortracker_attname)r(   rJ   rK   rL   s       r!   __init__zDescriptorWrapper.__init__O   s    $$.r    c                     y r&   r   r'   s      r!   r+   zDescriptorWrapper.__get__T       r    c                     y r&   r   r'   s      r!   r+   zDescriptorWrapper.__get__X   rO   r    c                    || S | j                   |j                         v }| j                  j                  ||      }|r8t	        || j
                        }t        |      |j                  | j                   <   |S r&   )rJ   get_deferred_fieldsrK   r+   getattrrL   rF   
saved_data)r(   r)   r*   was_deferredr.   tracker_instances         r!   r+   zDescriptorWrapper.__get__\   sp    K(*F*F*HH''%8&x1E1EF;OPU;V''8r    c                   t        |d      }| j                  |j                         v }d| j                  z   }t        ||      }|rD|rB|s@t        ||d       	 t	        || j                         |j
                  j                  |d        t        | j                  d      r| j                  j                  ||       y ||j
                  | j                  <   y # |j
                  j                  |d        w xY w)Nr   	_setting_Tr/   )	hasattrrJ   rR   setattrrS   __dict__poprK   r/   )r(   r)   r.   initializedrU   recursion_sentinel_attnamealready_settings          r!   r/   zDescriptorWrapper.__set__f   s    h(?@(*F*F*HH
 &14??%B"!(,FG<H8$?H $//2!!%%&@$G4??I.OO##He416Hdoo.	 !!%%&@$Gs   C C5c                .    t        | j                  |      S r&   )rS   rK   )r(   attrs     r!   __getattr__zDescriptorWrapper.__getattr__}   s    t--r    c                2    t        | d      rt        S t        S )Nr6   )rY   FullDescriptorWrapperrH   )rK   s    r!   cls_for_descriptorz$DescriptorWrapper.cls_for_descriptor   s    :|,(($$r    N)rJ   strrK   Descriptor[T]rL   rf   )r)   r2   r*   type[models.Model]r1   zDescriptorWrapper[T])r)   models.Modelr*   rh   r1   r"   )r)   models.Model | Noner*   rh   r1   zDescriptorWrapper[T] | T)r)   ri   r.   r"   r1   r2   )ra   rf   r1   r"   )rK   rg   r1   ztype[DescriptorWrapper[T]])
r   r   r   rM   r   r+   r/   rb   staticmethodre   r   r    r!   rH   rH   M   sR    /
    7.. % %r    rH   c                      e Zd ZdZddZy)rd   zD
    Wrapper for descriptors with all three descriptor methods.
    c                d    t        t        t           | j                        j	                  |       y r&   )r   r4   r"   rK   r6   )r(   objs     r!   r6   z FullDescriptorWrapper.__delete__   s     ^A0;;C@r    N)rn   ri   r1   r2   )r   r   r   r@   r6   r   r    r!   rd   rd      s    Ar    rd   c                  H    e Zd ZdZdd	 	 	 	 	 ddZddZ	 	 	 	 	 	 	 	 d	dZy)
FieldsContexta  
    A context manager for tracking nested reset fields contexts.

    If tracked fields is mentioned in more than one FieldsContext, it's state
    is being reset on exiting last context that mentions that field.

    >>> with fields_context(obj.tracker, 'f1', state=state):
    ...     with fields_context(obj.tracker, 'f1', 'f2', state=state):
    ...         obj.do_something_useful()
    ...     # f2 is reset after inner context exit
    ...     obj.do_something_else()
    ... # f1 is reset after outer context exit
    >>>

    * Note that fields are counted by passing same state dict
    * FieldsContext is instantiated using FieldInstanceTracker (`obj.tracker`)
    * Different objects has own state stack

    N)r<   c               6    |i }|| _         || _        || _        y)a  
        :param tracker: FieldInstanceTracker instance to be reset after
            context exit
        :param fields: a list of field names to be tracked in current context
        :param state: shared state dict used to count number of field
            occurrences in context stack.

        On context enter each field mentioned in `fields` has +1 in shared
        state, and on exit it receives -1. Fields that have zero after context
        exit are reset in tracker instance.
        N)trackerfieldsr<   )r(   rr   r<   rs   s       r!   rM   zFieldsContext.__init__   s#    " =E
r    c                    | j                   D ]5  }| j                  j                  |d       | j                  |xx   dz  cc<   7 | S )zN
        Increments tracked fields occurrences count in shared state.
        r      )rs   r<   
setdefault)r(   fs     r!   	__enter__zFieldsContext.__enter__   sD      	AJJ!!!Q'JJqMQM	 r    c                    g }| j                   D ]J  }| j                  |xx   dz  cc<   | j                  |   dk(  s-|j                  |       | j                  |= L |r| j                  j	                  |       yy)z
        Decrements tracked fields occurrences count in shared state.

        If any field has no more occurrences in shared state, this field is
        being reset by tracker.
        ru   r   rs   N)rs   r<   appendrr   set_saved_fields)r(   exc_typeexc_valexc_tbreset_fieldsrw   s         r!   __exit__zFieldsContext.__exit__   sv      	"AJJqMQMzz!}!##A&JJqM		"
 LL)))> r    )rr   FieldInstanceTrackerrs   rf   r<   zdict[str, int] | Noner1   rp   r}   ztype[BaseException] | Noner~   zBaseException | Noner   zTracebackType | Noner1   r2   )r   r   r   r@   rM   rx   r   r   r    r!   rp   rp      s]    0 (,	%  %	.?,? &? %	?
 
?r    rp   c                      e Zd ZddZddZ	 	 	 	 	 	 	 	 ddZddZedd       ZddZ	dddZ
ddd	Zdd
ZddZddZy)r   c                x    t        d|      | _        || _        || _        t	        | g| j                   | _        y )Nr   )r   r)   rs   	field_maprp   context)r(   r)   rs   r   s       r!   rM   zFieldInstanceTracker.__init__   s4    .9"$T8DKK8r    c                6    | j                   j                         S r&   )r   rx   r(   s    r!   rx   zFieldInstanceTracker.__enter__   s    ||%%''r    c                <    | j                   j                  |||      S r&   )r   r   )r(   r}   r~   r   s       r!   r   zFieldInstanceTracker.__exit__   s     ||$$Xw??r    c                H    t        | g|d| j                  j                  iS )Nr<   )rp   r   r<   r(   rs   s     r!   __call__zFieldInstanceTracker.__call__   s!    TEFE$,,2D2DEEr    c                6    | j                   j                         S r&   )r)   rR   r   s    r!   deferred_fieldsz$FieldInstanceTracker.deferred_fields   s    }}0022r    c                H    t        | j                  | j                  |         S r&   )rS   r)   r   r(   rC   s     r!   get_field_valuez$FieldInstanceTracker.get_field_value   s    t}}dnnU&;<<r    Nc                <   | j                   j                  si | _        nD|| j                         | _        n, | j                  j                  di | j                  |       | j                  j                         D ]  \  }}t        |      | j                  |<    y )Nrz   r   )r)   pkrT   currentupdateitemsrF   )r(   rs   rC   field_values       r!   r|   z%FieldInstanceTracker.set_saved_fields   s    }} DO^"llnDO"DOO""AT\\\%@A #'//"7"7"9 	GE;%9+%FDOOE"	Gr    c                    |8| j                   }|r| j                  D cg c]  }||vr|
 }}n| j                  }|D ci c]  }|| j                  |       c}S c c}w c c}w )z5Returns dict of current values for all tracked fields)r   rs   r   )r(   rs   r   rC   rw   s        r!   r   zFieldInstanceTracker.current  st    >"22O'+{{#O3  
 4:;q4''**;; <s
   AA c                    || j                   v rN|| j                  v r|| j                  j                  vry| j	                  |      }| j                  |      }||k7  S t        d|z        )@Returns ``True`` if field has changed from currently saved valueFfield "%s" not tracked)rs   r   r)   r[   previousr   r   r(   rC   prevcurrs       r!   has_changedz FieldInstanceTracker.has_changed  si    DKK,,,dmm>T>T1T==/D//6D4<5=>>r    c                   | j                   j                  r|| j                  v r|| j                  vr|| j                   j                  vr| j                  |       ny| j                  |      }| j                   j                  |g       t        | j                  |            | j                  |<   t        | j                   | j                  |   |       | j                  j                  |      S )z,Returns currently saved value of given fieldrz   )r)   r   r   rT   r[   r   refresh_from_dbrF   rZ   r   get)r(   rC   current_values      r!   r   zFieldInstanceTracker.previous  s     ==)=)= =%tB^ DMM222$$U+
 !% 4 4U ;--eW-=)=d>R>RSX>Y)Z&t~~e'<mL""5))r    c                    | j                   D ci c]%  }| j                  |      r|| j                  |      ' c}S c c}w z@Returns dict of fields that changed since save (with old values))rs   r   r   r   s     r!   changedzFieldInstanceTracker.changed1  sD     
& 4==''
 	
 
s   *<)r)   ri   rs   zIterable[str]r   zMapping[str, str]r   r   )rs   rf   r1   rp   )r1   r   )rC   rf   r1   r   r&   )rs   Iterable[str] | Noner1   r2   )rs   r   r1   r?   rC   rf   r1   r   r>   )r   r   r   rM   rx   r   r   propertyr   r   r|   r   r   r   r   r   r    r!   r   r      su    9(@,@ &@ %	@
 
@F 3 3=
G<
?*(
r    r   c                      e Zd ZeZdddZe	 	 d	 	 	 	 	 dd       Ze	 d	 	 	 	 	 dd       Z	 	 d	 	 	 	 	 ddZddZddZ	ddZ
	 	 	 	 	 	 	 	 dd	Zdd
ZddZddZedd       Zedd       ZddZy)FieldTrackerNc                <    t        t        t           |      | _        y r&   )r   r
   rf   rs   r   s     r!   rM   zFieldTracker.__init__>  s    8C=&1r    c                     y r&   r   r(   funcrs   s      r!   r   zFieldTracker.__call__B       	r    c                     y r&   r   r   s      r!   r   zFieldTracker.__call__J  r   r    c                ,     d fd}||S  ||      S )Nc                6     t               d fd       }|S )Nc                    t        | j                        }|j                  n} || 5   | g|i |cd d d        S # 1 sw Y   y xY wr&   )rS   attnamers   )rn   argskwargsrr   
field_listrw   rs   r(   s        r!   innerz7FieldTracker.__call__.<locals>.decorator.<locals>.innerX  sQ    !#t||4/5~W^^6
j) 3S242623 3 3s   AA)rn   ri   r   r0   r   r0   r1   r"   r   )rw   r   rs   r(   s   ` r!   	decoratorz(FieldTracker.__call__.<locals>.decoratorW  s     1X3 3 Lr    )rw   Callable[..., T]r1   r   r   )r(   r   rs   r   s   ` ` r!   r   zFieldTracker.__call__R  s    
	 <r    c           
     :   | j                   D ci c]  }|| }}|j                  j                   D ci c]  }|j                  |j                   }} |j                  di |j                         D ci c]  \  }}||v r|| c}} |S c c}w c c}w c c}}w )z:Returns dict mapping fields names to model attribute namesr   )rs   _metarD   r   r   r   )r(   clsrC   r   rw   
all_fieldskvs           r!   get_field_mapzFieldTracker.get_field_mapd  s    /3{{;eUE\;	;141A1ABAaffaii'B
B	 	0z/?/?/A /Va I~ qD / 	0	 <B/s   
BB4Bc                    || _         d|z  | _        t        j                  j                  j                  | j                  |       y )Nz_%s)sender)rD   r   r   signalsclass_preparedconnectfinalize_class)r(   r   rD   s      r!   contribute_to_classz FieldTracker.contribute_to_classl  s7    	t|%%--d.A.A#-Nr    c                   | j                   t        r"d |j                  j                   D        | _         t        | j                         | _         | j                   D ]D  }t	        ||      }t
        j                  |      } |||| j                        }t        |||       F | j                  |      | _
        | j                  |       || _        t        || j                  |        | j                  |       y )Nc              3  4   K   | ]  }|j                     y wr&   )r   ).0rC   s     r!   	<genexpr>z.FieldTracker.finalize_class.<locals>.<genexpr>s  s     JU5==Js   )rs   r   r   setrS   rH   re   r   rZ   r   r   
patch_initmodel_classrD   
patch_save)r(   r   r   rJ   rK   wrapper_clswrapped_descriptors          r!   r   zFieldTracker.finalize_classq  s    ;;-Jfll6I6IJDK$++&++ 	<J181LJ+>>zJK!,ZT\\!RFJ(:;		<
 ++F3!		4(r    c                    t        || j                        sy | j                  || j                  | j                        }t        || j                  |       |j                          dt        d|      _	        y )NTr   )
rE   r   tracker_classrs   r   rZ   r   r|   r   r   )r(   r   r)   r   rr   s        r!   initialize_trackerzFieldTracker.initialize_tracker  s_     (D$4$45$$Xt{{DNNK$,,0  "BF)?r    c                h     t        d      t              d fd       }t        d|       y )NrM   c                B     | g|i | j                  |        y r&   )r   )r)   r   r   modeloriginalr(   s      r!   r   z&FieldTracker.patch_init.<locals>.inner  s%    X///##E84r    )r)   ri   r   r   r   r   r1   r2   rS   r   rZ   )r(   r   r   r   s   `` @r!   r   zFieldTracker.patch_init  s3    5*-	x	5 
	5 	z5)r    c                P    | j                  |dd       | j                  |dd       y )N	save_baseupdate_fieldsr   rs   )_patch)r(   r   s     r!   r   zFieldTracker.patch_save  s#    E;8E,h7r    c                h     t        ||      t              d fd       }t        |||       y )Nc                    |j                        }|j                  }nfd|D        }t        | j                        } || 5   | g|i |cd d d        S # 1 sw Y   y xY w)Nc              3  >   K   | ]  }|j                   v r|  y wr&   rz   )r   rC   r(   s     r!   r   z5FieldTracker._patch.<locals>.inner.<locals>.<genexpr>  s%      #T[[( s   )r   rs   rS   r   )	r)   r   r   r   rs   rr   fields_kwargr   r(   s	         r!   r   z"FieldTracker._patch.<locals>.inner  sp    28**\2JM$'4 h5G&! ;:4:6:; ; ;s   AA')r)   ri   r   r0   r   r   r1   r0   r   )r(   r   methodr   r   r   s   `  ` @r!   r   zFieldTracker._patch  s3    5&)	x	; 
	; 	vu%r    c                     y r&   r   r'   s      r!   r+   zFieldTracker.__get__  rO   r    c                     y r&   r   r'   s      r!   r+   zFieldTracker.__get__  rO   r    c                6    || S t        || j                        S r&   )rS   r   r'   s      r!   r+   zFieldTracker.__get__  s    K8T\\22r    r&   )rs   r   )NN)r   r2   rs   r   r1   z.Callable[[Callable[..., T]], Callable[..., T]])r   r   rs   r   r1   r   )r   zCallable[..., T] | Noners   r   r1   zACallable[[Callable[..., T]], Callable[..., T]] | Callable[..., T]r   rh   r1   zdict[str, str])r   rh   rD   rf   r1   r2   )r   rh   r   r0   r1   r2   )r   rh   r)   ri   r   r0   r1   r2   )r   rh   r1   r2   )r   rh   r   rf   r   rf   r1   r2   )r)   r2   r*   rh   r1   r   )r)   ri   r*   rh   r1   r   )r)   rj   r*   rh   r1   z#FieldTracker | FieldInstanceTracker)r   r   r   r   r   rM   r   r   r   r   r   r   r   r   r   r+   r   r    r!   r   r   :  s   (M2  '+ % 
8	   (, % 
	  )-'+% % 
K	$O
 G"G G 	G
 
G*8&&    3r    r   c                      e Zd ZddZddZy)ModelInstanceTrackerc                    | j                   j                  sy|| j                  v r'| j                  |      }| j	                  |      }||k7  S t        d|z        )r   Tr   )r)   r   rT   r   r   r   r   s       r!   r   z ModelInstanceTracker.has_changed  sW    }}doo%==/D//6D4<5=>>r    c                    | j                   j                  si S | j                  j                         }| j	                         }|D ci c]  \  }}|||   k7  s|| c}}S c c}}w r   )r)   r   rT   r   r   )r(   savedr   r   r   s        r!   r   zModelInstanceTracker.changed  sW    }}I%%',,.!&:A!wqz/1:::s   A"A"Nr   r>   )r   r   r   r   r   r   r    r!   r   r     s    	?;r    r   c                      e Zd ZeZddZy)ModelTrackerc                B    | j                   D ci c]  }|| c}S c c}w r&   rz   )r(   r   rC   s      r!   r   zModelTracker.get_field_map  s    *.++6u666s   
Nr   )r   r   r   r   r   r   r   r    r!   r   r     s    (M7r    r   N)r.   r"   r1   r"   )(
__future__r   copyr   	functoolsr   typingr   r   r	   r
   r   r   r   r   django.core.exceptionsr   	django.dbr   django.db.models.fields.filesr   collections.abcr   r   typesr   Modelr   r"   r$   r4   r8   rF   rH   rd   rp   r   r   r   r   r   r    r!   <module>r      s    "  	 	 	 .  31##&,, # CL! Z] 
) (
8%
 8%vA-a0 AH? H?V\
 \
~@3 @3F;/ ;,7< 7r    