o
    iUB                     @   sZ  d Z ddlZddlZddlZddlmZ ddlZddlZddlZddl	Z	ddl
mZmZ ddlZddlmZ ddlZddlmZ ddlmZ dd	gZd
d Zdd Zd,ddZeddd ZedjZdd ZG dd de Z!G dd dZ"G dd de"Z#G dd de"Z$dd  Z%i Z&e%  d!d	 Z'd"d# Z(d$d% Z)d&d' Z*d-d)dZ+d*d+ Z,dS ).z(
Utilities for comparing image results.
    N)Path)TemporaryDirectoryTemporaryFile)Image)cbook)ImageComparisonFailurecompare_imagescomparable_formatsc                 C   s   t j| \}}d|||f S )zQ
    Make a new filename by inserting *purpose* before the file's extension.
    z%s-%s%s)ospathsplitext)fnamepurposebaseext r   U/var/www/edux/Edux_v2/venv/lib/python3.10/site-packages/matplotlib/testing/compare.pymake_test_filename   s   r   c                  C   s$   t t d} | jddd t| S )N
test_cacheT)parentsexist_ok)r   mplget_cachedirmkdirstr)	cache_dirr   r   r   get_cache_dir!   s   r      c                 C   s   t  }t| d}	 ||}|sn|| qW d    n1 s#w   Y  t| jdkrA|tt	dj
d | S t| jdkrV|tt	dj
d | S )NrbTz.pdfgszutf-8z.svginkscape)hashlibmd5openreadupdater   suffixr   r   _get_executable_infoversionencode	hexdigest)r   
block_sizer"   fddatar   r   r   get_file_hash'   s(   

r.   z3.3c                    s    fdd}|S )Nc                    s~    | |}t j|dt jt jd}| \}}| }tj|r"|r=dd| }|r1|d| 7 }|r9|d| 7 }t	|d S )NT)universal_newlinesstdoutstderrzConversion command failed:
%s
 zStandard output:
%s
zStandard error:
%s
)

subprocessPopenPIPEcommunicatewaitr
   r   existsjoinIOError)oldnewcmdlinepiper0   r1   errcodemsgcmdr   r   convert<   s   
z1make_external_conversion_command.<locals>.convertr   )rB   rC   r   rA   r    make_external_conversion_command:   s   rD   s   [^a-zA-Z0-9_@%+=:,./-]c                 C   s$   t | d u r| S d| dd d S )N   's   '"'"')_find_unsafe_bytesreplace)br   r   r   _shlex_quote_bytesQ   s   rI   c                   @   s   e Zd ZdS )_ConverterErrorN)__name__
__module____qualname__r   r   r   r   rJ   V   s    rJ   c                   @   s$   e Zd Zdd Zdd Zdd ZdS )
_Converterc                 C   s   d | _ t| j d S N)_procatexitregister__del__selfr   r   r   __init__[   s   z_Converter.__init__c                 C   sR   | j r'| j   | j   td | j j| j j| j jgD ]}|  qd | _ d S d S rO   )rP   killr7   filterstdinr0   r1   close)rU   streamr   r   r   rS   c   s   





z_Converter.__del__c                 C   sJ   t  }	 | jjd}|st|| ||r$t|dt|  S q)z!Read until the prompt is reached.T   N)		bytearrayrP   r0   r$   rJ   extendendswithbyteslen)rU   
terminatorbufcr   r   r   _read_untilm   s   

z_Converter._read_untilN)rK   rL   rM   rV   rS   re   r   r   r   r   rN   Z   s    
rN   c                   @   s   e Zd Zdd ZdS )_GSConverterc              
   C   s
  | j s/tjtdjdddgtjtjd| _ z| d W n ty. } zt	d|d }~ww dd	 }| j j
d
|| d || d  | j j
  | d}| d}|s^tj|s|rht|dd  nd}| j j
