
    NwgG%                         d dl Z d dlmZ d dlmZmZmZmZmZm	Z	m
Z
 d dlmZmZ d dlmZ d dlmZmZ d dlmZ dd	lmZmZmZmZ dd
lmZ dedefdZdedefdZ G d d      Z  G d d      Z!y)    N)commonprefix)AnyDictFinalListTupleTypeUnion)ManyToManyFieldModel)conditional_escape)
SafeString	mark_safe)capfirst   )HistoricalChangesModelChangeModelChangeValue
ModelDelta)get_m2m_reverse_field_nameobjreturnc                 <    t        | t              r| S t        |       S )z@
    Converts ``obj`` to a string, unless it's already one.
    )
isinstancestr)r   s    T/var/www/horilla/myenv/lib/python3.12/site-packages/simple_history/template_utils.pyconditional_strr      s     #s
s8O    sc                     t        | d      S )z
    Returns whether ``s`` is a (presumably) pre-escaped string or not.

    This relies on the same ``__html__`` convention as Django's ``conditional_escape``
    does.
    __html__)hasattr)r   s    r   is_safe_strr#      s     1j!!r   c            
           e Zd ZU dZdZeed<   eddee   de	fdZ
ded	eeeef      fd
Zded	efdZdeded	efdZdededed	eeef   fdZddZy)HistoricalRecordContextHelperzm
    Class containing various utilities for formatting the template context for
    a historical record.
    d   (DEFAULT_MAX_DISPLAYED_DELTA_CHANGE_CHARS) max_displayed_delta_change_charsmodelhistorical_recordc                .    || _         || _        || _        y N)r)   recordr(   )selfr)   r*   r(   s       r   __init__z&HistoricalRecordContextHelper.__init__)   s     
'0P-r   deltar   c                     g }|j                   D ]F  }| j                  |      }|j                  |j                  |j                  |j
                  d       H |S )a  
        Return the template context for ``delta.changes``.
        By default, this is a list of dicts with the keys ``"field"``,
        ``"old"`` and ``"new"`` -- corresponding to the fields of ``ModelChange``.

        :param delta: The result from calling ``diff_against()`` with another historical
               record. Its ``old_record`` or ``new_record`` field should have been
               assigned to ``self.record``.
        fieldoldnew)changesformat_delta_changeappendr3   r4   r5   )r.   r0   context_listchangeformatted_changes        r   context_for_delta_changesz7HistoricalRecordContextHelper.context_for_delta_changes5   sc     mm 	F#77?-33+//+//	 r   r:   c                 T   | j                  ||j                        }| j                  ||j                        }| j                  |||      \  }}| j                  j
                  j                  |j                        }t        j                  |t        |j                        ||      S )zs
        Return a ``ModelChange`` object with fields formatted for being used as
        template context.
        r2   )prepare_delta_change_valuer4   r5   stringify_delta_change_valuesr)   _meta	get_fieldr3   dataclassesreplacer   verbose_name)r.   r:   r4   r5   
field_metas        r   r7   z1HistoricalRecordContextHelper.format_delta_changeK   s    
 --ffjjA--ffjjA55fc3GSZZ%%//=
"":223	
 	
r   valuec                     | j                   j                  j                  |j                        }t	        |t
              rt        |      }|D cg c]  }||   	 }}|S |}|S c c}w )a  
        Return the prepared value for the ``old`` and ``new`` fields of ``change``,
        before it's passed through ``stringify_delta_change_values()`` (in
        ``format_delta_change()``).

        For example, if ``value`` is a list of M2M related objects, it could be
        "prepared" by replacing the related objects with custom string representations.

        :param change:
        :param value: Either ``change.old`` or ``change.new``.
        )r)   r@   rA   r3   r   r   r   )r.   r:   rF   rE   reverse_field_nameobj_values_dictdisplay_values          r   r>   z8HistoricalRecordContextHelper.prepare_delta_change_value]   su      ZZ%%//=
j/2!;J!G LQ8G 23M 
  "Ms   A#r4   r5   c                     dt         dt        t        t        f   fd} ||       ||      }}| j	                         }|j                  ||      \  }}	t        |      t        |	      fS )a  
        Called by ``format_delta_change()`` after ``old`` and ``new`` have been
        prepared by ``prepare_delta_change_value()``.

        Return a tuple -- ``(old, new)`` -- where each element has been
        escaped/sanitized and turned into strings, ready to be displayed in a template.
        These can be HTML strings (remember to pass them through ``mark_safe()`` *after*
        escaping).

        If ``old`` or ``new`` are instances of ``list``, the default implementation will
        use each list element's ``__str__()`` method, and also reapply ``mark_safe()``
        if all the passed elements are safe strings.
        rF   r   c                     t        | t              rIddj                  t        t        |              d}t        t        t        |             rt        |      }|S t	        |       }|S )N[z, ])r   listjoinmapr   allr#   r   )rF   strings     r   stringify_valuezTHistoricalRecordContextHelper.stringify_delta_change_values.<locals>.stringify_value   s^     %&TYYs?E'BCDAFs;./&v.F M )/Mr   )r   r
   r   r   get_obj_diff_displaycommon_shorten_reprr   )
