B
    q\;                 @   s   d Z ddlmZ ddlmZmZ ddlmZ G dd dejZG dd deZG d	d
 d
ej	Z
G dd dejZG dd dej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dS )zAn extensible ASCII table reader and writer.

fixedwidth.py:
  Read or write a table with fixed width columns.

:Copyright: Smithsonian Astrophysical Observatory (2011)
:Author: Tom Aldcroft (aldcroft@head.cfa.harvard.edu)
   )core)InconsistentTableErrorDefaultSplitter)basicc               @   s,   e Zd ZdZdZdZdZdd Zdd Zd	S )
FixedWidthSplittera  
    Split line based on fixed start and end positions for each ``col`` in
    ``self.cols``.

    This class requires that the Header class will have defined ``col.start``
    and ``col.end`` for each column.  The reference to the ``header.cols`` gets
    put in the splitter object by the base Reader.read() function just in time
    for splitting data lines by a ``data`` object.

    Note that the ``start`` and ``end`` positions are defined in the pythonic
    style so line[start:end] is the desired substring for a column.  This splitter
    class does not have a hook for ``process_lines`` since that is generally not
    useful for fixed-width input.

     F|c             #   sH   xB|D ]:  fddj D }jr:fdd|D V  q|V  qW d S )Nc                s   g | ]} |j |j qS  )startend).0x)liner	   :lib/python3.7/site-packages/astropy/io/ascii/fixedwidth.py
<listcomp>(   s    z/FixedWidthSplitter.__call__.<locals>.<listcomp>c                s   g | ]}  |qS r	   )process_val)r   r   )selfr	   r   r   *   s    )colsr   )r   linesvalsr	   )r   r   r   __call__&   s
    
zFixedWidthSplitter.__call__c             C   sf   | j pd}| jpd}|| | }| jr8|| }|| }nd}d}dd t||D }||| | S )Nr   c             S   s$   g | ]\}}d |t |  | qS ) )len)r   valwidthr	   r	   r   r   8   s    z+FixedWidthSplitter.join.<locals>.<listcomp>)delimiter_pad	delimiterbookendzipjoin)r   r   widthsZpadr   Zpadded_delimZbookend_leftZbookend_rightr	   r	   r   r   .   s    


