
    HR-e>                        d Z ddlZddlZddlZddlZddlZddlZddlZddlm	Z	 ddl
mZ ddlmZ ddlZddlmZ ddlmZmZmZmZ ddlmZ d	d
lmZmZ d	dlmZmZ d	dlm Z  d	dl!m"Z" d	dl#m$Z$ g dZ%g dZ& G d d          Z' G d de'          Z( G d de'          Z) G d de'          Z* G d de'          Z+ G d de+          Z, G d de'          Z-d dZ.dS )!z
Facilities for diffing two FITS files.  Includes objects for diffing entire
FITS files, individual HDUs, FITS headers, or just FITS data.

Used to implement the fitsdiff program.
    N)defaultdict)	signature)islice)__version__)diff_valuesfixed_width_indentreport_diff_valueswhere_not_allclose)NOT_OVERWRITING_MSG   )
BLANK_CARDCard)HDUListfitsopen)_TableLikeHDU)Header)	path_like)FITSDiffHDUDiff
HeaderDiffImageDataDiffRawDataDiffTableDataDiff))unitunits)nullznull values)bscalebscales)bzerobzeros)dispzdisplay formats)dim
dimensionsc                   d    e Zd ZdZd Zd Zed             Zed             Z	dd	Z
d
 Zd Zd ZdS )	_BaseDiffaa  
    Base class for all FITS diff objects.

    When instantiating a FITS diff object, the first two arguments are always
    the two objects to diff (two FITS files, two FITS headers, etc.).
    Instantiating a ``_BaseDiff`` also causes the diff itself to be executed.
    The returned ``_BaseDiff`` instance has a number of attribute that describe
    the results of the diff operation.

    The most basic attribute, present on all ``_BaseDiff`` instances, is
    ``.identical`` which is `True` if the two objects being compared are
    identical according to the diff method for objects of that type.
    c                 f    || _         || _        d| _        d| _        |                                  dS )a-  
        The ``_BaseDiff`` class does not implement a ``_diff`` method and
        should not be instantiated directly. Instead instantiate the
        appropriate subclass of ``_BaseDiff`` for the objects being compared
        (for example, use `HeaderDiff` to compare two `Header` objects.
        Nr   )ab_fileobj_indent_diff)selfr'   r(   s      4lib/python3.11/site-packages/astropy/io/fits/diff.py__init__z_BaseDiff.__init__I   s3      

    c                     | j          S )z
        A ``_BaseDiff`` object acts as `True` in a boolean context if the two
        objects compared are different.  Otherwise it acts as `False`.
        )	identicalr,   s    r-   __bool__z_BaseDiff.__bool__Y   s    
 >!!r/   c                     t          | j                  }i }t          |j                                                  dd         D ]%}t          ||          rt          ||          ||<   & | ||fi |S )aQ  
        Returns a new Diff object of a specific subclass from an existing diff
        object, passing on the values for any arguments they share in common
        (such as ignore_keywords).

        For example::

            >>> from astropy.io import fits
            >>> hdul1, hdul2 = fits.HDUList(), fits.HDUList()
            >>> headera, headerb = fits.Header(), fits.Header()
            >>> fd = fits.FITSDiff(hdul1, hdul2, ignore_keywords=['*'])
            >>> hd = fits.HeaderDiff.fromdiff(fd, headera, headerb)
            >>> list(hd.ignore_keywords)
            ['*']
           N)r   r.   list
parameterskeyshasattrgetattr)clsotherr'   r(   sigkwargsargs          r-   fromdiffz_BaseDiff.fromdiff`   s    " %%++--..qrr2 	2 	2Cuc"" 2%eS11ss1a""6"""r/   c                 F     t           fd j        D                        S )ac  
        `True` if all the ``.diff_*`` attributes on this diff instance are
        empty, implying that no differences were found.

        Any subclass of ``_BaseDiff`` must have at least one ``.diff_*``
        attribute, which contains a non-empty value if and only if some
        difference was found between the two objects being compared.
        c              3   b   K   | ])}|                     d           t          |          V  *dS )diff_N)
startswithr:   ).0attrr,   s     r-   	<genexpr>z&_BaseDiff.identical.<locals>.<genexpr>   sR       
 
