a
    Dgp                     @   s  d dl 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mZ d d
lmZ d dlmZmZ d dlmZ d dlmZ e Zd:ddZG dd dZG dd deZ eej!e d eej"e d G dd de Z#eee#d dd Z$G dd dZ%G dd de%Z&G dd de%Z'G d d! d!e%Z(G d"d# d#e%Z)G d$d% d%e)Z*G d&d' d'e)Z+G d(d) d)eZ,eee,d G d*d+ d+eZ-G d,d- d-eZ.G d.d/ d/e.Z/eee/d G d0d1 d1eZ0G d2d3 d3Z1G d4d5 d5Z2G d6d7 d7Z3d8d9 Z4dS );    N)ImproperlyConfigured)models)	force_str)escapeformat_htmlformat_html_join)	mark_safe)capfirst)gettext_lazy)TaggableManager)blocks)RichTextFieldStreamField)ModelFieldRegistry)text_from_htmlFc                 C   s<   |du rt d|r&| tjkr&t dtj| |||d dS )zo
    Define parameters for form fields to be used by WagtailAdminModelForm for a given
    database field.
    NzNregister_comparison_class must be passed a 'comparison_class' keyword argumentzRThe 'to' argument on register_comparison_class is only valid for ForeignKey fields)tovalueexact_class)r   r   Z
ForeignKeycomparison_class_registryregister)Zfield_classr   comparison_classr    r   T/var/www/lab.imftr.de/x/nb_venv/lib/python3.9/site-packages/wagtail/admin/compare.pyregister_comparison_class   s    r   c                   @   s4   e Zd ZdZdZdd Zdd Zdd Zd	d
 ZdS )FieldComparisonTFc                 C   s"   || _ ||| _||| _d S N)fieldZvalue_from_objectval_aval_b)selfr   obj_aobj_br   r   r   __init__/   s    zFieldComparison.__init__c                 C   s.   t | jdd}|du r&| jjdd}t|S zL
        Returns a label for this field to be displayed to the user
        verbose_nameN_ )getattrr   namereplacer	   r   r$   r   r   r   field_label4   s    zFieldComparison.field_labelc                 C   s6   | j | jkr(td| j fd| jfg S t| j S d S )Ndeletionaddition)r   r   TextDiffto_htmlr   r   r   r   r   htmldiff@   s
    zFieldComparison.htmldiffc                 C   s   | j | jkS )z7
        Returns True if the field has changed
        r   r   r0   r   r   r   has_changedH   s    zFieldComparison.has_changedN)	__name__
__module____qualname__is_fieldis_child_relationr"   r+   r1   r3   r   r   r   r   r   +   s   r   c                   @   s   e Zd Zdd ZdS )TextFieldComparisonc                 C   s   t | j| j S r   )	diff_textr   r   r/   r0   r   r   r   r1   P   s    zTextFieldComparison.htmldiffNr4   r5   r6   r1   r   r   r   r   r9   O   s   r9   )r   c                   @   s   e Zd Zdd ZdS )RichTextFieldComparisonc                 C   s   t t| jt| j S r   )r:   r   r   r   r/   r0   r   r   r   r1   Y   s    z RichTextFieldComparison.htmldiffNr;   r   r   r   r   r<   X   s   r<   c                 C   s   t | dr|  S t| tjtjfr(tS t| tjr8tS t| tjrHt	S t| tj
rXtS t| tjrhtS t| tjrxtS t	S d S )Nget_comparison_class)hasattrr=   
isinstancer   Z	CharBlockZ	TextBlockCharBlockComparisonZRawHTMLBlockZRichTextBlockRichTextBlockComparisonZStructBlockStructBlockComparisonZStreamBlockStreamBlockComparisonZ	ListBlockListBlockComparison)blockr   r   r   get_comparison_class_for_blockb   s    
rF   c                   @   s<   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd ZdS )BlockComparisonc                 C   s"   || _ || _|| _|| _|| _d S r   )rE   exists_aexists_br   r   )r   rE   rH   rI   r   r   r   r   r   r"   x   s
    zBlockComparison.__init__c                 C   s   | j o| j S r   )rI   rH   r0   r   r   r   is_new   s    zBlockComparison.is_newc                 C   s   | j o| j S r   )rH   rI   r0   r   r   r   
is_deleted   s    zBlockComparison.is_deletedc                 C   s   | j | jkS r   r2   r0   r   r   r   r3      s    zBlockComparison.has_changedc                 C   s   t t| j|S )zu
        Return an HTML representation of this block that is safe to be included
        in comparison views
        )r   r   rE   render_basicr   valr   r   r   	htmlvalue   s    zBlockComparison.htmlvaluec                 C   s2   | j | j}| j | j}tt|t| S r   )rE   rL   r   r   r:   r   r/   )r   Z
