B
    q\,                 @   s   d Z ddlZddlmZ ddlZddl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
giZdZd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jZdS )z
Define the Enhanced Character-Separated-Values (ECSV) which allows for reading and
writing all the meta data associated with an astropy Table object.
    N)OrderedDict   )corebasic)meta	serialize)serialize_context_as)AstropyWarningEcsvZyamlz0.9) ,c                   s@   e Zd ZdZdd Zdd Zdd Zdd	 Z fd
dZ  Z	S )
EcsvHeaderzHeader class for which the column definition line starts with the
    comment character.  See the :class:`CommentedHeader` class  for an example.
    c             c   sZ   t | j}xH|D ]@}| }|s$q||}|rN|| d }|rR|V  qdS qW dS )zReturn only non-blank lines that start with the comment regexp.  For these
        lines strip out the matching characters and leading/trailing whitespace.N)recompilecommentstripmatchend)selflinesZ
re_commentliner   out r   4lib/python3.7/site-packages/astropy/io/ascii/ecsv.pyprocess_lines   s    

zEcsvHeader.process_linesc                s    j jtkrtdx4 jD ]*}tt|dddkrtd|jj	qW  jdd} j
rf j
|d<  j jd	kr~ j j|d
< dtdgt| }| fdd|D  | j dd  jD  dS )a  
        Write header information in the ECSV ASCII format.  This format
        starts with a delimiter separated list of the column names in order
        to make this format readable by humans and simple csv-type readers.
        It then encodes the full table meta and column attributes and meta
        as YAML and pretty-prints this in the header.  Finally the delimited
        column names are repeated again, for humans and readers that look
        for the *last* comment line as defining the column names.
        z=only space and comma are allowed for delimiter in ECSV formatshaper   r   z:ECSV format does not support multidimensional column '{0}'zastropy-2.0)colsZschemar   r   	delimiterz	%ECSV {0}z---c                s   g | ]} j | qS r   )Zwrite_comment).0r   )r   r   r   
<listcomp>L   s    z$EcsvHeader.write.<locals>.<listcomp>c             S   s   g | ]}|j jqS r   )infoname)r   xr   r   r   r   M   s    N)splitterr   
DELIMITERS
ValueErrorr   lengetattrformatr    r!   
table_metaECSV_VERSIONr   Zget_yaml_from_headerextendappendjoin)r   r   colheaderZheader_yaml_linesr   )r   r   write,   s     

zEcsvHeader.writec             C   s   dS )z}
        Override the default write_comments to do nothing since this is handled
        in the custom write method.
        Nr   )r   r   r   r   r   r   write_commentsO   s    zEcsvHeader.write_commentsc             C   s   dS )z~
        Override the default update_meta to do nothing.  This process is done
        in get_cols() for this reader.
        Nr   )r   r   r   r   r   r   update_metaV   s    zEcsvHeader.update_metac          
      s  |}t | |}d}d}|s(t|t||d  tj}|sNt|yt	|}W nb t
k
r } z&dt|krtdt tdW dd}~X Y n  tjk
r   tdY nX d	|kr|d	 | _d
|kr|d
 }|tkrtd|| j_|| jj_tdd |d D }	dd |d D | _tt |}
t| |
g}|| jkrptd| j||   x~| jD ]t}x4dD ],}||	|j krt|||	|j |  qW |	|j d |_|jdkrd|_|j drt!dqW dS )z
        Initialize the header Column objects from the table ``lines``.

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

        z%ECSV [ ]
                             (?P<major> \d+)
                             \. (?P<minor> \d+)
                             \.? (?P<bugfix> \d+)? $zeECSV header line like "# %ECSV <version>" not found as first line.  This is required for a ECSV file.r   zPyYAML package is requiredzVfile looks like ECSV format but PyYAML is not installed so it cannot be parsed as ECSVz@unable to parse yaml in meta header (PyYAML package is required)Nz#unable to parse yaml in meta headerr   r   z=only space and comma are allowed for delimiter in ECSV formatc             s   s   | ]}|d  |fV  qdS )r!   Nr   )r   r"   r   r   r   	<genexpr>   s    z&EcsvHeader.get_cols.<locals>.<genexpr>Zdatatypec             S   s   g | ]}|d  qS )r!   r   )r   r"   r   r   r   r      s    z'EcsvHeader.get_cols.<locals>.<listcomp>zScolumn names from ECSV header {} do not match names from header line of CSV data {})Zdescriptionr(   Zunitr   stringstrcomplexz1ecsv reader does not support complex number types)"listr   r   ZInconsistentTableErrorr   r   r   VERBOSEr   Zget_header_from_yamlImportErrorr5   warningswarnr	   ZYamlParseErrorr)   r$   r%   r#   r   datar   namesnextsuperr(   Z_set_cols_from_namesr   r!   setattrdtype