d|  t|d | d t dd S )Nr   z	-dNOSAFERz	-dNOPAUSEz-sDEVICE=png16m)rY   r0   s   
GSzFailed to start Ghostscriptc                 S   s"   t | ddddddS )N   \s   \\   (s   \(   )s   \))r
   fsencoderG   )namer   r   r   encode_and_escape   s
   z0_GSConverter.__call__.<locals>.encode_and_escapes   << /OutputFile (s   ) >> setpagedevice (s   ) run flush
s   GS   >r\   r   s   pop
rG   )rP   r3   r4   r   r'   
executabler5   re   rJ   OSErrorrY   writeflushr
   r   r8   intr   decodesysgetfilesystemencoding)rU   origdesterrrl   stack
stack_sizer   r   r   __call__z   sH   



z_GSConverter.__call__N)rK   rL   rM   r{   r   r   r   r   rf   y   s    rf   c                       s$   e Zd Zdd Z fddZ  ZS )_SVGConverterc           
   
   C   s  t djdk }|rdnd}t| dst | _| jr!| j d urdi tj	dtj
d}t }tj|r7g dndd	gtjtj||| jjd
| _|| j_z| | W n tyc } ztd|d }~ww t| jjtd}t| jjtd}	z|t|  W n ty   t|| Y nw | jj|rdnd | jj  z| | W n" ty } z| jjd t| jj  t!" d|d }~ww t#| t$|	| d S )Nr    1s   
>s   > _tmpdir )DISPLAYINKSCAPE_PROFILE_DIR)r    z--without-gui--shellr   )rY   r0   r1   envcwdz,Failed to start Inkscape in interactive modes   f.svgs   f.pngs   f.svg --export-png=f.png
s;   file-open:f.svg;export-filename:f.png;export-do;file-close
r   rG   )%r   r'   r(   hasattrr   r~   rP   pollr
   environdevnullr   r3   r4   r5   rk   r1   re   rJ   ro   r   fsdecode
symlink_toresolveshutilcopyfilerY   rp   rq   seekr   r$   rs   rt   ru   removemove)
rU   rv   rw   old_inkscaperb   r   r1   rx   inkscape_originkscape_destr   r   r   r{      sn   


z_SVGConverter.__call__c                    s&   t    t| dr| j  d S d S )Nr~   )superrS   r   r~   cleanuprT   	__class__r   r   rS      s   

z_SVGConverter.__del__)rK   rL   rM   r{   rS   __classcell__r   r   r   r   r|      s    >r|   c                   C   sj   zt d W n
 t jy   Y n
w t  td< td< zt d W n t jy-   Y d S w t td< d S )Nr   pdfepsr    svg)r   r'   ExecutableNotFoundErrorrf   	converterr|   r   r   r   r   _update_converter   s   r   c                   C   s
   dgt S )z
    Return the list of file formats that `.compare_images` can compare
    on this system.

    Returns
    -------
    list of str
        E.g. ``['png', 'pdf', 'svg', 'eps']``.

    png)r   r   r   r   r   r	      s   
c                 C   s
  t | }| st| d|jdd tvr&ddl}|d|j d |j|j d|jdd  d }| rE|	 j
|	 j
k r|rLt t nd}|durkt|}|||j  }| rkt|| t|S t|jdd  || |durt|| t|S )	at  
    Convert the named file to png; return the name of the created file.

    If *cache* is True, the result of the conversion is cached in
    `matplotlib.get_cachedir() + '/test_cache/'`.  The caching is based on a
    hash of the exact contents of the input file.  There is no limit on the
    size of the cache, so it may need to be manually cleared periodically.
    z does not existr\   Nr   zDon't know how to convert z files to png_z.png)r   r8   r:   r&   r   pytestskipparentstemstatst_mtimer   r.   r   r   r   )filenamecacher   r   newpathr   
hash_valuecached_pathr   r   r   rC   	  s&   	"rC   c           
      C   s   | dd dkrF|dd dkrF|j \}}}|j \}}}	|t|d |d  t|d |d  t|d |d  t|d |d  f }||fS )Nir   r      )shaperr   )
