B
    q\P                 @   s8  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Z	dddddd	d
ddddgZ
dgZe Ze Ze ZeejfZG dd deZe Ze jdd Zd*ddZdd Zd+ddZdd Zd,dd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#d$d
Z$dd#d%dZ%d&d' Z&d(d) Z'dS ).    N)OrderedDict)
itemgetterregister_readerregister_writerregister_identifieridentify_format
get_reader
get_writerreadwriteget_formatsIORegistryErrordelay_doc_updatesc               @   s   e Zd ZdZdS )r   z'Custom error for registry clashes.
    N)__name__
__module____qualname____doc__ r   r   2lib/python3.7/site-packages/astropy/io/registry.pyr      s   c             c   s2   t |  dV  t |  t| d t| d dS )a  Contextmanager to disable documentation updates when registering
    reader and writer. The documentation is only built once when the
    contextmanager exits.

    .. versionadded:: 1.3

    Parameters
    ----------
    cls : class
        Class for which the documentation updates should be delayed.

    Notes
    -----
    Registering multiple readers and writers can cause significant overhead
    because the documentation of the corresponding ``read`` and ``write``
    methods are build every time.

    .. warning::
        This contextmanager is experimental and may be replaced by a more
        general approach.

    Examples
    --------
    see for example the source code of ``astropy.table.__init__``.
    Nr
   r   )_delayed_docs_classesadddiscard_update__doc__)clsr   r   r   r   *   s
    


c          	   C   sb  ddl m} tttttB tdd}g }x|D ]}| dk	rPt| |d |sPq2|tkr\dnd}|tkrldnd}|tkr|dnd}d|d  |d f}	|	|krdnd	}
|	|d j
|d ||||
f q2W |dk	r|d
krdd |D }n"|dkrdd |D }ntd|r0ttt|tdddd }nd}||dd}t|d dks^|d |S )a  
    Get the list of registered I/O formats as a Table.

    Parameters
    ----------
    data_class : classobj, optional
        Filter readers/writer to match data class (default = all classes).

    readwrite : str or None, optional
        Search only for readers (``"Read"``) or writers (``"Write"``). If None
        search for both.  Default is None.

        .. versionadded:: 1.3

    Returns
    -------
    format_table : Table
        Table of available I/O formats.
    r   )Table)keyN   YesZNozascii. Readc             S   s   g | ]}|d  dkr|qS )   r   r   ).0rowr   r   r   
<listcomp>{   s    zget_formats.<locals>.<listcomp>Writec             S   s   g | ]}|d  dkr|qS )   r   r   )r!   r"   r   r   r   r#   }   s    zQunrecognized value for "readwrite": {0}.
Allowed are "Read" and "Write" and None.   )z
Data classZFormatr   r$   zAuto-identify
Deprecated)namesr'   )Zastropy.tabler   sortedset_readers_writersr   _is_best_match_identifiersappendr   
ValueErrorlistzipnpanyremove_column)
data_class	readwriter   format_classesZrowsZformat_classZhas_readZ	has_writeZhas_identifyZascii_format_classZ
deprecateddataformat_tabler   r   r   r   N   s6    




c       
         sP  d t | |}t|jtsdS |j } fddt|D }|rV|d }|d| }dd |dd D }dtd	d
 |D  t| | }|	d |j
ddd}tdd|d }	|	|d< |d|	 ||	 d|jkr|dddg  dg| }|fdd|D  yd||_W n$ tk
rJ   d||j_Y nX dS )z
    Update the docstring to include all the available readers / writers for the
    ``data_class.read`` or ``data_class.write`` functions (respectively).
    z#The available built-in formats are:Nc                s   g | ]\}} |kr|qS r   r   )r!   Ziiline)FORMATS_TEXTr   r   r#      s    z"_update__doc__.<locals>.<listcomp>r   c             S   s   g | ]}t d |qS )z(\S))research)r!   r;   r   r   r   r#      s    r    c             s   s   | ]}|r|  V  qd S )N)start)r!   matchr   r   r   	<genexpr>   s    z!_update__doc__.<locals>.<genexpr>z
Data classP   )	max_linesZ	max_width-=r'   r   zZDeprecated format names like ``aastex`` will be removed in a future version. Use the full z%name (e.g. ``ascii.aastex``) instead.c                s   g | ]} | qS r   r   )r!   r;   )left_indentr   r   r#      s    
)getattr
isinstancer   str
splitlines	enumerateminr   
capitalizer5   pformatr=   subinsertr/   ZcolnamesextendjoinAttributeError__func__)
r6   r7   Zclass_readwrite_funclinesZsep_indicesZ
chop_indexZmatchesr:   Z	new_linesZtable_rst_sepr   )r<   rH   r   r      s8    