$(T__W=U=U
D$
 
 
 
 
 
r/   )any__dict__r2   s   `r-   r1   z_BaseDiff.identicalz   sD      
 
 
 
,0M
 
 
 
 
 
 	
r/   Nr   Fc                 &   d}d}t          |t                    rtt          j                            |          }t          j                            |          r#|s!t          t          j        |                    |}t          |d          }n|t          j                    }d}|| _        || _        	 |                                  |r|                                 n# |r|                                 w w xY w|r|                                S dS )a  
        Generates a text report on the differences (if any) between two
        objects, and either returns it as a string or writes it to a file-like
        object.

        Parameters
        ----------
        fileobj : file-like, string, or None, optional
            If `None`, this method returns the report as a string. Otherwise it
            returns `None` and writes the report to the given file-like object
            (which must have a ``.write()`` method at a minimum), or to a new
            file at the path specified.

        indent : int
            The number of 4 space tabs to indent the report.

        overwrite : bool, optional
            If ``True``, overwrite the output file if it exists. Raises an
            ``OSError`` if ``False`` and the output file exists. Default is
            ``False``.

        Returns
        -------
        report : str or None
        FNwT)
isinstancer   ospath
expanduserexistsOSErrorr   formatopenioStringIOr)   r*   _reportclosegetvalue)r,   fileobjindent	overwritereturn_stringfilepaths         r-   reportz_BaseDiff.report   s   4 gy)) 		!g((11Gw~~g&& .y .18AABBB"x--_kmmG M	 LLNNN        	&##%%%	& 	&s   4C C8c                 f    | j                             t          || j                  dz              d S )N
)r)   writer   r*   )r,   texts     r-   _writelnz_BaseDiff._writeln   s0    .tT\BBTIJJJJJr/   c                     t           NNotImplementedErrorr2   s    r-   r+   z_BaseDiff._diff       !!r/   c                     t           re   rf   r2   s    r-   rV   z_BaseDiff._report   rh   r/   )Nr   F)__name__
__module____qualname____doc__r.   r3   classmethodr@   propertyr1   r^   rc   r+   rV    r/   r-   r%   r%   :   s            " " " # # [#2 
 
 X
2& 2& 2& 2&hK K K" " "" " " " "r/   r%   c            	       B     e Zd ZdZg g g g dddddf	 fd	Zd Zd Z xZS )r   a  Diff two FITS files by filename, or two `HDUList` objects.

    `FITSDiff` objects have the following diff attributes:

    - ``diff_hdu_count``: If the FITS files being compared have different
      numbers of HDUs, this contains a 2-tuple of the number of HDUs in each
      file.

    - ``diff_hdus``: If any HDUs with the same index are different, this
      contains a list of 2-tuples of the HDU index and the `HDUDiff` object
      representing the differences between the two HDUs.
    
           Tc                 \   t          |t          t          j        f          r:	 t	          |          }n&# t
          $ r}t          d| d          |d}~ww xY wd}nd}t          |t          t          j        f          r:	 t	          |          }n&# t
          $ r}t          d| d          |d}~ww xY wd}nd}d |D             | _        d |D             | _        d	 |D             | _	        d
 |D             | _
        || _        || _        |	| _        |
| _        || _        t!                      | _        t%          | j                  D ]P}|dk    rHt'          j        |          r4| j                            |           | j                            |           Qd| _        g | _        	 t3                                          ||           |r|                                 |r|                                 dS dS # |r|                                 |r|                                 w w xY w)a
  
        Parameters
        ----------
        a : str or `HDUList`
            The filename of a FITS file on disk, or an `HDUList` object.

        b : str or `HDUList`
            The filename of a FITS file on disk, or an `HDUList` object to
            compare to the first file.

        ignore_hdus : sequence, optional
            HDU names to ignore when comparing two FITS files or HDU lists; the
            presence of these HDUs and their contents are ignored.  Wildcard
            strings may also be included in the list.

        ignore_keywords : sequence, optional
            Header keywords to ignore when comparing two headers; the presence
            of these keywords and their values are ignored.  Wildcard strings
            may also be included in the list.

        ignore_comments : sequence, optional
            A list of header keywords whose comments should be ignored in the
            comparison.  May contain wildcard strings as with ignore_keywords.

        ignore_fields : sequence, optional
            The (case-insensitive) names of any table columns to ignore if any
            table data is to be compared.

        numdiffs : int, optional
            The number of pixel/table values to output when reporting HDU data
            differences.  Though the count of differences is the same either
            way, this allows controlling the number of different values that
            are kept in memory or output.  If a negative value is given, then
            numdiffs is treated as unlimited (default: 10).

        rtol : float, optional
            The relative difference to allow when comparing two float values
            either in header values, image arrays, or table columns
            (default: 0.0). Values which satisfy the expression

            .. math::

                \left| a - b \right| > \text{atol} + \text{rtol} \cdot \left| b \right|

            are considered to be different.
            The underlying function used for comparison is `numpy.allclose`.

            .. versionadded:: 2.0

        atol : float, optional
            The allowed absolute difference. See also ``rtol`` parameter.

            .. versionadded:: 2.0

        ignore_blanks : bool, optional
            Ignore extra whitespace at the end of string values either in
            headers or data. Extra leading whitespace is not ignored
            (default: True).

        ignore_blank_cards : bool, optional
            Ignore all cards that are blank, i.e. they only contain
            whitespace (default: True).
        zerror opening file a ()NTFzerror opening file b (c                 6    h | ]}|                                 S rp   upperrE   ks     r-   	<setcomp>z$FITSDiff.__init__.<locals>.<setcomp>4  s     ;;;!AGGII;;;r/   c                 6    h | ]}|                                 S rp   rw   ry   s     r-   r{   z$FITSDiff.__init__.<locals>.<setcomp>5       CCCa		CCCr/   c                 6    h | ]}|                                 S rp   rw   ry   s     r-   r{   z$FITSDiff.__init__.<locals>.<setcomp>6  r}   r/   c                 6    h | ]}|                                 S rp   rw   ry   s     r-   r{   z$FITSDiff.__init__.<locals>.<setcomp>7       ???Aaggii???r/   *rp   )rL   strrM   PathLiker   	ExceptionrQ   ignore_hdusignore_keywordsignore_commentsignore_fieldsnumdiffsrtolatolignore_blanksignore_blank_cardssetignore_hdu_patternsr6   glob	has_magicremoveadddiff_hdu_count	diff_hdussuperr.   rW   )r,   r'   r(   r   r   r   r   r   r   r   r   r   excclose_aclose_bname	__class__s                   r-   r.   zFITSDiff.__init__   s~   Z a#r{+,, 	FQKK F F F;q;;;<<#EFGGGa#r{+,, 	FQKK F F F;q;;;<<#EFGGG <;{;;;CC?CCCCC?CCC????? 		*"4 $'55 )** 	3 	3Ds{{t~d33{ ''---(,,T222 	GGQ""" 			 					   			 				s8   4 
AAAB 
B4B//B4*"G< </H+c                 j    t           j                  t           j                  k    r-t           j                  t           j                  f _         j                                         _         j        s0d j        j        j         dt           j                  dd _         j                                         _	         j	        s0d j        j        j         dt           j                  dd _	         j
        rJt           fd j        D                        _        t           fd j        D                        _         j        rd  j        D             }d  j        D             } j        D ]v}t          j        ||          t          fd	 j        D                        _        t          j        ||          t          fd
 j        D                        _        wt          t!          t           j                  t           j                                      D ]}t"                                j        |          j        |                   }|j        s j        |         j         j        |         j        k    re j        |         j         j        |         j        k    r? j                            || j        |         j         j        |         j        f           Ɖ j                            ||d j        |         j        f           d S )N<z object at z#x>c                 0    g | ]}|j         j        v|S rp   r   r   rE   hr,   s     r-   
<listcomp>z"FITSDiff._diff.<locals>.<listcomp>`  (    RRRA16AQ3Q3Qa3Q3Q3Qr/   c                 0    g | ]}|j         j        v|S rp   r   r   s     r-   r   z"FITSDiff._diff.<locals>.<listcomp>a  r   r/   c                     g | ]	}|j         
S rp   r   rE   hdus     r-   r   z"FITSDiff._diff.<locals>.<listcomp>c      222Csx222r/   c                     g | ]	}|j         
S rp   r   r   s     r-   r   z"FITSDiff._diff.<locals>.<listcomp>d  r   r/   c                 &    g | ]}|j         v|S rp   r   )rE   r   	a_ignoreds     r-   r   z"FITSDiff._diff.<locals>.<listcomp>g  %    !O!O!OqvY7N7N!7N7N7Nr/   c                 &    g | ]}|j         v|S rp   r   )rE   r   	b_ignoreds     r-   r   z"FITSDiff._diff.<locals>.<listcomp>i  r   r/    )lenr'   r(   r   filename	filenamear   rj   id	filenamebr   r   r   fnmatchfilterrangeminr   r@   r1   r   verr   append)r,   a_namesb_namespatternidxhdu_diffr   r   s   `     @@r-   r+   zFITSDiff._diffR  s   tv;;#df++%%#&tv;;DF"<D **~ 	XW!1!:WWr$&zzWWWWDN**~ 	XW!1!:WWr$&zzWWWWDN 	TRRRRRRRSSDFRRRRRRRSSDF# 	Q2246222G2246222G3 Q Q#N7G<<	 !O!O!O!OTV!O!O!OPP#N7G<<	 !O!O!O!OTV!O!O!OPP S[[#df++6677 	P 	PC''dfSk46#;GGH% 	PF3K$s(888s46#;?::N))hs(8$&+/J    N))3"dfSko*NOOO	P 	Pr/   c           
      
   t          j        dd          }| j                            d           |                     dt
                      |                     d| j         d| j                    | j        rRd	                    t          | j                            }|                     d|                    |          z              | j        rRd	                    t          | j                            }|                     d|                    |          z              | j        rRd	                    t          | j                            }|                     d	|                    |          z              | j        rRd	                    t          | j                            }|                     d
