a
    ߙfbB6                     @   s   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g dZG dd de	Z
G dd deZdd	 Zdd
dZdd Zdd Zdd Zdd Zdd Zdd Zdd ZG dd deZdd ZdS )    N)OrderedDict)get_header_from_yamlget_yaml_from_headerget_yaml_from_tablec                       s    e Zd ZdZ fddZ  ZS )ColumnOrderListzq
    List of tuples that sorts in a specific order that makes sense for
    astropy table column attributes.
    c                    s~   t    g d}t| }g }|D ]}||v r"|||| f q"| D ]\}}||vrF|||f qF| d d = | | d S )N)nameunitdatatypeformatdescriptionmeta)supersortdictappendextend)selfargskwargsZcolumn_keysZin_dictZout_listkeyval	__class__ 1lib/python3.9/site-packages/astropy/table/meta.pyr      s    

zColumnOrderList.sort)__name__
__module____qualname____doc__r   __classcell__r   r   r   r   r      s   r   c                       s    e Zd ZdZ fddZ  ZS )
ColumnDictz
    Specialized dict subclass to represent attributes of a Column
    and return items() in a preferred order.  This is only for use
    in generating a YAML map representation that has a fixed order.
    c                    s   t t  S )zt
        Return items as a ColumnOrderList, which sorts in the preferred
        way for column attributes.
        )r   r   items)r   r   r   r   r!   -   s    zColumnDict.items)r   r   r   r   r!   r   r   r   r   r   r    &   s   r    c                 c   s   t  }|V  t|tjs6tjd|jd|j |j|jD ]}t|tj	sjtjd|jd|j |jt
|jdkrtjd|jdt
|j d|j|jd \}}| |}| |}|||< q<dS )	a  
    Construct OrderedDict from !!omap in yaml safe load.

    Source: https://gist.github.com/weaver/317164
    License: Unspecified

    This is the same as SafeConstructor.construct_yaml_omap(),
    except the data type is changed to OrderedDict() and setitem is
    used instead of append in the loop

    Examples
    --------
    ::

      >>> yaml.load('''  # doctest: +SKIP
      ... !!omap
      ... - foo: bar
      ... - mumble: quux
      ... - baz: gorp
      ... ''')
      OrderedDict([('foo', 'bar'), ('mumble', 'quux'), ('baz', 'gorp')])

      >>> yaml.load('''!!omap [ foo: bar, mumble: quux, baz : gorp ]''')  # doctest: +SKIP
      OrderedDict([('foo', 'bar'), ('mumble', 'quux'), ('baz', 'gorp')])
    z!while constructing an ordered mapzexpected a sequence, but found z*expected a mapping of length 1, but found    z*expected a single mapping item, but found z itemsr   N)r   
isinstanceyamlSequenceNodeconstructorZConstructorErrorZ
start_markidvalueMappingNodelenZconstruct_object)loadnodeZomapZsubnodeZkey_nodeZ
value_noder   r(   r   r   r   _construct_odict5   s0    



r-   c           
      C   s   g }t j|||d}| jdur*|| j| j< d}|D ]6\}}| ||i}	t|	t jrZ|	jr^d}||	 q2|du r| j	dur| j	|_
n||_
|S )z
    This is the same code as BaseRepresenter.represent_sequence(),
    but the value passed to dump.represent_data() in the loop is a
    dictionary instead of a tuple.

    Source: https://gist.github.com/weaver/317164
    License: Unspecified
    
