B
    ܇\3                 @   s   d Z ddlmZ ddlmZ ddlmZ ddlZddlZddlZddl	m
Z
 ddlmZ dZd	d
 Zdd Zdd Zdd ZyeZW n ek
r   eZY nX dd Zd$ddZdd Zd%ddZd&ddZd'ddZd(ddZd d! Zd)d"d#ZdS )*z!Utilities for assertion debugging    )absolute_import)division)print_functionN   )Sequence)safereprc             C   s   t | tr| ddS | S d S )NzUTF-8replace)
isinstancebytesdecode)s r   5lib/python3.7/site-packages/_pytest/assertion/util.pyecu   s    
r   c             C   s"   t | } t| }t|}d|S )a  This formats an explanation

    Normally all embedded newlines are escaped, however there are
    three exceptions: 
{, 
} and 
~.  The first two are intended
    cover nested explanations, see function and attribute explanations
    for examples (.visit_Call(), visit_Attribute()).  The last one is
    for when one explanation needs to span multiple lines, e.g. when
    displaying diffs.
    
)r   _split_explanation_format_linesjoin)explanationlinesresultr   r   r   format_explanation   s    
r   c             C   sb   | pd d}|d g}xD|dd D ]4}|rF|d dkrF|| q&|d  d| 7  < q&W |S )	zReturn a list of individual lines in the explanation

    This will return a list of lines split on '
{', '
}' and '
~'.
    Any other newlines will be escaped and appear in the line as the
    literal '
' characters.
     r   r      N){}~>z\n)splitappend)r   Z	raw_linesr   valuesr   r   r   r   .   s    
r   c             C   sJ  | dd }dg}dg}x| dd D ]}| dr|d rFd}nd}|t| |d  d7  < |d |dd	t|d   | |dd   q(| d
r|  |  ||d   |dd 7  < q(|d dkst|d  d7  < | dr
t|n
t|d }|d	| |dd   q(W t|dksFt|S )a
  Format the individual lines

    This will replace the '{', '}' and '~' characters of our mini
    formatting language with the proper 'where ...', 'and ...' and ' +
    ...' text, taking care of indentation along the way.

    Return a list of formatted lines.
    Nr   r   r   r   zand   zwhere z +z  r   )r   r   r   )
startswithr    lenpopAssertionError)r   r   stackZstackcntliner   indentr   r   r   r   ?   s,    	

,
 r   c                s  dt | d }t|t|d d}t||t | d}dt||t|f }dd }dd  d	d
 }	dd }
dd }dd } fdd}| d}d}yB|dkr |rĈ |rt|||}n||r||rt|||}n|
|r|
|rt|||}np|	|r&|	|r&t|||}nNt	|t	|krd||sL||rd||f}t
||||}n|rtt||}||r||rt|||}|dk	r|| n|}n*|dkrڈ |rڈ |rt|||}W n, tk
r   dttjj g}Y nX |sdS |g| S )z;Return specialised explanations for some operators/operandsA   r   )maxsizez%s %s %sc             S   s   t | tot | t S )N)r	   r   
basestring)xr   r   r   
issequenceq   s    z&assertrepr_compare.<locals>.issequencec             S   s
   t | tS )N)r	   r+   )r,   r   r   r   istextt   s    z"assertrepr_compare.<locals>.istextc             S   s
   t | tS )N)r	   dict)r,   r   r   r   isdictw   s    z"assertrepr_compare.<locals>.isdictc             S   s   t | ttfS )N)r	   set	frozenset)r,   r   r   r   issetz   s    z!assertrepr_compare.<locals>.issetc             S   s   t | dd d k	S )N__dataclass_fields__)getattr)objr   r   r   	isdatacls}   s    z%assertrepr_compare.<locals>.isdataclsc             S   s   t | dd d k	S )N__attrs_attrs__)r5   )r6   r   r   r   isattrs   s    z#assertrepr_compare.<locals>.isattrsc                s,   yt |   |  S  tk
r&   dS X d S )NF)iter	TypeError)r6   )r.   r   r   
isiterable   s
    
z&assertrepr_compare.<locals>.isiterableverboseNz==znot inzg(pytest_assertion plugin: representation of details failed.  Probably an object has a faulty __repr__.))r#   r   intr   Z	getoption
_diff_text_compare_eq_sequence_compare_eq_set_compare_eq_dicttype_compare_eq_cls_compare_eq_verbose_compare_eq_iterableextend_notin_text	Exceptionsix	text_type_pytest_codeZExceptionInfoZfrom_current)ZconfigopleftrightwidthZ	left_reprZ
right_reprZsummaryr-   r0   r3   r7   r9   r<   r=   r   Ztype_fnZexplr   )r.   r   assertrepr_comparei   sT    

&


