o
    hp                     @   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   
ForeignKeycomparison_class_registryregister)field_classr   comparison_classr    r   U/var/www/html/ndineBlogger/venv/lib/python3.10/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)field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   s2   | j | jkrtd| j fd| jfg S t| j S )Ndeletionaddition)r    r!   TextDiffto_htmlr   r"   r   r   r   htmldiff@   s   
zFieldComparison.htmldiffc                 C      | j | jkS )z7
        Returns True if the field has changed
        r    r!   r3   r   r   r   has_changedH   s   zFieldComparison.has_changedN)	__name__
__module____qualname__is_fieldis_child_relationr%   r.   r4   r7   r   r   r   r   r   +   s    r   c                   @      e Zd Zdd ZdS )TextFieldComparisonc                 C   s   t | j| j S r   )	diff_textr    r!   r2   r3   r   r   r   r4   P   s   zTextFieldComparison.htmldiffNr8   r9   r:   r4   r   r   r   r   r>   O       r>   )r   c                   @   r=   )RichTextFieldComparisonc                 C      t t| jt| j S r   )r?   r   r    r!   r2   r3   r   r   r   r4   Y   s
   z RichTextFieldComparison.htmldiffNr@   r   r   r   r   rB   X   rA   rB   c                 C   s|   t | dr	|  S t| tjtjfrtS t| tjrtS t| tjr$t	S t| tj
r,tS t| tjr4tS t| tjr<tS t	S )Nget_comparison_class)hasattrrD   
isinstancer   	CharBlock	TextBlockCharBlockComparisonRawHTMLBlockRichTextBlockRichTextBlockComparisonStructBlockStructBlockComparisonStreamBlockStreamBlockComparison	ListBlockListBlockComparison)blockr   r   r   get_comparison_class_for_blockb   s   
rT   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   )rS   exists_aexists_br    r!   )r"   rS   rV   rW   r    r!   r   r   r   r%   x   s
   
zBlockComparison.__init__c                 C      | j o| j S r   )rW   rV   r3   r   r   r   is_new      zBlockComparison.is_newc                 C   rX   r   )rV   rW   r3   r   r   r   
is_deleted   rZ   zBlockComparison.is_deletedc                 C   r5   r   r6   r3   r   r   r   r7      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   rS   render_basicr"   valr   r   r   	htmlvalue   s   zBlockComparison.htmlvaluec                 C   s2   | j | j}| j | j}tt|t| S r   )rS   r\   r    r!   r?   r   r2   )r"   
html_val_a
html_val_br   r   r   r4      s   zBlockComparison.htmldiffN)	r8   r9   r:   r%   rY   r[   r7   r_   r4   r   r   r   r   rU   w   s    rU   c                   @      e Zd Zdd Zdd ZdS )rI   c                 C   rC   r   )r?   r   r    r!   r2   r3   r   r   r   r4      s   zCharBlockComparison.htmldiffc                 C      t |S r   )r   r]   r   r   r   r_         zCharBlockComparison.htmlvalueN)r8   r9   r:   r4   r_   r   r   r   r   rI      s    rI   c                   @   s   e Zd ZdS )rL   N)r8   r9   r:   r   r   r   r   rL      s    rL   c                   @   rb   )rN   c                 C   sn   g }| j j D ]%\}}| j j| j}t|}||||dd|| || || f qtdtdd|S )NT<dl>
{}
</dl>
    <dt>{}</dt>
    <dd>{}</dd>)	rS   child_blocksitemslabelrT   appendr_   r   r   )r"   r^   
htmlvaluesr+   rS   rj   r   r   r   r   r_      s   	
zStructBlockComparison.htmlvaluec                 C   sp   g }| j j D ]&\}}| j j| j}t|}||||| j| j| j| | j	| 
 f qtdtdd|S )Nre   rf   rg   )rS   rh   ri   rj   rT   rk   rV   rW   r    r!   r4   r   r   )r"   	htmldiffsr+   rS   rj   r   r   r   r   r4      s(   