|                    |          z              | j        rRd	                    t          | j                            }|                     d|                    |          z              |                     d| j                    |                     d| j         d| j                    | j        r| j                            d           |                     d           |                     d| j        d                     |                     d| j        d                     | j        s|                     d           d S n8| j        s1| j                            d           |                     d           d S | j        D ]\  }}}	}
|dk    r0| j                            d           |                     d           nU| j                            d           |	r |                     d| d|	 d|
 d           n|                     d| d           |                    | j        | j        dz              d S )Nz  )initial_indentsubsequent_indentr`   z fitsdiff: z a: z
 b:  z HDU(s) not to be compared:
z  Keyword(s) not to be compared:
z3 Keyword(s) whose comments are not to be compared:
z% Table column(s) not to be compared:
z9 Maximum number of different data values to be reported: z Relative tolerance: z, Absolute tolerance: z(Files contain different numbers of HDUs:r   z b: r   z)No differences found between common HDUs.zNo differences found.zPrimary HDU:zExtension HDU z (z, z)::rZ   )textwrapTextWrapperr)   ra   rc   r   r   r   r   joinsortedfillr   r   r   r   r   r   r   r   r   r^   r*   )r,   wrapperr   r   r   r   r   r   r   extnameextvers              r-   rV   zFITSDiff._report~  s&   &ddSSSD!!!1K11222CT^CC4>CCDDD 	W((6$*:#;#;<<KMM9GLL<U<UUVVV# 	"%((6$2J+K+K"L"LMM/',,?R2S2SS    	!hhvd.B'C'CDDOMM3gll?6S6SS    	!hhvd.B'C'CDDOMMF,,//0  
  	HHVD,>%?%?@@MMM87<<;V;VV   	WWW	
 	
 	
 	PDIPPTYPP	
 	
 	
  	M%%%MMDEEEMM9!4Q!799:::MM9!4Q!799:::> IJJJ  	M%%%MM1222F.2n 	D 	D*C7Faxx##D)))n----##D))) ;MM"O3"O"O'"O"OV"O"O"OPPPPMM"93"9"9"9:::OODM$,2BOCCCC	D 	Dr/   rj   rk   rl   rm   r.   r+   rV   __classcell__r   s   @r-   r   r      s         " | | | | | ||*P *P *PXDD DD DD DD DD DD DDr/   r   c                   @     e Zd ZdZg g g dddddf fd	Zd Zd Z xZS )r   a  
    Diff two HDU objects, including their headers and their data (but only if
    both HDUs contain the same type of data (image, table, or unknown).

    `HDUDiff` objects have the following diff attributes:

    - ``diff_extnames``: If the two HDUs have different EXTNAME values, this
      contains a 2-tuple of the different extension names.

    - ``diff_extvers``: If the two HDUS have different EXTVER values, this
      contains a 2-tuple of the different extension versions.

    - ``diff_extlevels``: If the two HDUs have different EXTLEVEL values, this
      contains a 2-tuple of the different extension levels.

    - ``diff_extension_types``: If the two HDUs have different XTENSION values,
      this contains a 2-tuple of the different extension types.

    - ``diff_headers``: Contains a `HeaderDiff` object for the headers of the
      two HDUs. This will always contain an object--it may be determined
      whether the headers are different through ``diff_headers.identical``.

    - ``diff_data``: Contains either a `ImageDataDiff`, `TableDataDiff`, or
      `RawDataDiff` as appropriate for the data in the HDUs, and only if the
      two HDUs have non-empty data of the same type (`RawDataDiff` is used for
      HDUs containing non-empty data of an indeterminate type).
    rr   rs   Tc                 L   d |D             | _         d |D             | _        d |D             | _        || _        || _        || _        |	| _        |
| _        d| _        d| _	        d| _
        d| _        d| _        d| _        t                                          ||           dS )a  
        Parameters
        ----------
        a : BaseHDU
            An HDU object.

        b : BaseHDU
            An HDU object to compare to the first HDU object.

        ignore_keywords : sequence, optional
            Header keywords to ignore when comparing two headers; the presence
            of these keywords and their values are ignored.  Wildcard strings
            may also be included in the list.

        ignore_comments : sequence, optional
            A list of header keywords whose comments should be ignored in the
            comparison.  May contain wildcard strings as with ignore_keywords.

        ignore_fields : sequence, optional
            The (case-insensitive) names of any table columns to ignore if any
            table data is to be compared.

        numdiffs : int, optional
            The number of pixel/table values to output when reporting HDU data
            differences.  Though the count of differences is the same either
            way, this allows controlling the number of different values that
            are kept in memory or output.  If a negative value is given, then
            numdiffs is treated as unlimited (default: 10).

        rtol : float, optional
            The relative difference to allow when comparing two float values
            either in header values, image arrays, or table columns
            (default: 0.0). Values which satisfy the expression

            .. math::

                \left| a - b \right| > \text{atol} + \text{rtol} \cdot \left| b \right|

            are considered to be different.
            The underlying function used for comparison is `numpy.allclose`.

            .. versionadded:: 2.0

        atol : float, optional
            The allowed absolute difference. See also ``rtol`` parameter.

            .. versionadded:: 2.0

        ignore_blanks : bool, optional
            Ignore extra whitespace at the end of string values either in
            headers or data. Extra leading whitespace is not ignored
            (default: True).

        ignore_blank_cards : bool, optional
            Ignore all cards that are blank, i.e. they only contain
            whitespace (default: True).
        c                 6    h | ]}|                                 S rp   rw   ry   s     r-   r{   z#HDUDiff.__init__.<locals>.<setcomp>(  r}   r/   c                 6    h | ]}|                                 S rp   rw   ry   s     r-   r{   z#HDUDiff.__init__.<locals>.<setcomp>)  r}   r/   c                 6    h | ]}|                                 S rp   rw   ry   s     r-   r{   z#HDUDiff.__init__.<locals>.<setcomp>*  r   r/   rp   N)r   r   r   r   r   r   r   r   diff_extnamesdiff_extversdiff_extlevelsdiff_extension_typesdiff_headers	diff_datar   r.   )r,   r'   r(   r   r   r   r   r   r   r   r   r   s              r-   r.   zHDUDiff.__init__  s    L  DC?CCCCC?CCC?????		 *"4 $&! Ar/   c                    | j         j        | j        j        k    r| j         j        | j        j        f| _        | j         j        | j        j        k    r| j         j        | j        j        f| _        | j         j        | j        j        k    r| j         j        | j        j        f| _        | j         j        	                    d          | j        j        	                    d          k    rC| j         j        	                    d          | j        j        	                    d          f| _
        t                              | | j         j                                        | j        j                                                  | _        | j         j        | j        j        d S | j         j        r[| j        j        rOt"                              | | j         j        | j        j                  | _        d | j        _         d | j        _        d S t'          | j         t(                    rit'          | j        t(                    rOt*                              | | j         j        | j        j                  | _        d | j        _         d | j        _        d S | j
        sOt,                              | | j         j        | j        j                  | _        d | j        _         d | j        _        d S d S )NXTENSION)r'   r   r(   r   r   r   levelr   headergetr   r   r@   copyr   datais_imager   r   rL   r   r   r   r2   s    r-   r+   zHDUDiff._diff<  sD   6;$&+%%"&&+tv{!;D6:##!%TVZ 8D6<46<''#'6<">D6=Z((DFM,=,=j,I,III!!*--!!*--)D%
 '//$&-$$&&(:(:(<(<
 
 6;$&+"5DV_ 	$ 	$*33D$&+tv{SSDN  $DN#DN.. 	$:dfm3T3T 	$*33D$&+tv{SSDN  $DN#DN* 	$ )11$TV[QQDN  $DN#DN	$ 	$r/   c                 ,   | j         r|                     d           | j        r"|                      dj        | j                    | j        r"|                      dj        | j                    | j        r"|                      dj        | j                    | j        r"|                      dj        | j                    | j        j         sX| j        	                    d           |                     d           | j        
                    | j        | j        dz   	           | j        f| j        j         s\| j        	                    d           |                     d
           | j        
                    | j        | j        dz   	           d S d S d S )Nz No differences found.z( Extension types differ:
  a: {}
  b: {}z( Extension names differ:
  a: {}
  b: {}z+ Extension versions differ:
  a: {}
  b: {}z) Extension levels differ:
  a: {}
  b: {}r`   z Headers contain differences:r   r   z Data contains differences:)r1   rc   r   rR   r   r   r   r   r)   ra   r^   r*   r   r2   s    r-   rV   zHDUDiff._reporti  s   > 	4MM2333$ 	MMC<C.  
  	MMC<CTEWX    	MMF?F&    	MMD=D(    * 	MM%%%MM9:::$$T]4<!;K$LLL>%dn.F%M%%%MM7888N!!$-q8H!IIIII &%%%r/   r   r   s   @r-   r   r     s         @ X X X X X Xt+$ +$ +$Z#J #J #J #J #J #J #Jr/   r   c                   <     e Zd ZdZg g ddddf fd	Zd Zd Z xZS )r   a  
    Diff two `Header` objects.

    `HeaderDiff` objects have the following diff attributes:

    - ``diff_keyword_count``: If the two headers contain a different number of
      keywords, this contains a 2-tuple of the keyword count for each header.

    - ``diff_keywords``: If either header contains one or more keywords that
      don't appear at all in the other header, this contains a 2-tuple
      consisting of a list of the keywords only appearing in header a, and a
      list of the keywords only appearing in header b.

    - ``diff_duplicate_keywords``: If a keyword appears in both headers at
      least once, but contains a different number of duplicates (for example, a
      different number of HISTORY cards in each header), an item is added to
      this dict with the keyword as the key, and a 2-tuple of the different
      counts of that keyword as the value.  For example::

          {'HISTORY': (20, 19)}

      means that header a contains 20 HISTORY cards, while header b contains
      only 19 HISTORY cards.

    - ``diff_keyword_values``: If any of the common keyword between the two
      headers have different values, they appear in this dict.  It has a
      structure similar to ``diff_duplicate_keywords``, with the keyword as the
      key, and a 2-tuple of the different values as the value.  For example::

          {'NAXIS': (2, 3)}

      means that the NAXIS keyword has a value of 2 in header a, and a value of
      3 in header b.  This excludes any keywords matched by the
      ``ignore_keywords`` list.

    - ``diff_keyword_comments``: Like ``diff_keyword_values``, but contains
      differences between keyword comments.

    `HeaderDiff` objects also have a ``common_keywords`` attribute that lists
    all keywords that appear in both headers.
    rs   Tc	                    d |D             | _         d |D             | _        || _        || _        || _        || _        t                      | _        t                      | _        t          | j                   D ]d}	|	
                                }	|	dk    rHt          j        |	          r4| j                             |	           | j                            |	           et          | j                  D ]d}	|	
                                }	|	dk    rHt          j        |	          r4| j                            |	           | j                            |	           eg | _        d| _        d| _        d| _        i | _        t)          t                    | _        t)          t                    | _        t/          |t0                    rt3          j        |          }t/          |t0                    rt3          j        |          }t/          |t2                    rt/          |t2                    st7          d          t9                                          ||           dS )a>  
        Parameters
        ----------
        a : `~astropy.io.fits.Header` or string or bytes
            A header.

        b : `~astropy.io.fits.Header` or string or bytes
            A header to compare to the first header.

        ignore_keywords : sequence, optional
            Header keywords to ignore when comparing two headers; the presence
            of these keywords and their values are ignored.  Wildcard strings
            may also be included in the list.

        ignore_comments : sequence, optional
            A list of header keywords whose comments should be ignored in the
            comparison.  May contain wildcard strings as with ignore_keywords.

        numdiffs : int, optional
            The number of pixel/table values to output when reporting HDU data
            differences.  Though the count of differences is the same either
            way, this allows controlling the number of different values that
            are kept in memory or output.  If a negative value is given, then
            numdiffs is treated as unlimited (default: 10).

        rtol : float, optional
            The relative difference to allow when comparing two float values
            either in header values, image arrays, or table columns
            (default: 0.0). Values which satisfy the expression

            .. math::

                \left| a - b \right| > \text{atol} + \text{rtol} \cdot \left| b \right|

            are considered to be different.
            The underlying function used for comparison is `numpy.allclose`.

            .. versionadded:: 2.0

        atol : float, optional
            The allowed absolute difference. See also ``rtol`` parameter.

            .. versionadded:: 2.0

        ignore_blanks : bool, optional
            Ignore extra whitespace at the end of string values either in
            headers or data. Extra leading whitespace is not ignored
            (default: True).

        ignore_blank_cards : bool, optional
            Ignore all cards that are blank, i.e. they only contain
            whitespace (default: True).
        c                 6    h | ]}|                                 S rp   rw   ry   s     r-   r{   z&HeaderDiff.__init__.<locals>.<setcomp>  r}   r/   c                 6    h | ]}|                                 S rp   rw   ry   s     r-   r{   z&HeaderDiff.__init__.<locals>.<setcomp>  r}   r/   r   rp   z[HeaderDiff can only diff astropy.io.fits.Header objects or strings containing FITS headers.N)r   r   r   r   r   r   r   ignore_keyword_patternsignore_comment_patternsr6   rx   r   r   r   r   common_keywordsdiff_keyword_countdiff_keyword_positionsdiff_keywordsdiff_duplicate_keywordsr   diff_keyword_valuesdiff_keyword_commentsrL   r   r   