html_val_aZ
html_val_br   r   r   r1      s
    zBlockComparison.htmldiffN)	r4   r5   r6   r"   rJ   rK   r3   rO   r1   r   r   r   r   rG   w   s   rG   c                   @   s   e Zd Zdd Zdd ZdS )r@   c                 C   s   t t| jt| j S r   )r:   r   r   r   r/   r0   r   r   r   r1      s    zCharBlockComparison.htmldiffc                 C   s   t |S r   )r   rM   r   r   r   rO      s    zCharBlockComparison.htmlvalueN)r4   r5   r6   r1   rO   r   r   r   r   r@      s   r@   c                   @   s   e Zd ZdS )rA   N)r4   r5   r6   r   r   r   r   rA      s   rA   c                   @   s   e Zd Zdd Zdd ZdS )rB   c                 C   sn   g }| j j D ]J\}}| j j| j}t|}||||dd|| || || f qtdtdd|S )NT<dl>
{}
</dl>
    <dt>{}</dt>
    <dd>{}</dd>)	rE   child_blocksitemslabelrF   appendrO   r   r   )r   rN   Z
htmlvaluesr(   rE   rU   r   r   r   r   rO      s    	
zStructBlockComparison.htmlvaluec                 C   sp   g }| j j D ]L\}}| j j| j}t|}||||| j| j| j| | j	| 
 f qtdtdd|S )NrP   rQ   rR   )rE   rS   rT   rU   rF   rV   rH   rI   r   r   r1   r   r   )r   Z	htmldiffsr(   rE   rU   r   r   r   r   r1      s&    
zStructBlockComparison.htmldiffN)r4   r5   r6   rO   r1   r   r   r   r   rB      s   rB   c                   @   s4   e Zd Zedd Zedd Zdd Zdd Zd	S )
BaseSequenceBlockComparisonc                 C   s   t d S r   )NotImplementedError)rN   r   r   r   get_blocks_from_value   s    z1BaseSequenceBlockComparison.get_blocks_from_valuec                 C   s$   dd | D }dd |D }||fS )Nc                 S   s   i | ]}|j |qS r   id.0rE   r   r   r   
<dictcomp>       z@BaseSequenceBlockComparison.get_blocks_by_id.<locals>.<dictcomp>c                 S   s   i | ]}|j |qS r   rZ   r\   r   r   r   r^      r_   r   )a_blocksb_blocksa_blocks_by_idb_blocks_by_idr   r   r   get_blocks_by_id   s    z,BaseSequenceBlockComparison.get_blocks_by_idc              	      s8  |  | j}|  | j}| ||\}}| |   g }|D ]V}t|j}|j|v r||||jdd||j j	|j	 q@|||jddd |j	 q@ fddt
|D }|D ]\}}	t|j}||jdd|j	d }
d}d}t
|D ]:\}}| rq||	kr|||
 d} q$|d7 }q|s||
 q|S )NTFc                    s"   g | ]\}}|j  v r||fqS r   rZ   )r]   irE   Zdeleted_idsr   r   