actual_pathactual_imageexpected_pathexpected_imageawahadewehedr   r   r   crop_to_same.  s    &r   c                 C   s<   | j |j krtd| j |j t| | td  S )zR
    Calculate the per-pixel errors, then compute the root mean square error.
    9Image sizes do not match expected size: {} actual size {}r   )r   r   formatnpsqrtastypefloatmean)r   r   r   r   r   calculate_rms9  s   r   Fc           
         sn  t |}t j|std| t |jdkrtd| t | } t j| s0td|  | dd }|dkrGt	|dd	}t	| d
d	} t
t| 	d}t
t|	d}t||| |\}}t|d}|dkrwt
||rwdS |t
j}|t
j}t||}||krdS t| || t|t| t|t||d |sg d}	d fdd|	D   S )a+  
    Compare two "image" files checking differences within a tolerance.

    The two given filenames may point to files which are convertible to
    PNG via the `.converter` dictionary. The underlying RMS is calculated
    with the `.calculate_rms` function.

    Parameters
    ----------
    expected : str
        The filename of the expected image.
    actual : str
        The filename of the actual image.
    tol : float
        The tolerance (a color value difference, where 255 is the
        maximal difference).  The test fails if the average pixel
        difference is greater than this value.
    in_decorator : bool
        Determines the output format. If called from image_comparison
        decorator, this should be True. (default=False)

    Returns
    -------
    None or dict or str
        Return *None* if the images are equal within the given tolerance.

        If the images differ, the return value depends on  *in_decorator*.
        If *in_decorator* is true, a dict with the following entries is
        returned:

        - *rms*: The RMS of the image difference.
        - *expected*: The filename of the expected image.
        - *actual*: The filename of the actual image.
        - *diff_image*: The filename of the difference image.
        - *tol*: The comparison tolerance.

        Otherwise, a human-readable multi-line string representation of this
        information is returned.

    Examples
    --------
    ::

        img1 = "./baseline/plot.png"
        img2 = "./output/plot.png"
        compare_images(img1, img2, 0.001)

    zOutput image %s does not exist.r   zOutput image file %s is empty.z!Baseline image %r does not exist..r   F)r   TRGBzfailed-diffN)rmsexpectedactualdifftol)z!Error: Image files did not match.zRMS Value: {rms}zExpected:  
    {expected}zActual:    
    {actual}zDifference:
    {diff}zTolerance: 
    {tol}z
  c                    s   g | ]
}|j d i  qS )r   r   ).0lineresultsr   r   
<listcomp>  s    z"compare_images.<locals>.<listcomp>)r
   fspathr   r8   	Exceptionr   st_sizer:   splitrC   r   asarrayr   r#   r   r   array_equalr   int16r   save_diff_imagedictr   r9   )
r   r   r   in_decorator	extensionr   r   
diff_imager   templater   r   r   r   I  sD   
1



c                 C   s   t t| d}t t|d}t||| |\}}t |t}t |t}|j	|j	kr?t
d|j	|j	t || }|d9 }t |ddt j}|j	\}}}	|	dkryt j||dft jd}
||
d	d	d	d	ddf< |
}d|d	d	d	d	df< t|j|d
d d	S )z
    Parameters
    ----------
    expected : str
        File path of expected image.
    actual : str
        File path of actual image.
    output : str
        File path to save difference image to.
    r   r   i	  r            )dtypeNr   r   )r   r   r   r#   rC   r   arrayr   r   r   r   r   absclipuint8empty	fromarraysave)r   r   outputr   r   abs_diff_imagesave_image_npheightwidthdepth
with_alphar   r   r   r     s,   r   )r   )F)-__doc__rQ   r!   r
   pathlibr   rer   r3   rt   tempfiler   r   numpyr   PILr   
matplotlibr   r   matplotlib.testing.exceptionsr   __all__r   r   r.   
deprecatedrD   compilesearchrF   rI   r   rJ   rN   rf   r|   r   r   r	   rC   r   r   r   r   r   r   r   r   <module>   sH    

&E%
h