r   Fc             C   sF   | |ft ks|r|t | |f< ntd| |j|tkrBt|d dS )a  
    Register a reader function.

    Parameters
    ----------
    data_format : str
        The data format identifier. This is the string that will be used to
        specify the data type when reading.
    data_class : classobj
        The class of the object that the reader produces.
    function : function
        The function to read in a data object.
    force : bool, optional
        Whether to override any existing function if already present.
        Default is ``False``.
    z:Reader for format '{0}' and class '{1}' is already definedr
   N)r+   r   formatr   r   r   )data_formatr6   functionforcer   r   r   r      s    c             C   sD   | |ft krt | |f ntd| |j|tkr@t|d dS )z
    Unregister a reader function

    Parameters
    ----------
    data_format : str
        The data format identifier.
    data_class : classobj
        The class of the object that the reader produces.
    z2No reader defined for format '{0}' and class '{1}'r
   N)r+   popr   rY   r   r   r   )rZ   r6   r   r   r   unregister_reader   s    r^   c             C   sF   | |ft ks|r|t | |f< ntd| |j|tkrBt|d dS )a  
    Register a table writer function.

    Parameters
    ----------
    data_format : str
        The data format identifier. This is the string that will be used to
        specify the data type when writing.
    data_class : classobj
        The class of the object that can be written.
    function : function
        The function to write out a data object.
    force : bool, optional
        Whether to override any existing function if already present.
        Default is ``False``.
    z:Writer for format '{0}' and class '{1}' is already definedr   N)r,   r   rY   r   r   r   )rZ   r6   r[   r\   r   r   r   r      s    c             C   sD   | |ft krt | |f ntd| |j|tkr@t|d dS )z
    Unregister a writer function

    Parameters
    ----------
    data_format : str
        The data format identifier.
    data_class : classobj
        The class of the object that can be written.
    z2No writer defined for format '{0}' and class '{1}'r   N)r,   r]   r   rY   r   r   r   )rZ   r6   r   r   r   unregister_writer  s    r_   c             C   s4   | |ft ks|r|t | |f< ntd| |jdS )a2  
    Associate an identifier function with a specific data type.

    Parameters
    ----------
    data_format : str
        The data format identifier. This is the string that is used to
        specify the data type when reading/writing.
    data_class : classobj
        The class of the object that can be written.
    identifier : function
        A function that checks the argument specified to `read` or `write` to
        determine whether the input can be interpreted as a table of type
        ``data_format``. This function should take the following arguments:

           - ``origin``: A string ``"read"`` or ``"write"`` identifying whether
             the file is to be opened for reading or writing.
           - ``path``: The path to the file.
           - ``fileobj``: An open file object to read the file's contents, or
             `None` if the file could not be opened.
           - ``*args``: Positional arguments for the `read` or `write`
             function.
           - ``**kwargs``: Keyword arguments for the `read` or `write`
             function.

        One or both of ``path`` or ``fileobj`` may be `None`.  If they are
        both `None`, the identifier will need to work from ``args[0]``.

        The function should return True if the input can be identified
        as being of format ``data_format``, and False otherwise.
    force : bool, optional
        Whether to override any existing function if already present.
        Default is ``False``.

    Examples
    --------
    To set the identifier based on extensions, for formats that take a
    filename as a first argument, you can do for example::

        >>> def my_identifier(*args, **kwargs):
        ...     return isinstance(args[0], str) and args[0].endswith('.tbl')
        >>> register_identifier('ipac', Table, my_identifier)
    z>Identifier for format '{0}' and class '{1}' is already definedN)r.   r   rY   r   )rZ   r6   Z