fromstring	TypeErrorr   r.   )r,   r'   r(   r   r   r   r   r   r   keywordr   s             r-   r.   zHeaderDiff.__init__  s9   @  DC?CCCCC?CCC		*"4'*uu$'*uu$D011 	: 	:GmmooG#~~$."9"9~$++G444,00999D011 	: 	:GmmooG#~~$."9"9~$++G444,00999  " #%
 ')#   (*$ $/t#4#4  &1%6%6"a 	%!!$$Aa 	%!!$$A1f%% 	*Q*?*? 	>  
 	Ar/   c                      j         r-d  j        j        D             }d  j        j        D             }n2t	           j        j                  }t	           j        j                  } fd} ||          \  }} ||          \  }}d |D             }d |D             }	t          |                    |	                     _        t          |          t          |          k    r#t          |          t          |          f _	        |
                     j                  }|	
                     j                  }	 j        rZ j        D ]R}
|
                    t          j        ||
                    }|	
                    t          j        |	|
                    }	Sd j        v rd S t          |
                    |	                    }t          |	
                    |                    }|s|r	||f _         j        D ]}| j        v r j        r(d} j        D ]}
t          j        ||
          rd} n|r<t          ||                   }t          ||                   }||k    r||f j        |<   t#          ||         ||                   D ]e\  }}t%          || j         j        	          r# j        |                             ||f           E j        |                             d            ft/           j        |                   s j        |= d j        v s	| j        v r0 j        r)d} j        D ]}