<listcomp>   s   zKBaseSequenceBlockComparison.get_block_comparisons_by_id.<locals>.<listcomp>r      )rY   r   r   rd   keysrF   rE   r[   rV   r   	enumeraterJ   insert)r   r`   ra   rb   rc   comparisonsrE   r   Zdeleted_block_indicesindexZcomparison_to_insertZcurrent_indexZblock_insertedre   
comparisonr   rf   r   get_block_comparisons_by_id   sR    






z7BaseSequenceBlockComparison.get_block_comparisons_by_idc                 C   s   g }|   D ]}dg}| r6|d ||j}n>| rV|d ||j}n| rh| }n||j}d	|}|d| d| d qt
d	|S )	Nzcomparison__child-objectr-   r,   r&   z<div class="z">z</div>rQ   )get_block_comparisonsrJ   rV   rO   r   rK   r   r3   r1   joinr   )r   Zcomparisons_htmlrn   classesZblock_renderedr   r   r   r1     s    



z$BaseSequenceBlockComparison.htmldiffN)r4   r5   r6   staticmethodrY   rd   ro   r1   r   r   r   r   rW      s   

<rW   c                   @   s    e Zd Zedd Zdd ZdS )rC   c                 C   s   t | p
g }|S r   )listrN   r   r   r   r   rY   /  s    z+StreamBlockComparison.get_blocks_from_valuec                 C   s   |   S r   )ro   r0   r   r   r   rp   4  s    z+StreamBlockComparison.get_block_comparisonsNr4   r5   r6   rs   rY   rp   r   r   r   r   rC   .  s   
rC   c                   @   s    e Zd Zedd Zdd ZdS )rD   c                 C   s   t | jpg }|S r   )rt   Zbound_blocksru   r   r   r   rY   9  s    z)ListBlockComparison.get_blocks_from_valuec           
   	   C   s   |  | j}|  | j}tdd |D o:tdd |D }|rH|  S g }t| jj}t|}t|}t	|D ]L\}}	||k r|
||	jdd|| j|	j qp|
||	jddd |	j qp||kr||d  D ]}	|
||	jdd|	jd  q|S )Nc                 s   s   | ]}|j V  qd S r   )Zoriginal_idr\   r   r   r   	<genexpr>E  r_   z<ListBlockComparison.get_block_comparisons.<locals>.<genexpr>TF)rY   r   r   anyro   rF   rE   Zchild_blocklenrj   rV   r   )
r   r`   ra   Zboth_in_new_formatrl   r   Za_lengthZb_lengthrm   rE   r   r   r   rp   >  s>    z)ListBlockComparison.get_block_comparisonsNrv   r   r   r   r   rD   8  s   
rD   c                   @   s   e Zd Zdd Zdd ZdS )StreamFieldComparisonc                 C   s   |sdS t |d jS )NTr   )boolr[   rM   r   r   r   has_block_idst  s    z#StreamFieldComparison.has_block_idsc                 C   sR   |  | jr4|  | jr4t| jjdd| j| j S tt| jt| j	 S d S )NT)
r|   r   r   rC   r   Zstream_blockr1   r:   r   r/   r0   r   r   r   r1   z  s    zStreamFieldComparison.htmldiffN)r4   r5   r6   r|   r1   r   r   r   r   rz   s  s   rz   c                   @   s   e Zd Zdd ZdS )ChoiceFieldComparisonc                 C   s   t t| jj| j| jdd}t t| jj| j| jdd}| j| jkrg }|rb|d|fg7 }|rt|d|fg7 }t| S t	|S d S )NT)Zstrings_onlyr,   r-   )
r   dictr   Zflatchoicesgetr   r   r.   r/   r   )r   r   r   Zdiffsr   r   r   r1     s    zChoiceFieldComparison.htmldiffNr;   r   r   r   r   r}     s   r}   c                   @   s,   e Zd Zdd Zdd Zdd Zdd Zd	S )
M2MFieldComparisonc                 C   s   t | jt | jfS r   )rt   r   r   r0   r   r   r   	get_items  s    zM2MFieldComparison.get_itemsc                 C   s   t |S r   )str)r   itemr   r   r   get_item_display  s    z#M2MFieldComparison.get_item_displayc                 C   s,  |   \}}td||}g }| D ]\}}}}}	|dkr||| D ]}
|d| |
f qH|||	 D ]}
|d| |
f qnq&|dkr||| D ]}
|d| |
f qq&|dkr|||	 D ]}
|d| |
f qq&|dkr&||| D ]}
|d| |
f  qq&t|dd	 S )
Nr   r)   r,   r-   deleterk   equalz, )	separator)r   difflibSequenceMatcherget_opcodesrV   r   r.   r/   )r   items_aitems_bsmchangesopi1i2j1j2r   r   r   r   r1     s&    zM2MFieldComparison.htmldiffc                 C   s   |   \}}||kS r   )r   )r   r   r   r   r   r   r3     s    zM2MFieldComparison.has_changedN)r4   r5   r6   r   r   r1   r3   r   r   r   r   r     s   r   c                   @   s   e Zd Zdd ZdS )TagsFieldComparisonc                 C   s   |j S r   )Zslug)r   tagr   r   r   r     s    z$TagsFieldComparison.get_item_displayN)r4   r5   r6   r   r   r   r   r   r     s   r   c                   @   s   e Zd Zdd Zdd ZdS )ForeignObjectComparisonc                 C   s8   | j j}|jj| jd }|jj| jd }||fS )N)pk)r   related_modelZobjectsfilterr   firstr   )r   modelr    r!   r   r   r   get_objects  s    z#ForeignObjectComparison.get_objectsc                 C   s   |   \}}||krr|r<|r<tdt|fdt|fg S |rVtdt|fg S |rtdt|fg S n|rtt|S tdS d S )Nr,   r-   None)r   r.   r   r/   r   r%   r   r    r!   r   r   r   r1     s    z ForeignObjectComparison.htmldiffN)r4   r5   r6   r   r1   r   r   r   r   r     s   r   c                   @   sF   e Zd ZdZdZdddZdd Zdd	 Zd
d Zdd Z	dd Z
dS )ChildRelationComparisonFT c                 C   s2   || _ || _t||j| _t||j| _|| _d S r   )r   field_comparisonsr'   Zrelated_namer   r   rU   )r   r   r   r    r!   rU   r   r   r   r"     s
    z ChildRelationComparison.__init__c                 C   s<   t | jdd}|du r4| jr$| j}n| jjdd}t|S r#   )r'   r   rU   r(   r)   r	   r*   r   r   r   r+     s    z#ChildRelationComparison.field_labelc                 C   s  i }i }g }g }t |D ]T\}}t |D ]B\}	}