identifierr\   r   r   r   r   3  s
    -c             C   s2   | |ft krt | |f ntd| |jdS )z
    Unregister an identifier function

    Parameters
    ----------
    data_format : str
        The data format identifier.
    data_class : classobj
        The class of the object that can be read/written.
    z6No identifier defined for format '{0}' and class '{1}'N)r.   r]   r   rY   r   )rZ   r6   r   r   r   unregister_identifierh  s    r`   c       	      C   sL   g }xBt D ]:\}}t||t r
t ||f | ||f||r
|| q
W |S )a  Loop through identifiers to see which formats match.

    Parameters
    ----------
    origin : str
        A string ``"read`` or ``"write"`` identifying whether the file is to be
        opened for reading or writing.
    data_class_required : object
        The specified class for the result of `read` or the class that is to be
        written.
    path : str, other path object or None
        The path to the file or None.
    fileobj : File object or None.
        An open file object to read the file's contents, or ``None`` if the
        file could not be opened.
    args : sequence
        Positional arguments for the `read` or `write` function. Note that
        these must be provided as sequence.
    kwargs : dict-like
        Keyword arguments for the `read` or `write` function. Note that this
        parameter must be `dict`-like.

    Returns
    -------
    valid_formats : list
        List of matching formats.
    )r.   r-   r/   )	originZdata_class_requiredpathfileobjargskwargsvalid_formatsrZ   r6   r   r   r   r   {  s    
c             C   s,   t | |d}|d d|jdd}|S )N)r7   z
Data classrI   rC   )rE   )r   r5   rU   rQ   )r6   r7   r:   format_table_strr   r   r   _get_format_table_str  s    
rh   c                s^    fddt D }xF|D ] \}}t|||rt ||f S qW t|d}td |j|dS )a  Get reader for ``data_format``.

    Parameters
    ----------
    data_format : str
        The data format identifier. This is the string that is used to
        specify the data type when reading/writing.
    data_class : classobj
        The class of the object that can be written.

    Returns
    -------
    reader : callable
        The registered reader function for this format and class.
    c                s    g | ]\}}| kr||fqS r   r   )r!   fmtr   )rZ   r   r   r#     s    zget_reader.<locals>.<listcomp>r   zRNo reader defined for format '{0}' and class '{1}'.
The available formats are:
{2}N)r+   r-   rh   r   rY   r   )rZ   r6   ZreadersZreader_formatZreader_classrg   r   )rZ   r   r     s    
c                s^    fddt D }xF|D ] \}}t|||rt ||f S qW t|d}td |j|dS )a  Get writer for ``data_format``.

    Parameters
    ----------
    data_format : str
        The data format identifier. This is the string that is used to
        specify the data type when reading/writing.
    data_class : classobj
        The class of the object that can be written.

    Returns
    -------
    writer : callable
        The registered writer function for this format and class.
    c                s    g | ]\}}| kr||fqS r   r   )r!   ri   r   )rZ   r   r   r#     s    zget_writer.<locals>.<listcomp>r$   zRNo writer defined for format '{0}' and class '{1}'.
The available formats are:
{2}N)r,   r-   rh   r   rY   r   )rZ   r6   ZwritersZwriter_formatZwriter_classrg   r   )rZ   r   r	     s    
)rY   c      
   	   O   sp  d}zJ|dkrd}d}t |rt|d trddlm} t|d tjrdt|d f|dd  }|d }y||d dd}| }W n, t	k
r    Y q t
k
r   d}Y qX |gt|dd  }nt|d drd}|d }td| ||||}t|| }|||}	t|	| sNy| |	}	W n& t
k
rL   td| jY nX W d|dk	rj|jt   X |	S )	zV
    Read in data.

    The arguments passed to this method depend on the format.
    Nr   )get_readable_fileobjr   Zbinary)encodingr
   z-could not convert reader output to {0} class.)lenrK   
PATH_TYPESZastropy.utils.datarj   pathlibPathrL   	__enter__OSError	Exceptionr1   hasattr_get_valid_formatr   	TypeErrorrY   r   __exit__sysexc_info)
r   rY   rd   re   Zctxrb   rc   rj   readerr9   r   r   r   r
     sF    



c            O   s   |dkrd}d}t |rxt|d tr^t|d tjrPt|d f|dd  }|d }d}nt|d drxd}|d }td| j||||}t	|| j}|| f|| dS )zX
    Write out data.

    The arguments passed to this method depend on the format.
    Nr   r   r
   r   )
rl   rK   rm   rn   ro   rL   rs   rt   	__class__r	   )r9   rY   rd   re   rb   rc   writerr   r   r   r     s     c             C   sD   t | |r@dd |D }x&| jD ]}||kr0dS ||kr dS q W dS )ad  
    Determine if class2 is the "best" match for class1 in the list
    of classes.  It is assumed that (class2 in classes) is True.
    class2 is the the best match if:

    - ``class1`` is a subclass of ``class2`` AND
    - ``class2`` is the nearest ancestor of ``class1`` that is in classes
      (which includes the case that ``class1 is class2``)
    c             S   s   h | ]\}}|qS r   r   )r!   ri   r   r   r   r   	<setcomp>>  s    z!_is_best_match.<locals>.<setcomp>TF)
issubclass__mro__)Zclass1Zclass2r8   classesparentr   r   r   r-   3  s    

r-   c          	   C   sp   t | |||||}t|dkr<t||  }td|n,t|dkrhtddt|tdd|d S )z
    Returns the first valid format that can be used to read/write the data in
    question.  Mode can be either 'read' or 'write'.
    r   z>Format could not be identified.
The available formats are:
{0}r   z&Format is ambiguous - options are: {0}z, )r   )	r   rl   rh   rP   r   rY   rU   r)   r   )moder   rb   rc   rd   re   rf   rg   r   r   r   rt   G  s    
rt   )NN)F)F)F)(
contextlibrn   r=   rw   collectionsr   operatorr   Znumpyr3   __all__Z__doctest_skip__r+   r,   r.   rL   ro   rm   rr   r   r*   r   contextmanagerr   r   r   r   r^   r   r_   r   r`   r   rh   r   r	   r
   r   r-   rt   r   r   r   r   <module>   sB   


	$
D;


5&7