t          j        ||
          rd} n|r`t#          ||         ||                   D ]X\  }}t%          ||          r# j        |                             ||f           8 j        |                             d            Yt/           j        |                   s j        |= d S )
Nc                 B    g | ]}t          |          t          k    |S rp   r   r   rE   cs     r-   r   z$HeaderDiff._diff.<locals>.<listcomp>=  (    FFFAQ:1E1Ea1E1E1Er/   c                 B    g | ]}t          |          t          k    |S rp   r   r   s     r-   r   z$HeaderDiff._diff.<locals>.<listcomp>>  r   r/   c                 N   i }i }| D ]}|j         }j        r)t          |t                    r|                                }|                    |j        g                               |           |                    |j        g                               |j                   ||fS re   )	valuer   rL   r   rstrip
setdefaultr   r   comment)cardsvaluescommentscardr   r,   s        r-   get_header_values_commentsz4HeaderDiff._diff.<locals>.get_header_values_commentsD  s    FH K K
% +*UC*@*@ +!LLNNE!!$,33::5AAA##DL"55<<T\JJJJ8##r/   c                 6    h | ]}|                                 S rp   rw   ry   s     r-   r{   z#HeaderDiff._diff.<locals>.<setcomp>T       0001QWWYY000r/   c                 6    h | ]}|                                 S rp   rw   ry   s     r-   r{   z#HeaderDiff._diff.<locals>.<setcomp>U  r	  r/   r   FTr   r   )r   r'   r  r(   r6   r   intersectionr   r   r   
differencer   r   r   r   r   r   zipr   r   r   r   r   rH   r   r   r   )r,   cardsacardsbr  valuesa	commentsavaluesb	commentsb	keywordsa	keywordsbr   left_only_keywordsright_only_keywordsr   skipcountacountbr'   r(   s   `                  r-   r+   zHeaderDiff._diff;  s   " 	(FFFFFFFFFFFFF$&,''F$&,''F		$ 		$ 		$ 		$ 		$ 87??77?? 10000	00000	%i&<&<Y&G&GHHv;;#f++%%'*6{{CKK&@D# (()=>>	(()=>>	' 	U7 U U%00	71S1STT	%00	71S1STT		$&&&F#I$8$8$C$CDD$Y%9%9)%D%DEE 	K!4 	K"46I!JD + 1	8 1	8G$...+ #;  Gw88 #  )**F)**F9?8H,W5 GG,gg.>?? C C1q!$)$)DDD C,W5<<aVDDDD
 ,W5<<TBBBBt/899 6,W5d***g9M.M.M+ #;  Gw88 #  Ig.	'0BCC E E1q!$$ E.w7>>1vFFFF.w7>>tDDDDt1':;; 8.w7c1	8 1	8r/   c                    | j         r[|                     d           |                     d| j         d                     |                     d| j         d                     | j        r| j        d         D ]M}|t          j        v r| j        |         d         }n| j        |         }|                     d|dd|           N| j        d         D ]M}|t          j        v r| j        |         d         }n| j        |         }|                     d|dd	|           N| j        rct          | j        	                                          D ]<\  }}|                     d