flow_styleNTF)r$   r%   	alias_keyrepresented_objectsrepresent_datar#   
ScalarNodestyler   default_flow_styler/   )
dumptagZsequencer/   r(   r,   
best_styler   r   itemr   r   r   _repr_pairsi   s    	


r:   c                 C   s   t | d| S )a  
    Represent OrderedDict in yaml dump.

    Source: https://gist.github.com/weaver/317164
    License: Unspecified

    >>> data = OrderedDict([('foo', 'bar'), ('mumble', 'quux'), ('baz', 'gorp')])
    >>> yaml.dump(data, default_flow_style=False)  # doctest: +SKIP
    '!!omap\n- foo: bar\n- mumble: quux\n- baz: gorp\n'
    >>> yaml.dump(data, default_flow_style=True)  # doctest: +SKIP
    '!!omap [foo: bar, mumble: quux, baz: gorp]\n'
    tag:yaml.org,2002:omap)r:   r!   Zdumperdatar   r   r   _repr_odict   s    r>   c                 C   s   |  d|S )z
    Represent ColumnDict in yaml dump.

    This is the same as an ordinary mapping except that the keys
    are written in a fixed order that makes sense for astropy table
    columns.
    ztag:yaml.org,2002:map)represent_mappingr<   r   r   r   _repr_column_dict   s    r@   c                 C   s   G dd dt }tjtjtjtjf}zt| dksDtdd | D sH|| d j}| d j	dd }| D ]6}t
|jj|r|j	dd |kr|t||j}qh|d }W n |y   | jj}d	}Y n0 ||fS )
aL  Check if object-type ``col`` is really a variable length list.

    That is true if the object consists purely of list of nested lists, where
    the shape of every item can be represented as (m, n, ..., *) where the (m,
    n, ...) are constant and only the lists in the last axis have variable
    shape. If so the returned value of shape will be a tuple in the form (m, n,
    ..., None).

    If ``col`` is a variable length array then the return ``dtype`` corresponds
    to the type found by numpy for all the individual values. Otherwise it will
    be ``np.dtype(object)``.

    Parameters
    ==========
    col : column-like
        Input table column, assumed to be object-type

    Returns
    =======
    shape : tuple
        Inferred variable length shape or None
    dtype : np.dtype
        Numpy dtype that applies to col
    c                   @   s   e Zd ZdZdS )z6_get_variable_length_array_shape.<locals>.ConvertErrorz!Local conversion error used belowNr   r   r   r   r   r   r   r   ConvertError   s   rB   r   c                 s   s   | ]}t |tjV  qd S N)r#   npZndarray).0r   r   r   r   	<genexpr>       z3_get_variable_length_array_shape.<locals>.<genexpr>NrC   r   )
ValueErrorrD   ZfloatingZintegerZbool_Zunicode_r*   alldtypeshape
issubclasstypeZpromote_typesinfo)colrB   Z
np_classesrK   rL   r   r   r   r    _get_variable_length_array_shape   s     
 
rQ   c                 C   s.   | j }|drd}|dr*|dd }|S )zCReturn string version of ``dtype`` for writing to ECSV ``datatype``)bytesstrstring_NrH   )r   
startswithendswith)rK   r	   r   r   r   _get_datatype_from_dtype   s    

rX   c           
      C   sJ  | j j}d}| jdd }|jdkrZ|dkrDtt}t| \}}qptt}tt}n|rptt}| j j}t|}t	 }| j j|d< ||d< ddd	 tfd
dd	 dfddd	 dfddd	 dffD ]2\}}}t
| j |}	||	r|r||	n|	||< q|r"t||d< |d dkr"d|d< |rF|d  tjt|dd7  < |S )a  
    Extract information from a column (apart from the values) that is required
    to fully serialize the column.

    Parameters
    ----------
    col : column-like
        Input Table column

    Returns
    -------
    attrs : dict
        Dict of ECSV attributes for ``col``
    Nr"   objectr   r   r	   r   c                 S   s   | d uS rC   r   xr   r   r   <lambda>  rG   z%_get_col_attributes.<locals>.<lambda>r
   c                 S   s   | d uS rC   r   rZ   r   r   r   r\     rG   r   c                 S   s   | d uS rC   r   rZ   r   r   r   r\     rG   r   c                 S   s   | S rC   r   rZ   r   r   r   r\     rG   subtypejson),:)Z
separators)rO   rK   rL   r   rD   rS   rQ   rY   rX   r    getattrr^   dumpslist)
rP   rK   r]   rL   r	   attrsattrZ
nontrivialZxformZcol_attrr   r   r   _get_col_attributes   s>    