rR   Fc             C   s  ddl m} g }dd }t| tr*|| } t|tr<||}|s&d}x0ttt| t|D ]}| | || kr^P q^W |dkr|d8 }d| g}| |d } ||d }t| t|kr&x*tt| D ]}| |  ||  krP qW |dkr&|d8 }|d	|g7 }| d|  } |d|  }d
}|  s>| r`t	t
| } t	t
|}|dg7 }|dd || |||D 7 }|S )a   Return the explanation for the diff between text or bytes

    Unless --verbose is used this will skip leading and trailing
    characters which are identical to keep the diff minimal.

    If the input are bytes they will be safely converted to text.
    r   )ndiffc             S   s2   t t| dd }|dd}|dd}|S )a  
        Ensures that the internal string is always valid unicode, converting any bytes safely to valid unicode.
        This is done using repr() which then needs post-processing to fix the encompassing quotes and un-escape
        newlines and carriage returns (#429).
        r   r   z\nr   z\r)rJ   rK   reprr   )Zbinary_textrr   r   r   escape_for_readable_diff   s    z,_diff_text.<locals>.escape_for_readable_diff*   
   z@Skipping %s identical leading characters in diff, use -v to showNzASkipping {} identical trailing characters in diff, use -v to showTz;Strings contain only whitespace, escaping them using repr()c             S   s   g | ]}| d qS )r   )strip).0r'   r   r   r   
<listcomp>   s   z_diff_text.<locals>.<listcomp>)difflibrS   r	   r
   rangeminr#   formatisspacerU   str
splitlines)rO   rP   r=   rS   r   rW   ikeependsr   r   r   r?      sJ    





r?   c             C   sL   d}t | |}t ||}g }|dd |D 7 }|dd |D 7 }|S )NTc             S   s   g | ]}d | qS )-r   )r[   r'   r   r   r   r\      s    z'_compare_eq_verbose.<locals>.<listcomp>c             S   s   g | ]}d | qS )+r   )r[   r'   r   r   r   r\      s    )rU   rc   )rO   rP   re   Z
left_linesZright_linesr   r   r   r   rE      s    rE   c             C   s   |s
dgS dd l }y&t|  }t| }dg}W n> tk
rv   tdd | D }tdd |D }dg}Y nX |dd |||D  |S )	NzUse -v to get the full diffr   z
Full diff:c             s   s   | ]}t |V  qd S )N)rU   )r[   r,   r   r   r   	<genexpr>  s    z'_compare_eq_iterable.<locals>.<genexpr>c             s   s   | ]}t |V  qd S )N)rU   )r[   r,   r   r   r   rh     s    z2Full diff (fallback to calling repr on each item):c             s   s   | ]}|  V  qd S )N)rZ   )r[   r'   r   r   r   rh     s    )r]   pprintpformatrc   rI   sortedrG   rS   )rO   rP   r=   r]   Zleft_formattingZright_formattingr   r   r   r   rF      s    
rF   c             C   s   g }xLt tt| t|D ]2}| | || kr|d|| | || f g7 }P qW t| t|kr~|dt| t|  g7 }n*t| t|k r|dt|t|   g7 }|S )NzAt index %s diff: %r != %rz.Left contains more items, first extra item: %sz/Right contains more items, first extra item: %s)r^   r_   r#   r   )rO   rP   r=   r   rd   r   r   r   r@     s    r@   c             C   sl   g }| | }||  }|r>| d x|D ]}| t| q(W |rh| d x|D ]}| t| qRW |S )NzExtra items in the left set:zExtra items in the right set:)r    r   )rO   rP   r=   r   Z	diff_leftZ
diff_rightitemr   r   r   rA   '  s    



rA   c       
         sL  g }t  t } fdd|D }|rJ|dk rJ|dt| g7 }n |rj|dg7 }|t| 7 } fdd|D }|r|dg7 }x6|D ].}|t| | id	 t|| i g7 }qW t  t  }|r|d
 |t fdd|D   t t   }	|	rH|d |tfdd|	D   |S )Nc                s&   i | ]} | | kr | |qS r   r   )r[   k)rO   rP   r   r   
<dictcomp>9  s    z$_compare_eq_dict.<locals>.<dictcomp>r   z,Omitting %s identical items, use -vv to showzCommon items:c                s    h | ]} | | kr|qS r   r   )r[   rm   )rO   rP   r   r   	<setcomp>?  s    z#_compare_eq_dict.<locals>.<setcomp>zDiffering items:z != zLeft contains more items:c                s   i | ]} | |qS r   r   )r[   rm   )rO   r   r   rn   H  s    zRight contains more items:c                s   i | ]} | |qS r   r   )r[   rm   )rP   r   r   rn   N  s    )	r1   intersectionr#   ri   rj   rc   r   r    rG   )
rO   rP   r=   r   commonsamediffrm   Z
extra_leftZextra_rightr   )rO   rP   r   rB   6  s0    


.

rB   c             C   s  |\}}|| r*| j }dd | D }n|| rF| j}dd |D }g }g }	x6|D ].}
t| |
t||
krx||
 qT|	|
 qTW g }|r|dk r|dt|  n |r|dg7 }|t| 7 }|	r|dg7 }x,|	D ]$}
|d|
t| |
t||
f g7 }qW |S )	Nc             S   s   g | ]\}}|j r|qS r   )Zcompare)r[   fieldinfor   r   r   r\   W  s    z#_compare_eq_cls.<locals>.<listcomp>c             S   s   g | ]}|j r|jqS r   )Zcmpname)r[   rt   r   r   r   r\   Z  s    r   z,Omitting %s identical items, use -vv to showzMatching attributes:zDiffering attributes:z%s: %r != %r)	r4   itemsr8   r5   r    r#   ri   rj   rc   )rO   rP   r=   Ztype_fnsr7   r9   Z
all_fieldsZfields_to_checkrr   rs   rt   r   r   r   r   rD   S  s2    



"rD   c       
      C   s   | | }|d | }||t|  d  }|| }t|||}dt| dd g}xP|D ]H}	|	drfqV|	drrqV|	dr|d|	dd    qV||	 qVW |S )	Nz%s is contained here:rX   )r*   ZSkippingz- z+ z  r   )findr#   r?   r   r"   r    )
Ztermtextr=   indexheadtailZcorrect_textrs   Znewdiffr'   r   r   r   rH   s  s    




rH   )F)F)F)F)F)F)__doc__Z
__future__r   r   r   ri   rJ   Z_pytest._coderL   compatr   Z_pytest._io.safereprr   Z_reprcomparer   r   r   r   r+   	NameErrorrb   rR   r?   rE   rF   r@   rA   rB   rD   rH   r   r   r   r   <module>   s4   $
I
?



 