zFixedWidthSplitter.joinN)	__name__
__module____qualname____doc__r   r   r   r   r   r	   r	   r	   r   r      s   r   c               @   s   e Zd ZdZdZdS )FixedWidthHeaderSplitterz$Splitter class that splits on ``|``.r   N)r!   r"   r#   r$   r   r	   r	   r	   r   r%   <   s   r%   c               @   s@   e Zd ZdZeZdZedZdd Z	dd Z
dd	 Zd
d ZdS )FixedWidthHeaderz*
    Fixed width table header reader.
    Nz`~!#$%^&*-_+=\|":'c             C   s2   x,t | |D ]\}}||krP qW td|S )NzNo header line found in table)	enumerateprocess_linesr   )r   r   indexir   r	   r	   r   get_lineK   s
    zFixedWidthHeader.get_linec                s  t  j |}t  j |}|dkr|dk	r@td j|}|sXtd |d \}}} fddt	dt
|d D  _n|dk	r& ||}t
t|t jjdg dkrtd	 jt jjdg}	t||	std
|	 |\} _}
dd |
D  _ ||} |\}}}| _   x,t jD ]\}}|| |_|| |_q\W dS )a:  
        Initialize the header Column objects from the table ``lines``.

        Based on the previously set Header attributes find or create the column names.
        Sets ``self.cols`` with the list of Columns.

        Parameters
        ----------
        lines : list
            List of table lines

        Nz:Cannot set position_line without also setting header_startz7No data lines found so cannot autogenerate column names    c                s   g | ]} j |qS r	   )Zauto_formatformat)r   r*   )r   r	   r   r   q   s   z-FixedWidthHeader.get_cols.<locals>.<listcomp>r   r   z]Position line should only contain delimiters and one other character, e.g. "--- ------- ---".z/Characters in position line must be part of {0}c             S   s    g | ]}|d k	r|d nd qS )Nr   r	   )r   r   r	   r	   r   r      s    )r   Z_get_line_index
start_liner(   position_line
ValueErrordatar   get_fixedwidth_paramsranger   namesr+   setsplitterr   set_of_position_line_charactersunionissubsetr-   
col_startscol_endsZ_set_cols_from_namesr'   r   r
   r   )r   r   r.   r/   Z
data_linesr   startsendsr   charsetr;   r*   colr	   )r   r   get_colsS   s8    

 
zFixedWidthHeader.get_colsc                s  | j dk	rb| jdk	rbt| j }dd | jD }t|t|krFtd fddt||D }n(| j dkr&| jdkr& | jj}dg}g }xJ|D ]B}|r|	|d t|  |	|d d  q|d  d7  < qW |dd }d	d |D }t|t|kst|t|krt
d
nd| j dk	rPt| j }|dd dg }n"dd | jD }dg|dd  } fddt||D }|||fS )a  
        Split ``line`` on the delimiter and determine column values and
        column start and end positions.  This might include null columns with
        zero length (e.g. for ``header row = "| col1 || col2 | col3 |"`` or
        ``header2_row = "----- ------- -----"``).  The null columns are
        stripped out.  Returns the values between delimiters and the
        corresponding start and end positions.

        Parameters
        ----------
        line : str
            Input line

        Returns
        -------
        vals : list
            List of values.
        starts : list
            List of starting indices.
        ends : list
            List of ending indices.

        Nc             S   s    g | ]}|d k	r|d nd qS )Nr   r	   )r   r   r	   r	   r   r      s    z:FixedWidthHeader.get_fixedwidth_params.<locals>.<listcomp>z=Fixed width col_starts and col_ends must have the same lengthc                s    g | ]\}} ||   qS r	   )strip)r   r
   r   )r   r	   r   r      s    r,   r   c             S   s   g | ]}|r|  qS r	   )rA   )r   r   r	   r	   r   r      s    z Error parsing fixed width headerc             S   s   g | ]}|d  qS )r   r	   )r   r   r	   r	   r   r      s    c                s    g | ]\}} ||   qS r	   )rA   )r   r
   r   )r   r	   r   r      s    )r:   r;   listr   r0   r   splitr6   r   appendr   )r   r   r<   r=   r   r   r	   )r   r   r2      s4    

$

z&FixedWidthHeader.get_fixedwidth_paramsc             C   s   d S )Nr	   )r   r   r	   r	   r   write   s    zFixedWidthHeader.write)r!   r"   r#   r$   r%   splitter_classr/   r5   r7   r+   r@   r2   rF   r	   r	   r	   r   r&   A   s   K>r&   c               @   s   e Zd ZdZeZdd ZdS )FixedWidthDataz!
    Base table data reader.
    c                s6  g }|   }xt| D ]}|| qW xPt| jD ]B\}tfdd|D |_| jjd k	r4t|jt	|j
j|_q4W dd | jD }| jjd k	r|| jdd | jD | | jjd k	r| jj t	 dkrtd  fdd| jD }|| j|| x"|D ]}|| j|| qW |S )Nc                s   g | ]}t |  qS r	   )r   )r   r   )r*   r	   r   r      s    z(FixedWidthData.write.<locals>.<listcomp>c             S   s   g | ]
}|j qS r	   )r   )r   r?   r	   r	   r   r      s    c             S   s   g | ]}|j jqS r	   )infoname)r   r?   r	   r	   r   r      s    r   z-Position_char="{}" must be a single characterc                s   g | ]} |j  qS r	   )r   )r   r?   )charr	   r   r      s    )Zstr_valsr   rE   r'   r   maxr   headerr.   r   rI   rJ   r6   r   r/   position_charr0   r-   )r   r   Z	vals_listZcol_str_itersr   r?   r    r	   )rK   r*   r   rF      s,    
zFixedWidthData.writeN)r!   r"   r#   r$   r   rG   rF   r	   r	   r	   r   rH      s   rH   c                   s2   e Zd ZdZdZdZeZeZ	d	 fdd	Z
  ZS )

FixedWidthar  
    Read or write a fixed width table with a single header line that defines column
    names and positions.  Examples::

      # Bar delimiter in header and data

      |  Col1 |   Col2      |  Col3 |
      |  1.2  | hello there |     3 |
      |  2.4  | many words  |     7 |

      # Bar delimiter in header only

      Col1 |   Col2      | Col3
      1.2    hello there    3
      2.4    many words     7

      # No delimiter with column positions specified as input

      Col1       Col2Col3
       1.2hello there   3
       2.4many words    7

    See the :ref:`fixed_width_gallery` for specific usage examples.

    Zfixed_widthzFixed widthNr   Tc                s2   t    || jj_|| jj_|| j_|| j_d S )N)	super__init__r1   r6   r   r   rM   r:   r;   )r   r:   r;   r   r   )	__class__r	   r   rQ   (  s
    


zFixedWidth.__init__)NNr   T)r!   r"   r#   r$   _format_name_descriptionr&   header_classrH   
data_classrQ   __classcell__r	   r	   )rR   r   rO     s   rO   c               @   s   e Zd ZdZdZdS )FixedWidthNoHeaderHeaderz7Header reader for fixed with tables with no header lineN)r!   r"   r#   r$   r.   r	   r	   r	   r   rX   0  s   rX   c               @   s   e Zd ZdZdZdS )FixedWidthNoHeaderDataz6Data reader for fixed width tables with no header liner,   N)r!   r"   r#   r$   r.   r	   r	   r	   r   rY   5  s   rY   c                   s2   e Zd ZdZdZdZeZeZ	d	 fdd	Z
  ZS )
FixedWidthNoHeaderaH  
    Read or write a fixed width table which has no header line.  Column
    names are either input (``names`` keyword) or auto-generated.  Column
    positions are determined either by input (``col_starts`` and ``col_stops``
    keywords) or by splitting the first data line.  In the latter case a
    ``delimiter`` is required to split the data line.

    Examples::

      # Bar delimiter in header and data

      |  1.2  | hello there |     3 |
      |  2.4  | many words  |     7 |

      # Compact table having no delimiter and column positions specified as input

      1.2hello there3
      2.4many words 7

    This class is just a convenience wrapper around the ``FixedWidth`` reader
    but with ``header.start_line = None`` and ``data.start_line = 0``.

    See the :ref:`fixed_width_gallery` for specific usage examples.

    Zfixed_width_no_headerzFixed width with no headerNr   Tc                s   t  j||||d d S )N)r   r   )rP   rQ   )r   r:   r;   r   r   )rR   r	   r   rQ   Y  s    zFixedWidthNoHeader.__init__)NNr   T)r!   r"   r#   r$   rS   rT   rX   rU   rY   rV   rQ   rW   r	   r	   )rR   r   rZ   :  s   rZ   c               @   s   e Zd ZdZeZdS )FixedWidthTwoLineHeaderzHeader reader for fixed width tables splitting on whitespace.

    For fixed width tables with several header lines, there is typically
    a white-space delimited format line, so splitting on white space is
    needed.
    N)r!   r"   r#   r$   r   rG   r	   r	   r	   r   r[   ^  s   r[   c               @   s   e Zd ZdZdZdS )FixedWidthTwoLineDataSplitterz5Splitter for fixed width tables splitting on ``' '``.r   N)r!   r"   r#   r$   r   r	   r	   r	   r   r\   h  s   r\   c               @   s   e Zd ZdZeZdS )FixedWidthTwoLineDataz8Data reader for fixed with tables with two header lines.N)r!   r"   r#   r$   r\   rG   r	   r	   r	   r   r]   m  s   r]   c                   s2   e Zd ZdZdZdZeZeZ	d
 fdd		Z
  ZS )FixedWidthTwoLinea  
    Read or write a fixed width table which has two header lines.  The first
    header line defines the column names and the second implicitly defines the
    column positions.  Examples::

      # Typical case with column extent defined by ---- under column names.

       col1    col2         <== header_start = 0
      -----  ------------   <== position_line = 1, position_char = "-"
        1     bee flies     <== data_start = 2
        2     fish swims

      # Pretty-printed table

      +------+------------+
      | Col1 |   Col2     |
      +------+------------+
      |  1.2 | "hello"    |
      |  2.4 | there world|
      +------+------------+

    See the :ref:`fixed_width_gallery` for specific usage examples.

    Zfixed_width_two_linez#Fixed width with second header liner   -NFc                s0   t  j||d || j_|| j_|d | j_d S )N)r   r   r   )rP   rQ   rM   r/   rN   r1   r.   )r   r/   rN   r   r   )rR   r	   r   rQ     s    zFixedWidthTwoLine.__init__)r   r_   NF)r!   r"   r#   r$   rS   rT   r]   rV   r[   rU   rQ   rW   r	   r	   )rR   r   r^   r  s   r^   N)r$   r   r   r   r   r   ZBaseSplitterr   r%   ZBasicHeaderr&   Z	BasicDatarH   ZBasicrO   rX   rY   rZ   r[   r\   r]   r^   r	   r	   r	   r   <module>	   s    * "&($