zStructBlockComparison.htmldiffN)r8   r9   r:   r_   r4   r   r   r   r   rN      s    rN   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 r   )NotImplementedError)r^   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      i | ]}|j |qS r   id.0rS   r   r   r   
<dictcomp>       z@BaseSequenceBlockComparison.get_blocks_by_id.<locals>.<dictcomp>c                 S   rq   r   rr   rt   r   r   r   rv      rw   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              	      s4  |  | j}|  | j}| ||\}}| |   g }|D ]+}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 ]\}}| r}qt||	kr|||
 d} n|d7 }qt|s||
 qY|S )NTFc                    s"   g | ]\}}|j  v r||fqS r   rr   )ru   irS   deleted_idsr   r   
<listcomp>   s    zKBaseSequenceBlockComparison.get_block_comparisons_by_id.<locals>.<listcomp>r      )rp   r    r!   r|   keysrT   rS   rs   rk   r   	enumeraterY   insert)r"   rx   ry   rz   r{   comparisonsrS   r   deleted_block_indicesindexcomparison_to_insertcurrent_indexblock_insertedr}   
comparisonr   r~   r   get_block_comparisons_by_id   sT   






z7BaseSequenceBlockComparison.get_block_comparisons_by_idc                 C   s   g }|   D ]E}dg}| r|d ||j}n| r+|d ||j}n| r4| }n||j}d	|}|d| d| d qt
d	|S )	Nzcomparison__child-objectr0   r/   r)   z<div class="z">z</div>rf   )get_block_comparisonsrY   rk   r_   r!   r[   r    r7   r4   joinr   )r"   comparisons_htmlr   classesblock_renderedr   r   r   r4     s   



z$BaseSequenceBlockComparison.htmldiffN)r8   r9   r:   staticmethodrp   r|   r   r4   r   r   r   r   rn      s    

<rn   c                   @       e Zd Zedd Zdd ZdS )rP   c                 C   s   t | pg }|S r   )listr^   r   r   r   r   rp   /  s   z+StreamBlockComparison.get_blocks_from_valuec                 C   s   |   S r   )r   r3   r   r   r   r   4  rd   z+StreamBlockComparison.get_block_comparisonsNr8   r9   r:   r   rp   r   r   r   r   r   rP   .      
rP   c                   @   r   )rR   c                 C   s   t | jpg }|S r   )r   bound_blocksr   r   r   r   rp   9  s   z)ListBlockComparison.get_blocks_from_valuec           
   	   C   s   |  | j}|  | j}tdd |D otdd |D }|r$|  S g }t| jj}t|}t|}t	|D ]&\}}	||k rQ|