|	|v r:q(|jdur(|
jdur(|j|
jkr(|	||< |||	< q(qg }t |D ]p\}}||vrzt |D ]V\}	}
|	|vr|jr|
jr|j|
jkrq| || ||	 }| }|||	|f qqz|jdd d |D ]4\}}	}||v s |	|v r"q |	||< |||	< q t |D ]\}}||vr>|| q>t |D ]\}	}
|	|vrf||	 qf||||fS )a  
        This bit of code attempts to match the objects in the A revision with
        their counterpart in the B revision.

        A match is firstly attempted by PK (where a matching ID indicates they're the same).
        We compare remaining the objects by their field data; the objects with the fewest
        fields changed are matched until there are no more possible matches left.

        This returns 4 values:
         - map_forwards => a mapping of object indexes from the B version to the A version
         - map_backwards => a mapping of object indexes from the A version to the B version
         - added => a list of indices for objects that didn't exist in the B version
         - deleted => a list of indices for objects that didn't exist in the A version

        Note the indices are 0-based array indices indicating the location of the object in either
        the objs_a or objs_b arrays.

        For example:

        objs_a => A, B, C, D
        objs_b => B, C, D, E

        Will return the following:

        map_forwards = {
            1: 0,  # B (objs_a: objs_b)
            2: 1,  # C (objs_a: objs_b)
            3: 2,  # D (objs_a: objs_b)
        }
        map_backwards = {
            0: 1,  # B (objs_b: objs_a)
            1: 2,  # C (objs_b: objs_a)
            2: 3,  # D (objs_b: objs_a)
        }
        added = [4]  # D in objs_b
        deleted = [0]  # A in objs_a
        Nc                 S   s   | d S )N   r   )matchr   r   r   <lambda>T  r_   z5ChildRelationComparison.get_mapping.<locals>.<lambda>)key)rj   r   get_child_comparisonget_num_differencesrV   sort)r   objs_aobjs_bmap_forwardsmap_backwardsaddeddeleteda_idxa_childb_idxb_childmatchesrn   num_differencesr   r   r   get_mapping	  sR    &


z#ChildRelationComparison.get_mappingc                 C   s   t | jj| j||S r   )ChildObjectComparisonr   r   r   r   r   r   r   r   i  s    z,ChildRelationComparison.get_child_comparisonc                 C   s   t | j }t | j }| ||\}}}}tt|}tt|}g }| D ]>\}}	||v rx|| 	d|	 qT|| 	|||  |	 qT| D ]"\}
}|
|v r|| 	|d q|S )aU  
        Returns a list of ChildObjectComparison objects. Representing all child
        objects that existed in either version.

        They are returned in the order they appear in the B version with deletions
        appended at the end.

        All child objects are returned, regardless of whether they were actually changed.
        N)
rt   r   allr   r   r~   rj   rT   rV   r   )r   r   r   r   r   r   r   rl   r   r   r   r   r   r   r   get_child_comparisonsn  s     
z-ChildRelationComparison.get_child_comparisonsc           
      C   st   t | j }t | j }| ||\}}}}|s8|r<dS | D ]*\}}| || || }	|	 rD dS qDdS )z
        Returns true if any changes were made to any of the child objects. This includes
        adding, deleting and reordering.
        TF)rt   r   r   r   r   rT   r   r3   )