rf   c                 C   s*   dt | j i}| jr"| j|d< t|S )a/  
    Return lines with a YAML representation of header content from the ``table``.

    Parameters
    ----------
    table : `~astropy.table.Table` object
        Table for which header content is output

    Returns
    -------
    lines : list
        List of text lines with YAML header content
    colsr   )rc   columnsvaluesr   r   )tableheaderr   r   r   r     s    
r   c                 C   st   ddl m} G dd d|}|tt |tt t| } dd | d D | d< | d= tj	| d	|d
d
 }|S )a  
    Return lines with a YAML representation of header content from a Table.

    The ``header`` dict must contain these keys:

    - 'cols' : list of table column objects (required)
    - 'meta' : table 'meta' attribute (optional)

    Other keys included in ``header`` will be serialized in the output YAML
    representation.

    Parameters
    ----------
    header : dict
        Table header content

    Returns
    -------
    lines : list
        List of text lines with YAML header content
    r   )AstropyDumperc                   @   s   e Zd ZdZdddZdS )z)get_yaml_from_header.<locals>.TableDumperzP
        Custom Dumper that represents OrderedDict as an !!omap object.
        Nc                 S   s   g }t j|||d}| jdur*|| j| j< d}t|dr|| }t|drT|  n(t|}zt|}W n t	yz   Y n0 |D ]V\}}| 
|}	| 
|}
t|	t jr|	jrd}t|
t jr|
jrd}||	|
f q|du r| jdur| j|_n||_|S )a|  
            This is a combination of the Python 2 and 3 versions of this method
            in the PyYAML library to allow the required key ordering via the
            ColumnOrderList object.  The Python 3 version insists on turning the
            items() mapping into a list object and sorting, which results in
            alphabetical order for the column keys.
            r.   NTr!   r   F)r$   r)   r0   r1   hasattrr!   r   rc   sorted	TypeErrorr2   r#   r3   r4   r   r5   r/   )r   r7   mappingr/   r(   r,   r8   Zitem_keyZ
item_valueZnode_keyZ
node_valuer   r   r   r?   J  s6    







z;get_yaml_from_header.<locals>.TableDumper.represent_mapping)N)r   r   r   r   r?   r   r   r   r   TableDumperE  s   rq   c                 S   s   g | ]}t |qS r   )rf   )rE   rP   r   r   r   
<listcomp>u  rG   z(get_yaml_from_header.<locals>.<listcomp>rg   r	   N   )r5   ZDumperwidth)astropy.io.misc.yamlrl   Zadd_representerr   r>   r    r@   copyr$   r6   
splitlines)rk   rl   rq   linesr   r   r   r   -  s    ,

r   c                   @   s   e Zd ZdS )YamlParseErrorN)r   r   r   r   r   r   r   ry   }  s   ry   c              
   C   s|   ddl m} G dd d|}|dt td| }ztj||d}W n, t	yv } zt
 |W Y d}~n
d}~0 0 |S )	aS  
    Get a header dict from input ``lines`` which should be valid YAML.  This
    input will typically be created by get_yaml_from_header.  The output is a
    dictionary which describes all the table and column meta.

    The get_cols() method in the io/ascii/ecsv.py file should be used as a
    guide to using the information when constructing a table using this
    header dict information.

    Parameters
    ----------
    lines : list
        List of text lines with YAML header content

    Returns
    -------
    header : dict
        Dictionary describing table and column meta

    r   )AstropyLoaderc                   @   s   e Zd ZdZdS )z)get_header_from_yaml.<locals>.TableLoaderz
        Custom Loader that constructs OrderedDict from an !!omap object.
        This does nothing but provide a namespace for adding the
        custom odict constructor.
        NrA   r   r   r   r   TableLoader  s   r{   r;   
)LoaderN)ru   rz   Zadd_constructorr-   textwrapdedentjoinr$   r+   	Exceptionry   )rx   rz   r{   Zheader_yamlrk   errr   r   r   r     s    r   )N)r^   r~   rv   collectionsr   ZnumpyrD   r$   __all__rc   r   r   r    r-   r:   r>   r@   rQ   rX   rf   r   r   r   ry   r   r   r   r   r   <module>   s&   4
4
:P