||	jdd|| j|	j q8|
||	jddd |	j q8||kry||d  D ]}	|
||	jdd|	jd  qi|S )Nc                 s   s    | ]}|j V  qd S r   )original_idrt   r   r   r   	<genexpr>E  s    z<ListBlockComparison.get_block_comparisons.<locals>.<genexpr>TF)rp   r    r!   anyr   rT   rS   child_blocklenr   rk   r   )
r"   rx   ry   both_in_new_formatr   r   a_lengthb_lengthr   rS   r   r   r   r   >  s>   z)ListBlockComparison.get_block_comparisonsNr   r   r   r   r   rR   8  r   rR   c                   @   rb   )StreamFieldComparisonc                 C   s   |sdS t |d jS )NTr   )boolrs   r]   r   r   r   has_block_idst  s   z#StreamFieldComparison.has_block_idsc                 C   sN   |  | jr|  | jrt| jjdd| j| j S tt| jt| j	 S )NT)
r   r    r!   rP   r   stream_blockr4   r?   r   r2   r3   r   r   r   r4   z  s   zStreamFieldComparison.htmldiffN)r8   r9   r:   r   r4   r   r   r   r   r   s      r   c                   @   r=   )ChoiceFieldComparisonc                 C   s   t t| jj| j| jdd}t t| jj| j| jdd}| j| jkr@g }|r1|d|fg7 }|r:|d|fg7 }t| S t	|S )NT)strings_onlyr/   r0   )
r   dictr   flatchoicesgetr    r!   r1   r2   r   )r"   r    r!   diffsr   r   r   r4     s   zChoiceFieldComparison.htmldiffNr@   r   r   r   r   r     rA   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   )r   r    r!   r3   r   r   r   	get_items  s   zM2MFieldComparison.get_itemsc                 C   rc   r   )str)r"   itemr   r   r   get_item_display  rd   z#M2MFieldComparison.get_item_displayc                 C   s*  |   \}}td||}g }| D ]y\}}}}}	|dkrE||| D ]}
|d| |
f q$|||	 D ]}
|d| |
f q7q|dkr]||| D ]}
|d| |
f qOq|dkru|||	 D ]}
|d| |
f qgq|dkr||| D ]}
|d| |
f qqt|dd	 S )
Nr   r,   r/   r0   deleter   equalz, )	separator)r   difflibSequenceMatcherget_opcodesrk   r   r1   r2   )r"   items_aitems_bsmchangesopi1i2j1j2r   r   r   r   r4     s.   zM2MFieldComparison.htmldiffc                 C   s   |   \}}||kS r   )r   )r"   r   r   r   r   r   r7     s   zM2MFieldComparison.has_changedN)r8   r9   r:   r   r   r4   r7   r   r   r   r   r     s
    r   c                   @   r=   )TagsFieldComparisonc                 C   s   |j S r   )slug)r"   tagr   r   r   r     s   z$TagsFieldComparison.get_item_displayN)r8   r9   r:   r   r   r   r   r   r     rA   r   c                   @   rb   )ForeignObjectComparisonc                 C   s8   | j j}|jj| jd }|jj| jd }||fS )N)pk)r   related_modelobjectsfilterr    firstr!   )r"   modelr#   r$   r   r   r   get_objects  s   z#ForeignObjectComparison.get_objectsc                 C   s   |   \}}||kr:|r|rtdt|fdt|fg S |r+tdt|fg S |r8tdt|fg S d S |rBtt|S tdS )Nr/   r0   None)r   r1   r   r2   r   r(   r"   r#   r$   r   r   r   r4     s    z ForeignObjectComparison.htmldiffN)r8   r9   r:   r   r4   r   r   r   r   r     r   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*   related_namer    r!   rj   )r"   r   r   r#   r$   rj   r   r   r   r%     s
   
z ChildRelationComparison.__init__c                 C   sB   t | jdd}|du r| jr| j}t|S | jjdd}t|S r&   )r*   r   rj   r+   r,   r	   r-   r   r   r   r.     s   z#ChildRelationComparison.field_labelc                 C   s  i }i }g }g }t |D ]*\}}t |D ]!\}	}
|	|v rq|jdur5|
jdur5|j|
jkr5|	||< |||	< qqg }t |D ]8\}}||vrut |D ]+\}	}
|	|vrt|jr^|
jr^|j|
jkr^qI| || ||	 }| }|||	|f qIq=|jdd d |D ]\}}	}||v s|	|v rq|	||< |||	< qt |D ]\}}||vr|| qt |D ]\}	}
|	|vr||	 q||||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  s    z5ChildRelationComparison.get_mapping.<locals>.<lambda>)key)r   r   get_child_comparisonget_num_differencesrk   sort)r"   objs_aobjs_bmap_forwardsmap_backwardsaddeddeleteda_idxa_childb_idxb_childmatchesr   num_differencesr   r   r   get_mapping	  sV   &




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 r<|| 	d|	 q*|| 	|||  |	 q*| D ]\}
}|
|v r_|| 	|d qN|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)
r   r    allr!   r   r   r   ri   rk   r   )r"   r   r   r   r   r   r   r   r   r   r   r   r   r   r   get_child_comparisonsn  s"   
z-ChildRelationComparison.get_child_comparisonsc           
      C   st   t | j }t | j }| ||\}}}}|s|rdS | D ]\}}| || || }	|	 r7 dS q"dS )z
        Returns true if any changes were made to any of the child objects. This includes
        adding, deleting and reordering.
        TF)r   r    r   r!   r   ri   r   r7   )