|dd           |                      dj
        |            =| j        s| j        rP| j        D ]J}t          | j        d| j        || j                   t          | j        d| j        || j                   Id S d S )Nz( Headers have different number of cards:  a: r     b: r   z Extra keyword 8z in a: z in b: z$ Inconsistent duplicates of keyword r   z)  Occurs {} time(s) in a, {} times in (b)r  )indr  )r   rc   r   r   _commentary_keywordsr'   r(   r   r   itemsrR   r   r   r   report_diff_keyword_attrr)   r*   )r,   r   valcounts       r-   rV   zHeaderDiff._report  sj   " 	@MMDEEEMM>$"9!"<>>???MM>$"9!"<>>??? 	M-a0 M Md777&/!,CC&/CKKKKCKKLLLL-a0 M Md777&/!,CC&/CKKKKCKKLLLL' 	"()E)K)K)M)M"N"N  SWSSSSTTTF?FN    # 	t'A 	/  (M,    )M.    	 	 r/   r   r   s   @r-   r   r     s        ( (\ | | | | | |Bd8 d8 d8L) ) ) ) ) ) )r/   r   c                   0     e Zd ZdZd fd	Zd Zd Z xZS )r   a  
    Diff two image data arrays (really any array from a PRIMARY HDU or an IMAGE
    extension HDU, though the data unit is assumed to be "pixels").

    `ImageDataDiff` objects have the following diff attributes:

    - ``diff_dimensions``: If the two arrays contain either a different number
      of dimensions or different sizes in any dimension, this contains a
      2-tuple of the shapes of each array.  Currently no further comparison is
      performed on images that don't have the exact same dimensions.

    - ``diff_pixels``: If the two images contain any different pixels, this
      contains a list of 2-tuples of the array index where the difference was
      found, and another 2-tuple containing the different values.  For example,
      if the pixel at (0, 0) contains different values this would look like::

          [(0, 0), (1.1, 2.2)]

      where 1.1 and 2.2 are the values of that pixel in each array.  This
      array only contains up to ``self.numdiffs`` differences, for storage
      efficiency.

    - ``diff_total``: The total number of different pixels found between the
      arrays.  Although ``diff_pixels`` does not necessarily contain all the
      different pixel values, this can be used to get a count of the total
      number of differences found.

    - ``diff_ratio``: Contains the ratio of ``diff_total`` to the total number
      of pixels in the arrays.
    rr   rs   c                     || _         || _        || _        d| _        g | _        d| _        d| _        t                                          ||           dS )a  
        Parameters
        ----------
        a : BaseHDU
            An HDU object.

        b : BaseHDU
            An HDU object to compare to the first HDU object.

        numdiffs : int, optional
            The number of pixel/table values to output when reporting HDU data
            differences.  Though the count of differences is the same either
            way, this allows controlling the number of different values that
            are kept in memory or output.  If a negative value is given, then
            numdiffs is treated as unlimited (default: 10).

        rtol : float, optional
            The relative difference to allow when comparing two float values
            either in header values, image arrays, or table columns
            (default: 0.0). Values which satisfy the expression

            .. math::

                \left| a - b \right| > \text{atol} + \text{rtol} \cdot \left| b \right|

            are considered to be different.
            The underlying function used for comparison is `numpy.allclose`.

            .. versionadded:: 2.0

        atol : float, optional
            The allowed absolute difference. See also ``rtol`` parameter.

            .. versionadded:: 2.0
        rp   r   N)	r   r   r   diff_dimensionsdiff_pixels
diff_ratio
diff_totalr   r.   )r,   r'   r(   r   r   r   r   s         r-   r.   zImageDataDiff.__init__  s[    H !		!
 Ar/   c                      j         j         j        j        k    r j         j         j        j        f _        d S t	          j         j         j        t          j                  s.t	          j         j        j        t          j                  sd}d}n j        } j	        }t           j          j        ||          }t          |d                    _         j        dk    rd S  j        dk     r j        }n j        } fdt          t          | d|          D              _        t#           j                  t#          t           j         j                            z   _        d S )Nr   )r   r   c                 H    g | ]}|j         |         j        |         ffS rp   )r'   r(   )rE   r   r,   s     r-   r   z'ImageDataDiff._diff.<locals>.<listcomp>H  s?     
 
 
 46#;s,-
 
 