startswith	TypeError)r   r   Z	raw_linesZecsv_header_reZno_header_msgr   r/   excr   Zheader_colsZheader_lineZheader_namesr.   attr)	__class__r   r   get_cols]   sV    





zEcsvHeader.get_cols)
__name__
__module____qualname____doc__r   r0   r1   r2   rG   __classcell__r   r   )rF   r   r      s   #r   c                   s$   e Zd ZdZg Z fddZ  ZS )EcsvOutputtera  
    After reading the input lines and processing, convert the Reader columns
    and metadata to an astropy.table.Table object.  This overrides the default
    converters to be an empty list because there is no "guessing" of the
    conversion function.
    c                s   t  ||}t|}|S )N)r?   __call__r   Z_construct_mixins_from_columns)r   r   r   r   )rF   r   r   rN      s    
zEcsvOutputter.__call__)rH   rI   rJ   rK   Zdefault_convertersrN   rL   r   r   )rF   r   rM      s   rM   c                   s   e Zd Z fddZ  ZS )EcsvDatac          	      st   t  | y| jjd }W n ttfk
r4   dS X x8|D ]0}|jdkr<|j|kr<||j d dkr<i |_q<W dS )a2  Set the fill values of the individual cols based on fill_values of BaseData

        For ECSV handle the corner case of data that has been serialized using
        the serialize_method='data_mask' option, which writes the full data and
        mask directly, AND where that table includes a string column with zero-length
        string entries ("") which are valid data.

        Normally the super() method will set col.fill_value=('', '0') to replace
        blanks with a '0'.  But for that corner case subset, instead do not do
        any filling.
        Z__serialized_columns__Nr5   rF   z!astropy.table.column.MaskedColumn)	r?   _set_fill_valuesr/   r)   AttributeErrorKeyErrorrA   r!   Zfill_values)r   r   Zscsr.   )rF   r   r   rP      s    
zEcsvData._set_fill_values)rH   rI   rJ   rP   rL   r   r   )rF   r   rO      s   rO   c               @   s0   e Zd ZdZdZdZdZeZe	Z
eZdd ZdS )r
   a%  
    Read a file which conforms to the ECSV (Enhanced Character Separated
    Values) format.  This format allows for specification of key table
    and column meta-data, in particular the data type and unit.  For details
    see: https://github.com/astropy/astropy-APEs/blob/master/APE6.rst.

    Examples
    --------

    >>> from astropy.table import Table
    >>> ecsv_content = '''# %ECSV 0.9
    ... # ---
    ... # datatype:
    ... # - {name: a, unit: m / s, datatype: int64, format: '%03d'}
    ... # - {name: b, unit: km, datatype: int64, description: This is column b}
    ... a b
    ... 001 2
    ... 004 3
    ... '''
    >>> Table.read(ecsv_content, format='ascii.ecsv')
    <Table length=2>
      a     b
    m / s   km
    int64 int64
    ----- -----
      001     2
      004     3
    ecsvzEnhanced CSVz.ecsvc          	   C   s"   t d t|}W dQ R X |S )a  
        Update table columns in place if mixin columns are present.

        This is a hook to allow updating the table columns after name
        filtering but before setting up to write the data.  This is currently
        only used by ECSV and is otherwise just a pass-through.

        Parameters
        ----------
        table : `astropy.table.Table`
            Input table for writing

        Returns
        -------
        table : `astropy.table.Table`
            Output table for writing
        rS   N)r   r   Z_represent_mixins_as_columns)r   tabler   r   r   r   update_table_data  s    
zEcsv.update_table_dataN)rH   rI   rJ   rK   Z_format_nameZ_descriptionZ_io_registry_suffixr   Zheader_classrO   Z
data_classrM   Zoutputter_classrU   r   r   r   r   r
      s   )rK   r   collectionsr   
contextlibr:    r   r   Zastropy.tabler   r   Zastropy.utils.data_infor   Zastropy.utils.exceptionsr	   Z__doctest_requires__r*   r$   ZBasicHeaderr   ZTableOutputterrM   Z	BasicDatarO   ZBasicr
   r   r   r   r   <module>   s    
 