r"   r   r   r   r   r   r   r   r   r   r   r   r   r7     s   z#ChildRelationComparison.has_changedNr   )r8   r9   r:   r;   r<   r%   r.   r   r   r   r7   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   rX   )zK
        Returns True if this child object was created since obj_a
        )r$   r#   r3   r   r   r   is_addition     z!ChildObjectComparison.is_additionc                 C   rX   )zH
        Returns True if this child object was deleted in obj_b
        )r#   r$   r3   r   r   r   is_deletion  r   z!ChildObjectComparison.is_deletionc                 C   sD   |   s|  s t| jddpd}t| jddpd}|| S d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.
        
sort_orderr   N)r   r   r*   r#   r$   )r"   sort_asort_br   r   r   get_position_change  s
   z)ChildObjectComparison.get_position_changec                 C   sd   g }|   s
|  r | jp| j}| jD ]
}|||| q|S | jD ]}||| j| j q#|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   rk   )r"   r   objfield_comparisonr   r   r   get_field_comparisons  s   

z+ChildObjectComparison.get_field_comparisonsc                 C   s    |   D ]	}| r dS qdS )NTFr   r7   )r"   r   r   r   r   r7     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   r   r   )r"   r   r   r   r   r   r     s   z)ChildObjectComparison.get_num_differencesN)
r8   r9   r:   r%   r   r   r   r   r7   r   r   r   r   r   r     s    r   c                   @   s    e Zd Zd
ddZdddZd	S )r1   r   c                 C   s   || _ || _d S r   )r   r   )r"   r   r   r   r   r   r%     s   
zTextDiff.__init__spanr0   r/   c                 C   s   g }| j D ]3\}}|dkr|t| q|dkr'|dj||t|d q|dkr8|dj||t|d qt| j|S )Nr   r0   z*<{tag} class="{classname}">{value}</{tag}>)r   	classnamer   r/   )r   rk   r   formatr   r   r   )r"   r   addition_classdeletion_classhtmlchange_typer   r   r   r   r2     s$   

zTextDiff.to_htmlNr   )r   r0   r/   )r8   r9   r:   r%   r2   r   r   r   r   r1     s    
r1   c                 C   s|  dd }|| }||}t dd ||}g }| D ]j\}}}	}
}|dkrG|||	 D ]	}|d|f q,||
| D ]	}|d|f q<q|dkr\|||	 D ]	}|d|f qQq|d	krq||
| D ]	}|d|f qfq|d
kr|||	 D ]	}|d
|f q{qg }g }d}|D ]\}}||kr|dur||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 ]}|  r||7 }q|r|| d}|| q|r)|| |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   )isalnumrk   )texttokenscurrent_tokencr   r   r   tokenise  s   


zdiff_text.<locals>.tokenisec                 S   s   t | dkS )N   )r   )tr   r   r   r   /  s    zdiff_text.<locals>.<lambda>r,   r/   r0   r   r   r   Nr   )r   r   r   rk   r   r1   )abr   a_tokb_tokr   r   r   r   r   r   r   tokenmerged_changescurrent_valuecurrent_change_typer   r   r   r   r   r?     sJ   r?   )NNF)5r   django.core.exceptionsr   	django.dbr   django.utils.encodingr   django.utils.htmlr   r   r   django.utils.safestringr   django.utils.textr	   django.utils.translationr
   r(   taggit.managersr   wagtailr   wagtail.fieldsr   r   wagtail.utils.registryr   wagtail.utils.textr   r   r   r   r>   	CharField	TextFieldrB   rT   rU   rI   rL   rN   rn   rP   rR   r   r   r   r   r   r   r   r1   r?   r   r   r   r   <module>   sT    
$ .]
;& 9H