r.   r:   r4   r5   rT   old_strnew_strdiff_display	old_short	new_shorts
             r   r?   z;HistoricalRecordContextHelper.stringify_delta_change_valuesx   sp    "
	3 
	5j+A 
	 +3/1E002+??Q	9 "),.@.KKKr   c                 .    t        | j                        S )z
        Return an instance of ``ObjDiffDisplay`` that will be used in
        ``stringify_delta_change_values()`` to display the difference between
        the old and new values of a ``ModelChange``.
        )
max_length)ObjDiffDisplayr(   )r.   s    r   rU   z2HistoricalRecordContextHelper.get_obj_diff_display   s     )N)NOOr   N)r   r^   )__name__
__module____qualname____doc__r'   r   __annotations__r	   r   r   r/   r   r   r   r   r   r<   r   r7   r   r>   r   r   r?   rU    r   r   r%   r%   !   s    
 7:,e9 *R
QE{
Q -
Qz d4S>>R ,
+ 
+ 
$   
	6#L!#L(+#L25#L	z:%	&#LJPr   r%   c                   n    e Zd ZdZdddddddZdedeed	f   fd
Zdede	de	defdZ
dede	dedefdZy)r^   a&  
    A class grouping functions and settings related to displaying the textual
    difference between two (or more) objects.
    ``common_shorten_repr()`` is the main method for this.

    The code is based on
    https://github.com/python/cpython/blob/v3.12.0/Lib/unittest/util.py#L8-L52.
    P         )r]   placeholder_lenmin_begin_lenmin_end_lenmin_common_lenc                    || _         || _        || _        || _        || _        |||z   |z   |z   |z   z
  | _        | j
                  dk\  sJ y )Nr   )r]   ri   rj   rk   rl   min_diff_len)r.   r]   ri   rj   rk   rl   s         r   r/   zObjDiffDisplay.__init__   su     %.*&,&  	
   A%%%r   argsr   .c                     t        t        t        |            }t        t        t        |            }| j
                  k  r|S t        |      t	               j
                  |z
   j                  z    j                  z   z
  }| j                  kD  rm j                   j                  z    j                  z   |z
  z    j
                  k  sJ  j                   j                  |      t        fd|D              S  j                   j                   j                        t         fd|D              S )a6  
        Returns ``args`` with each element converted into a string representation.
        If any of the strings are longer than ``self.max_length``, they're all shortened
        so that the first differences between the strings (after a potential common
        prefix in all of them) are lined up.
        c              3   0   K   | ]  } |d     y wr,   rd   ).0r   prefix
prefix_lens     r   	<genexpr>z5ObjDiffDisplay.common_shorten_repr.<locals>.<genexpr>   s!     CF8AjkN#34Cs   c              3   x   K   | ]1  }j                  |d  j                  j                        z    3 y wr,   )shortenrn   rk   )rr   r   rs   rt   r.   s     r   ru   z5ObjDiffDisplay.common_shorten_repr.<locals>.<genexpr>   s=      
 T\\!JK.$2C2CTEUEUVV
s   7:)tuplerQ   r   maxlenr]   r   rj   ri   rl   rw   )r.   ro   max_len
common_lenrs   rt   s   `   @@r   rV   z"ObjDiffDisplay.common_shorten_repr   s5    S$/0c#tn%doo%Kd#[
__j 4#5#558L8LL

 +++""&&'%%& Z') //	"" \\&$*<*<jIFCdCCCfd&8&8$:M:MN 

 
 	
r   r   rt   
suffix_lenc                     t        |      |z
  |z
  }|| j                  kD  r't        |      |z
  }| j                  |d | |||d        }|S r,   )rz   ri   shortened_str)r.   r   rt   r}   skipsuffix_indexs         r   rw   zObjDiffDisplay.shorten   sW    1v
"Z/$&&&q6J.L""1[j>4<=9IJAr   rs   num_skipped_charssuffixc                     | d|dd| S )a  
        Return a shortened version of the string representation of one of the args
        passed to ``common_shorten_repr()``.
        This should be in the format ``f"{prefix}{skip_str}{suffix}"``, where
        ``skip_str`` is a string indicating how many characters (``num_skipped_chars``)
        of the string representation were skipped between ``prefix`` and ``suffix``.
        rM   dz chars]rd   )r.   rs   r   r   s       r   r   zObjDiffDisplay.shortened_str   s     ,Q/wvh??r   N)r_   r`   ra   rb   r/   r   r   r   rV   intrw   r   rd   r   r   r^   r^      s     &.!
 !
sCx !
F # 3 3 @C @C @ @QT @r   r^   )"rB   os.pathr   typingr   r   r   r   r   r	   r
   django.db.modelsr   r   django.utils.htmlr   django.utils.safestringr   r   django.utils.textr   modelsr   r   r   r   utilsr   r   r   boolr#   r%   r^   rd   r   r   <module>r      sl       = = = 3 0 9 & P P -  "3 "4 "BP BPJS@ S@r   