
    Bsi^%                         d dl 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mZmZmZmZ d dlmZ d dlmZ d dlmZ d	 Zd
 ZddZdefdZddee   deegef   fdZdedefdZ	 	 ddee   dee   fdZy)    Ntimezone)CallableOptional)settings)ObjectDoesNotExist)NOT_PROVIDEDDateTimeField
ForeignKey	JSONFieldModel)	smart_str)import_stringc                 x    ddl m} | j                  ryt        | dd      | j                  j
                  |k(  ryy)a.  
    Returns whether the given field should be tracked by Auditlog.

    Untracked fields are many-to-many relations and relations to the Auditlog LogEntry model.

    :param field: The field to check.
    :type field: Field
    :return: Whether the given field should be tracked.
    :rtype: bool
    r   )LogEntryFremote_fieldNT)auditlog.modelsr   many_to_manygetattrr   model)fieldr   s     Y/var/www/python-projects/worksol/worksolenv/lib/python3.12/site-packages/auditlog/diff.pytrack_fieldr      s@     )  	~t,8$$0    c                     t        | t              sJ | j                  j                         D cg c]  }t	        |      s| c}S c c}w )aZ  
    Returns the list of fields in the given model instance. Checks whether to use the official
    _meta API or use the raw data. This method excludes many to many fields.

    :param instance: The model instance to get the fields for
    :type instance: Model
    :return: The list of fields for the given model (instance)
    :rtype: list
    )
isinstancer   _meta
get_fieldsr   )instancefs     r   get_fields_in_modelr!   (   s;     h&&&~~002E!k!nAEEEs   A Ac                      fd}	 t        t              rzt         j                        }	 j	                  |      }|<t        j                  r+t        j                  |      st        j                  |t        j                        }	 |S t        t              rLj	                  t         j                              }|s	 t        j                  |dj                         }|S j"                  sj$                  r3t'        d      r't)        t         j+                               d      }|S t         j                        }|s.t)        |      }t-        |      j.                  dk(  rt1        |      }|S # t
        $ r |cY S w xY w# t
        $ r Y |S w xY w# t2        t4        f$ r
  |       cY S w xY w)a  
    Gets the value of a given model instance field.

    :param obj: The model instance.
    :type obj: Model
    :param field: The field you want to find the value of.
    :type field: Any
    :return: The value of the field as a string.
    :rtype: str
    c                      	 j                   j                  j                        } | j                  }|t        u ryt        |      r |       S |S # t        $ r Y yw xY w)z
        Attempts to get the default value for a field from the model's field definition.

        :return: The default value of the field or None
        N)r   	get_fieldnamedefaultr	   callableAttributeError)model_fieldr&   r   objs     r   get_default_valuez*get_field_value.<locals>.get_default_valueC   s]    	))--ejj9K!))G,& y N 		s   9A A A 	AAr   T)	sort_keyscls	rel_class)strings_only	__proxy__)r   r
   r   r%   	to_python	TypeErrorr   USE_TZdjango_timezoneis_naive
make_naiver   utcr   jsondumpsencoder
one_to_onemany_to_onehasattrr   get_attnametype__name__strr   r(   )r*   r   use_json_for_changesr+   values   ``   r   get_field_valuerD   7   s   &#e]+ C,E. !OO'007'2258<<P& L% y)OOGC$<=E' JJu%--PE L %"3"39Tgc5+<+<+>?dSE L C,E'!%(;'';6JE L5   !  L / # ""#sg   &F$ F AF$ 7F$ "F 0A	F$ ;AF$ FF$ FF$ 	F!F$  F!!F$ $F=<F=returnc           	          t        d      t        t        t        t        t
        t        t        t        f	}t        | |      S )z
    Checks if the given object is a primitive Python type that can be safely serialized to JSON.

    :param obj: The object to check
    :return: True if the object is a primitive type, False otherwise
    :rtype: bool
    N)