r   r   r   r   r   r   r   r   r   rn   r   r   r   r3     s    z#ChildRelationComparison.has_changedN)r   )r4   r5   r6   r7   r8   r"   r+   r   r   r   r3   r   r   r   r   r     s   
`!r   c                   @   sD   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dS )r   c                 C   s   || _ || _|| _|| _d S r   )r   r   r    r!   )r   r   r   r    r!   r   r   r   r"     s    zChildObjectComparison.__init__c                 C   s   | j o| j S )zK
        Returns True if this child object was created since obj_a
        )r!   r    r0   r   r   r   is_addition  s    z!ChildObjectComparison.is_additionc                 C   s   | j o| j S )zH
        Returns True if this child object was deleted in obj_b
        )r    r!   r0   r   r   r   is_deletion  s    z!ChildObjectComparison.is_deletionc                 C   s@   |   s<|  s<t| jddp d}t| jddp2d}|| S dS )a  
        Returns the change in position as an integer. Positive if the object
        was moved down, negative if it moved up.

        For example: '3' indicates the object moved down three spaces. '-1'
        indicates the object moved up one space.
        Z
sort_orderr   N)r   r   r'   r    r!   )r   Zsort_aZsort_br   r   r   get_position_change  s    z)ChildObjectComparison.get_position_changec                 C   sb   g }|   s|  r>| jp| j}| jD ]}|||| q&n | jD ]}||| j| j qD|S )z
        Returns a list of comparisons for all the fields in this object.
        Fields that haven't changed are included as well.
        )r   r   r    r!   r   rV   )r   rl   objZfield_comparisonr   r   r   get_field_comparisons  s    

z+ChildObjectComparison.get_field_comparisonsc                 C   s    |   D ]}| r dS qdS )NTFr   r3   )r   rn   r   r   r   r3     s    z!ChildObjectComparison.has_changedc                 C   s&   d}|   D ]}| r|d7 }q|S )z[
        Returns the number of fields that differ between the two
        objects.
        r   rh   r   )r   r   rn   r   r   r   r     s
    
z)ChildObjectComparison.get_num_differencesN)
r4   r5   r6   r"   r   r   r   r   r3   r   r   r   r   r   r     s   r   c                   @   s    e Zd Zd
ddZdddZd	S )r.   r   c                 C   s   || _ || _d S r   )r   r   )r   r   r   r   r   r   r"     s    zTextDiff.__init__spanr-   r,   c                 C   s   g }| j D ]f\}}|dkr*|t| q
|dkrN|dj||t|d q
|dkr
|dj||t|d q
t| j|S )Nr   r-   z*<{tag} class="{classname}">{value}</{tag}>)r   	classnamer   r,   )r   rV   r   formatr   r   rq   )r   r   Zaddition_classZdeletion_classhtmlchange_typer   r   r   r   r/     s"    

zTextDiff.to_htmlN)r   )r   r-   r,   )r4   r5   r6   r"   r/   r   r   r   r   r.     s   
r.   c                 C   s  dd }|| }||}t dd ||}g }| D ]\}}}	}
}|dkr|||	 D ]}|d|f qX||
| D ]}|d|f qxq6|dkr|||	 D ]}|d|f qq6|d	kr||
| D ]}|d|f qq6|d
kr6|||	 D ]}|d
|f qq6g }g }d}|D ]D\}}||krT|durP||d|f g }|}|| q|r|||d|f t|S )z
    Performs a diffing algorithm on two pieces of text. Returns
    a string of HTML containing the content of both texts with
    <span> tags inserted indicating where the differences are.
    c                 S   sV   g }d}| pdD ]2}|  r&||7 }q|r8|| d}|| q|rR|| |S )a  
        Tokenises a string by splitting it into individual characters
        and grouping the alphanumeric ones together.

        This means that punctuation, whitespace, CJK characters, etc
        become separate tokens and words/numbers are merged together
        to form bigger tokens.

        This makes the output of the diff easier to read as words are
        not broken up.
        r   )isalnumrV   )texttokenscurrent_tokencr   r   r   tokenise  s    


zdiff_text.<locals>.tokenisec                 S   s   t | dkS )N   )ry   )tr   r   r   r   /  r_   zdiff_text.<locals>.<lambda>r)   r,   r-   r   rk   r   Nr   )r   r   r   rV   rq   r.   )abr   Za_tokZb_tokr   r   r   r   r   r   r   tokenZmerged_changesZcurrent_valueZcurrent_change_typer   r   r   r   r   r:     sB    

r:   )NNF)5r   Zdjango.core.exceptionsr   Z	django.dbr   Zdjango.utils.encodingr   Zdjango.utils.htmlr   r   r   Zdjango.utils.safestringr   Zdjango.utils.textr	   Zdjango.utils.translationr
   r%   Ztaggit.managersr   Zwagtailr   Zwagtail.fieldsr   r   Zwagtail.utils.registryr   Zwagtail.utils.textr   r   r   r   r9   Z	CharFieldZ	TextFieldr<   rF   rG   r@   rA   rB   rW   rC   rD   rz   r}   r   r   r   r   r   r.   r:   r   r   r   r   <module>   sR    
$ .]
;& 9H