r/   )r'   shaper(   r(  np
issubdtypedtypeinexactr   r   r
   r   r+  r   r   r  r)  floatflatr*  )r,   r   r   diffsr   s   `    r-   r+   zImageDataDiff._diff&  sI   6<46<''$(FL$&,#?D  F M$&,
33	}TV\2:66	 DDD9D9D"46464HHHeAh--?aF=1HH}H
 
 
 
c5k1h77
 
 
  005TV[9I9I3J3JJr/   c           	      X   | j         rd                    d t          | j         d                   D                       }d                    d t          | j         d                   D                       }|                     d           |                     d|            |                     d|            |                     d	           d S | j        sd S | j        D ]o\  }}d
 t          |          D             }|                     d| d           t          |d         |d         | j        | j        dz   | j        | j	                   p| j
        | j        k    r|                     d           |                     d                    | j
        | j                             d S )Nz x c              3   4   K   | ]}t          |          V  d S re   r   rE   ds     r-   rG   z(ImageDataDiff._report.<locals>.<genexpr>P  (      QQ!s1vvQQQQQQr/   r   c              3   4   K   | ]}t          |          V  d S re   r8  r9  s     r-   rG   z(ImageDataDiff._report.<locals>.<genexpr>Q  r;  r/   r   z Data dimensions differ:r  r  & No further data comparison performed.c                     g | ]}|d z   S )r   rp   )rE   xs     r-   r   z)ImageDataDiff._report.<locals>.<listcomp>_  s    444qQU444r/   z Data differs at r   rY   indent_widthr   r    ...z. {} different pixels found ({:.2%} different).)r(  r   reversedrc   r)  r	   r)   r*   r   r   r+  r   rR   r*  )r,   dimsadimsbindexr  s        r-   rV   zImageDataDiff._reportN  s    
	JJQQx8LQ8O/P/PQQQQQEJJQQx8LQ8O/P/PQQQQQEMM4555MM/%//***MM/%//*** MMBCCCF 	F!- 
	 
	ME644HUOO444EMM6e666777q	q	!\A-YY     ?T]**MM&!!!<CC 	
 	
 	
 	
 	
r/   )rr   rs   rs   r   r   s   @r-   r   r     sj         >1 1 1 1 1 1f&K &K &KP"
 "
 "
 "
 "
 "
 "
r/   r   c                   4     e Zd ZdZd fd	Z fdZd Z xZS )r   a  
    `RawDataDiff` is just a special case of `ImageDataDiff` where the images
    are one-dimensional, and the data is treated as a 1-dimensional array of
    bytes instead of pixel values.  This is used to compare the data of two
    non-standard extension HDUs that were not recognized as containing image or
    table data.

    `ImageDataDiff` objects have the following diff attributes:

    - ``diff_dimensions``: Same as the ``diff_dimensions`` attribute of
      `ImageDataDiff` objects. Though the "dimension" of each array is just an
      integer representing the number of bytes in the data.

    - ``diff_bytes``: Like the ``diff_pixels`` attribute of `ImageDataDiff`
      objects, but renamed to reflect the minor semantic difference that these
      are raw bytes and not pixel values.  Also the indices are integers
      instead of tuples.

    - ``diff_total`` and ``diff_ratio``: Same as `ImageDataDiff`.
    rr   c                 l    d| _         g | _        t                                          |||           dS )aF  
        Parameters
        ----------
        a : BaseHDU
            An HDU object.

        b : BaseHDU
            An HDU object to compare to the first HDU object.

        numdiffs : int, optional
            The number of pixel/table values to output when reporting HDU data
            differences.  Though the count of differences is the same either
            way, this allows controlling the number of different values that
            are kept in memory or output.  If a negative value is given, then
            numdiffs is treated as unlimited (default: 10).
        rp   )r   N)r(  
diff_bytesr   r.   )r,   r'   r(   r   r   s       r-   r.   zRawDataDiff.__init__  s9    "  "A11111r/   c                     t                                                       | j        r+| j        d         d         | j        d         d         f| _        d | j        D             | _        | `d S )Nr   r   c                 (    g | ]\  }}|d          |fS r   rp   )rE   r?  ys      r-   r   z%RawDataDiff._diff.<locals>.<listcomp>  s$    BBBAAaD!9BBBr/   )r   r+   r(  r)  rI  )r,   r   s    r-   r+   zRawDataDiff._diff  sp     	$Q'*$Q'*$D 
 CB1ABBBr/   c           	      Z   | j         rt|                     d           |                     d| j         d          d           |                     d| j         d          d           |                     d           d S | j        sd S | j        D ]V\  }}|                     d| d	           t          |d         |d         | j        | j        dz   | j        | j        
           W|                     d           |                     d                    | j	        | j
                             d S )Nz Data sizes differ:r  r   z bytesr  r   r=  z Data differs at byte r   r@  rB  z- {} different bytes found ({:.2%} different).)r(  rc   rI  r	   r)   r*   r   r   rR   r+  r*  )r,   rF  r  s      r-   rV   zRawDataDiff._report  s[    	MM/000MMA$"6q"9AAABBBMMA$"6q"9AAABBB MMBCCCF 	F!_ 		 		ME6MM;5;;;<<<q	q	!\A-YY     	f;BB 	
 	
 	
 	
 	
r/   )rr   r   r   s   @r-   r   r   s  so         *2 2 2 2 2 2,	 	 	 	 	
 
 
 
 
 
 
r/   r   c                   8     e Zd ZdZg dddf fd	Zd Zd Z xZS )r   a  
    Diff two table data arrays. It doesn't matter whether the data originally
    came from a binary or ASCII table--the data should be passed in as a
    recarray.

    `TableDataDiff` objects have the following diff attributes:

    - ``diff_column_count``: If the tables being compared have different
      numbers of columns, this contains a 2-tuple of the column count in each
      table.  Even if the tables have different column counts, an attempt is
      still made to compare any columns they have in common.

    - ``diff_columns``: If either table contains columns unique to that table,
      either in name or format, this contains a 2-tuple of lists. The first
      element is a list of columns (these are full `Column` objects) that
      appear only in table a.  The second element is a list of tables that
      appear only in table b.  This only lists columns with different column
      definitions, and has nothing to do with the data in those columns.

    - ``diff_column_names``: This is like ``diff_columns``, but lists only the
      names of columns unique to either table, rather than the full `Column`
      objects.

    - ``diff_column_attributes``: Lists columns that are in both tables but
      have different secondary attributes, such as TUNIT or TDISP.  The format
      is a list of 2-tuples: The first a tuple of the column name and the
      attribute, the second a tuple of the different values.

    - ``diff_values``: `TableDataDiff` compares the data in each table on a
      column-by-column basis.  If any different data is found, it is added to
      this list.  The format of this list is similar to the ``diff_pixels``
      attribute on `ImageDataDiff` objects, though the "index" consists of a
      (column_name, row) tuple.  For example::

          [('TARGET', 0), ('NGC1001', 'NGC1002')]

      shows that the tables contain different values in the 0-th row of the
      'TARGET' column.

    - ``diff_total`` and ``diff_ratio``: Same as `ImageDataDiff`.

    `TableDataDiff` objects also have a ``common_columns`` attribute that lists
    the `Column` objects for columns that are identical in both tables, and a
    ``common_column_names`` attribute which contains a set of the names of
    those columns.
    rr   rs   c                 B   t          |          | _        || _        || _        || _        g | _        t                      | _        d| _        d| _        d| _	        g | _
        d| _        g | _        d| _        d| _        t                                          ||           dS )av  
        Parameters
        ----------
        a : BaseHDU
            An HDU object.

        b : BaseHDU
            An HDU object to compare to the first HDU object.

        ignore_fields : sequence, optional
            The (case-insensitive) names of any table columns to ignore if any
            table data is to be compared.

        numdiffs : int, optional
            The number of pixel/table values to output when reporting HDU data
            differences.  Though the count of differences is the same either
            way, this allows controlling the number of different values that
            are kept in memory or output.  If a negative value is given, then
            numdiffs is treated as unlimited (default: 10).

        rtol : float, optional
            The relative difference to allow when comparing two float values
            either in header values, image arrays, or table columns
            (default: 0.0). Values which satisfy the expression

            .. math::

                \left| a - b \right| > \text{atol} + \text{rtol} \cdot \left| b \right|

            are considered to be different.
            The underlying function used for comparison is `numpy.allclose`.

            .. versionadded:: 2.0

        atol : float, optional
            The allowed absolute difference. See also ``rtol`` parameter.

            .. versionadded:: 2.0
        rp   r   N)r   r   r   r   r   common_columnscommon_column_names	diff_rowsdiff_column_countdiff_columnsdiff_column_attributesdiff_column_namesr   r*  r+  r   r.   )r,   r'   r(   r   r   r   r   r   s          r-   r.   zTableDataDiff.__init__  s    P !// 		 #&55 
 !# ')# "$Ar/   c           	      D     j         j        } j        j        }t          |          t          |          k    r#t          |          t          |          f _        d |D             }d |D             }d j        v rd S d  j        D             }|D ]$}|                                }||v r||= ||v r||= %t          |                                          }t          |                                          }t          |
                    |          t          j        d                     _        d  j        D              _        d |                    |          D             }d	 |                    |          D             }|s|r||f _        g g f _        |rO j         j        D ]B}	|	j                                        |v r% j        d
                             |	j                   C|rO j        j        D ]B}	|	j                                        |v r% j        d                             |	j                   Ct           j                   t           j                  k    r/t           j                   t           j                  f _        d S t           j                   t           j                  cxk    rd
k    rn nd S  j        D ]i}	|	j                                        }
|
|v r!||
         }||
         }t*          D ]n\  }}t-          ||d           }t-          ||d           }t/          ||          r7 j                            |	j                                        |f||ff           o j         |	j                  j        |	j                 t5          j        j        t4          j                  rBt5          j        j        t4          j                  rt=           j         j                   }nVd|	j!        v s	d|	j!        v r, fdtE          t                              D             f}nt5          j#        k              } xj$        t          t          |d
                             z  c_$         j%        d
k    r<t           j                   j%        k    r j%        t           j                  z
  }nt          |d
                   }d }tM          |d
         d