r?   boolintfloatrA   listtupledictsetr   )r*   primitive_typess     r   is_primitiverO   z   s-     Dz4eS$tSQOc?++r   mask_callablec                 b    | rt        |       S t        j                  }|rt        |      S t        S )a  
    Get the masking function to use based on the following priority:
    1. Model-specific mask_callable if provided
    2. mask_callable from settings if configured
    3. Default mask_str function

    :param mask_callable: The dotted path to a callable that will be used for masking.
    :type mask_callable: str
    :return: A callable that takes a string and returns a masked version.
    :rtype: Callable[[str], str]
    )r   r   AUDITLOG_MASK_CALLABLEmask_str)rP   default_mask_callables     r   get_mask_functionrU      s2     ]++$;;233Or   rC   c                 F    t        t        |       dz        }d|z  | |d z   S )z
    Masks the first half of the input string to remove sensitive data.

    :param value: The value to mask.
    :type value: str
    :return: The masked version of the string.
    :rtype: str
       *N)rH   len)rC   
mask_limits     r   rS   rS      s-     SZ!^$JeJK000r   oldnewc                    ddl m} | t        | t              st	        d      |t        |t              st	        d      i }| ^|\t        | j                  j                  |j                  j                  z         }|j                  |j                  j                        }n| :t        t        |             }|j                  | j                  j                        }nH|:t        t        |            }|j                  |j                  j                        }nt               }d}|r;|D ch c]0  }t        |t              r|j                  |v s|j                  |v r|2 }}|r]|d   s|d   rS|rQg }	|d   r!|D cg c]  }|j                  |d   v r| }	}n|}	|d   r |	D cg c]  }|j                  |d   vr| }	}|	}|D ]  }t        | ||      }
t        |||      }|
|k7  s#|r[|j                  |d   v rJt        |j!                  d	            } |t#        |
             |t#        |            f||j                  <   |s$t#        |
      t#        |      f||j                  <   t%        |
      st#        |
      }
t%        |      st#        |      }|
|f||j                  <    t'        |      dk(  rd}|S c c}w c c}w c c}w )
a  
    Calculates the differences between two model instances. One of the instances may be ``None``
    (i.e., a newly created model or deleted model). This will cause all fields with a value to have
    changed (from ``None``).

    :param old: The old state of the model instance.
    :type old: Model
    :param new: The new state of the model instance.
    :type new: Model
    :param fields_to_check: An iterable of the field names to restrict the diff to, while ignoring the rest of
        the model's fields. This is used to pass the `update_fields` kwarg from the model's `save` method.
    :param use_json_for_changes: whether or not to use a JSON for changes
        (see settings.AUDITLOG_STORE_JSON_CHANGES)
    :type fields_to_check: Iterable
    :return: A dictionary with the names of the changed fields as keys and a two tuple of the old and new
            field values as value.
    :rtype: dict
    r   )auditlogNz8The supplied old instance is not a valid model instance.z8The supplied new instance is not a valid model instance.include_fieldsexclude_fieldsmask_fieldsrP   )auditlog.registryr^   r   r   r2   rM   r   fieldsget_model_fieldsr   r!   r   attnamer%   rD   rU   getr   rO   rY   )r[   r\   fields_to_checkrB   r^   diffrc   model_fieldsr   filtered_fields	old_value	new_value	mask_funcs                r   model_instance_diffrn      s   0 +K:c51RSSK:c51RSSD
3?SYY%%		(8(88900A	(-.00A	(-.00A  
E:.5==O3SJJ/1	 
 
 	*+|<L/M() $::.>!?? O  %O() -::\2B%CC O 
 ! >#C0DE	#C0DE		!

l=.I I-l.>.>.OP	 i	23i	23$UZZ 
 ,(1)(<i	>R'SD$ (	2$-i$8	'	2$-i$8	(19'=D$1>4 4yA~K{
"s   -5J<=K%K)F)N)NF)r8   datetimer   typingr   r   django.confr   django.core.exceptionsr   django.db.modelsr	   r
   r   r   r   django.utilsr4   django.utils.encodingr   django.utils.module_loadingr   r   r!   rD   rG   rO   rA   rU   rS   rn    r   r   <module>rx      s      %   5 V V 4 + 56F@F	, 	,Xc] hucz>R .
1C 
1C 
1  	l	%l	%lr   