|          D ]<}||k    r	|} j                            |	j        |f|         |         ff           =kt           j                   t           j         j        j'                  z  }tQ           j$                  tQ          |          z   _)        d S )Nc                 B    i | ]}|j                                         |S rp   r   lowerr   s     r-   
<dictcomp>z'TableDataDiff._diff.<locals>.<dictcomp>K  $    222q222r/   c                 B    i | ]}|j                                         |S rp   rZ  r   s     r-   r\  z'TableDataDiff._diff.<locals>.<dictcomp>L  r]  r/   r   c                 6    h | ]}|                                 S rp   )r[  )rE   fs     r-   r{   z&TableDataDiff._diff.<locals>.<setcomp>U  s     ???q???r/   r   )keyc                 @    h | ]}|j                                         S rp   rZ  rE   cols     r-   r{   z&TableDataDiff._diff.<locals>.<setcomp>f  s$    #T#T#TCHNN$4$4#T#T#Tr/   c                 B    i | ]}|j                                         |S rp   rZ  rc  s     r-   r\  z'TableDataDiff._diff.<locals>.<dictcomp>h  s3     
 
 
&)CHNNc
 
 
r/   c                 B    i | ]}|j                                         |S rp   rZ  rc  s     r-   r\  z'TableDataDiff._diff.<locals>.<dictcomp>k  s3     
 
 
&)CHNNc
 
 
r/   r   r   r  PQc                 p    g | ]2}t          j        |         |         j        j                   0|3S )r  )r/  allcloser   r   )rE   r   arraarrbr,   s     r-   r   z'TableDataDiff._diff.<locals>.<listcomp>  sU       !{ ItCytyty       r/   )*r'   columnsr(   r   rT  r   r[  r   r  r   r  operator
attrgetterrQ  rR  r  rU  rW  r   r   rS  
_COL_ATTRSr:   r   rV  rx   r/  r0  r1  floatingr
   r   r   rR   r   wherer+  r   r   fieldsr3  r*  )r,   colsacolsbr   	fieldname	colsa_set	colsb_setleft_only_columnsright_only_columnsrd  
name_lowercolacolbrF   _valavalbr5  	max_diffslast_seen_idxr   total_valuesrk  rl  s   `                     @@r-   r+   zTableDataDiff._diff@  s    u::U##&)%jj#e**%=D" 32E22222E222$$$$ F @?D,>??? ' 	% 	%I!))IE!!)$E!!)$''	''	$""9--83Fv3N3N
 
 
 $U#T@S#T#T#T 
 
-6-A-A)-L-L
 
 

 
-6-A-A)-L-L
 
 
  	. 2 	.!24F GD&("XD" 	?v~ ? ?8>>##'888*1-44SX>>> 	?v~ ? ?8>>##'999*1-44SX>>> tv;;#df++%%!$&kk3tv;;7DNF tv;;#df++*********F & 8	S 8	SC))J]**$D$D%  atT400tT400tT** /66(..**D1D$<@   6#(#D6#(#D}TZ55 /"-
BK; ; / +4DIDIVVV
""cSZ&7&7     #(T#3#3   ..OOs3uQx==111OO}!!t'((DM99 !MC0@,A,AA		aMM	 MeAh955 S S-''  # ''#(C49d3i:P(QRRRRS 46{{S)<%=%==0053F3FFr/   c           	      "   | j         r[|                     d           |                     d| j         d                     |                     d| j         d                     | j        r| j        d         D ]H}| j        d         |                                         j        }|                     d| d| d           I| j        d         D ]H}| j        d         |                                         j        }|                     d| d| d	           It          t                    }| j        D ]d\  }}|\  }}|                     d
| d||          d           t          |d         |d         | j
        | j        dz   | j        | j                   e| j        rr|                     d           |                     d| j        d                     |                     d| j        d                     |                     d           d S | j        sd S | j        D ]Z\  }}|                      dj        |            t          |d         |d         | j
        | j        dz   | j        | j                   [| j        r6| j        | j        k     r&|                     d| j        | j        z
   d           | j        | j        k    r|                     d           |                     d                    | j        | j                             d S )Nz) Tables have different number of columns:r  r   r  r   z Extra column z of format z in az in bz Column  has different r   r@  z Table rows differ:r=  z" Column {} data differs in row {}:rB  z  additional difference(s) found.z= {} different table data element(s) found ({:.2%} different).)rT  rc   rW  rU  r[  rR   dictrp  rV  r	   r)   r*   r   r   rS  r   r   r+  r*  )	r,   r   rR   	col_attrscol_attrvalsrF   indxr  s	            r-   rV   zTableDataDiff._report  sv   ! 	?MMEFFFMM=$"8";==>>>MM=$"8";==>>>! 	O.q1 O O*1-djjll;BMtMMMMMNNNN.q1 O O*1-djjll;BMtMMMMMNNNN$$	 #9 
	 
	NHd!JD$MMLTLL)D/LLLMMMQQ!\A-YY     > 	MM/000MM5$."355666MM5$."355666MMBCCCF 	F !, 		 		LD&MME>EtLMMMq	q	!\A-YY      	 ? ?MMXt6XXX   ?T]**MM&!!!KRR 	
 	
 	
 	
 	
r/   r   r   s   @r-   r   r     s        - -^ ,.3 C C C C C CJPG PG PGd@
 @
 @
 @
 @
 @
 @
r/   r   c                    ||v r||         }t          |          D ]k\  }}||dk    rd}n	d|dz    d}|                     t          d|d| d	| d
|                     t          |d         |d         | |dz              jdS dS )zk
    Write a diff between two header keyword values or comments to the specified
    file-like object.
    Nr   r   [r   ]z	 Keyword r  r  z:
)rY   rA  )	enumeratera   r   r	   )	rY   rF   r5  r   r   r  r   r$  dups	            r-   r#  r#    s    
 %W~!$ 	V 	VHC{axx$#'nnnMM"HHH3HHtHHH    s1vs1vwSSTWUUUUU 	V 	Vr/   rL  )/rm   r   r   rT   rn  rM   os.pathr   collectionsr   inspectr   	itertoolsr   numpyr/  astropyr   astropy.utils.diffr   r   r	   r
   astropy.utils.miscr   r  r   r   hdu.hdulistr   r   	hdu.tabler   r   r   utilr   __all__rp  r%   r   r   r   r   r   r   r#  rp   r/   r-   <module>r     s      				  				   # # # # # #                                  3 2 2 2 2 2 " " " " " " " " + * * * * * * * $ $ $ $ $ $                
I" I" I" I" I" I" I" I"X|D |D |D |D |Dy |D |D |D~GJ GJ GJ GJ GJi GJ GJ GJT{ { { { { { { {H
]
 ]
 ]
 ]
 ]
I ]
 ]
 ]
@U
 U
 U
 U
 U
- U
 U
 U
pG
 G
 G
 G
 G
I G
 G
 G
T
V V V V V Vr/   