B
    dvi                 @   sj  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	Z
dd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d1ddZdd Zd2ddZdd Zd3ddZdd Zd4ddZdd Z d d Z!d!d" Z"d#d Z#d$d	 Z$ddd%d&d
Z%dd'd(dZ&d)d* Z'd+d, Z(d-d. Z)G d/d dZ*G d0d dZ+dS )5    N)OrderedDict)
itemgetterregister_readerregister_writerregister_identifieridentify_format
get_reader
get_writerreadwriteget_formatsIORegistryErrordelay_doc_updatesUnifiedReadWriteMethodUnifiedReadWritec               @   s   e Zd ZdZdS )r   z'Custom error for registry clashes.
    N)__name__
__module____qualname____doc__ r   r   `/work/yifan.wang/ringdown/master-ringdown-env/lib/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 : class, 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 : :class:`~astropy.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>z   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_classesrowsZformat_classZhas_readZ	has_writeZhas_identifyZascii_format_class
deprecateddataformat_tabler   r   r   r   M   s6    




c       
         sl  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  t|tr2d||j_n6yd||_W n$ tk
rf   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#   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_lines	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   
capitalizer7   pformatrB   subinsertr1   Zcolnamesextendr   join	__class__AttributeError__func__)
r8   r9   Zclass_readwrite_funclinesZsep_indicesZ
chop_indexmatchesr>   	new_linesZtable_rst_sepr   )rA   rN   r   r      s<    




r   Fc             C   sJ   | |ft ks|r"||ft | |f< ntd| |j|tkrFt|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 : class
        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``.
    priority : int, optional
        The priority of the reader, used to compare possible formats when trying
        to determine the best reader to use. Higher priorities are preferred
        over lower priorities, with the default priority being 0 (negative
        numbers are allowed though).
    z8Reader for format '{}' and class '{}' is already definedr
   N)r-   r   formatr   r   r   )data_formatr8   functionforcepriorityr   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 : class
        The class of the object that the reader produces.
    z0No reader defined for format '{}' and class '{}'r
   N)r-   popr   rb   r   r   r   )rc   r8   r   r   r   unregister_reader   s    rh   c             C   sJ   | |ft ks|r"||ft | |f< ntd| |j|tkrFt|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 : class
        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``.
    priority : int, optional
        The priority of the writer, used to compare possible formats when trying
        to determine the best writer to use. Higher priorities are preferred
        over lower priorities, with the default priority being 0 (negative
        numbers are allowed though).
    z8Writer for format '{}' and class '{}' is already definedr   N)r.   r   rb   r   r   r   )rc   r8   rd   re   rf   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 : class
        The class of the object that can be written.
    z0No writer defined for format '{}' and class '{}'r   N)r.   rg   r   rb   r   r   r   )rc   r8   r   r   r   unregister_writer'  s    ri   c             C   s4   | |ft ks|r|t | |f< ntd| |jdS )a/  
    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 : class
        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 '{}' and class '{}' is already definedN)r0   r   rb   r   )rc   r8   
identifierre   r   r   r   r   =  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 : class
        The class of the object that can be read/written.
    z4No identifier defined for format '{}' and class '{}'N)r0   rg   r   rb   r   )rc   r8   r   r   r   unregister_identifierr  s    rk   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 or path-like or None
        The path to the file or None.
    fileobj : file-like 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.
    )r0   r/   r1   )	originZdata_class_requiredpathfileobjargskwargsvalid_formatsrc   r8   r   r   r   r     s    
c             C   s,   t | |d}|d d|jdd}|S )N)r9   z
Data classrO   rH   )rJ   )r   r7   r[   rW   )r8   r9   r>   format_table_strr   r   r   _get_format_table_str  s    
rs   c                sb    fddt D }xJ|D ]$\}}t|||rt ||f d 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 : class
        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   )rc   r   r   r%     s    zget_reader.<locals>.<listcomp>r   r!   zQNo reader defined for format '{}' and class '{}'.

The available formats are:

{}N)r-   r/   rs   r   rb   r   )rc   r8   ZreadersZreader_formatZreader_classrr   r   )rc   r   r     s    
c                sb    fddt D }xJ|D ]$\}}t|||rt ||f d 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 : class
        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#   rt   r   )rc   r   r   r%     s    zget_writer.<locals>.<listcomp>r   r&   zQNo writer defined for format '{}' and class '{}'.

The available formats are:

{}N)r.   r/   rs   r   rb   r   )rc   r8   ZwritersZwriter_formatZwriter_classrr   r   )rc   r   r	     s    
)rb   cachec         	   O   s  d}z`|dkrd}d}t |rt|d trtj|d sddlm} t|d tjrxt	|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|
| sdy| |
}
W n& tk
rb   td| jY nX W d|dk	r|jt   X |
S )	zV
    Read in data.

    The arguments passed to this method depend on the format.
    Nr   )get_readable_fileobjr   binary)encodingru   r
   z,could not convert reader output to {} class.)lenrQ   
PATH_TYPESosrm   isdirZastropy.utils.datarv   PathLikefspath	__enter__OSError	Exceptionr3   hasattr_get_valid_formatr   	TypeErrorrb   r   __exit__sysexc_info)r   rb   ru   ro   rp   ctxrm   rn   rv   readerr=   r   r   r   r
     sF    




)rb   c            O   s   |dkrd}d}t |rzt|d tr`t|d tjrRt|d f|dd  }|d }d}nt|d drzd}|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   )
ry   rQ   rz   r{   r}   r~   r   r   r\   r	   )r=   rb   ro   rp   rm   rn   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#   rt   r   r   r   r   	<setcomp>H  s    z!_is_best_match.<locals>.<setcomp>TF)
issubclass__mro__)Zclass1Zclass2r:   classesparentr   r   r   r/   =  s    

r/   c             C   s\   t | |||||}t|dkr<t||  }td|nt|dkrTt| ||S |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   zFormat could not be identified based on the file name or contents, please provide a 'format' argument.
The available formats are:
{}r   )r   ry   rs   rV   r   rb   _get_highest_priority_format)moder   rm   rn   ro   rp   rq   rr   r   r   r   r   Q  s    
r   c       
   	   C   s   | dkrt }d}n| dkr"t}d}g }tj }xd|D ]\}y|||f \}}	W n tk
rh   tj }	Y nX |	|kr~|| q4|	|kr4|g}|	}q4W t|dkrtdd	t
|tdd	|d S )
z\
    Returns the reader or writer with the highest priority. If it is a tie,
    error.
    r
   r   r   r   r   z%Format is ambiguous - options are: {}z, r   )r   )r-   r.   r5   infKeyErrorr1   ry   r   rb   r[   r+   r   )
r   r   rq   Zformat_dictZmode_loaderZbest_formatsZcurrent_priorityrb   _rf   r   r   r   r   f  s,    
r   c               @   s,   e Zd ZdZdd Zd	ddZd
ddZdS )r   a  Base class for the worker object used in unified read() or write() methods.

    This lightweight object is created for each `read()` or `write()` call
    via ``read`` / ``write`` descriptors on the data object class.  The key
    driver is to allow complete format-specific documentation of available
    method options via a ``help()`` method, e.g. ``Table.read.help('fits')``.

    Subclasses must define a ``__call__`` method which is what actually gets
    called when the data object ``read()`` or ``write()`` method is called.

    For the canonical example see the `~astropy.table.Table` class
    implementation (in particular the ``connect.py`` module there).

    Parameters
    ----------
    instance : object
        Descriptor calling instance or None if no instance
    cls : type
        Descriptor calling class (either owner class or instance class)
    method_name : str
        Method name, either 'read' or 'write'
    c             C   s   || _ || _|| _d S )N)Z	_instance_cls_method_name)selfinstancer   method_namer   r   r   __init__  s    zUnifiedReadWrite.__init__Nc          
   C   s
  | j }| j}|dkrtnt}y|r,|||}W n. tk
r\ } zdt| }W dd}~X Y nX |rzd|j||}	|j}
n|j d| d}	t	||j}
t
dd|	}||	7 }|t
dd|	7 }|tj7 }|
dk	r|t|
7 }|dkrddl}|| n
|| dS )	a  Output help documentation for the specified unified I/O ``format``.

        By default the help output is printed to the console via ``pydoc.pager``.
        Instead one can supplied a file handle object as ``out`` and the output
        will be written to that handle.

        Parameters
        ----------
        format : str
            Unified I/O format name, e.g. 'fits' or 'ascii.ecsv'
        out : None or path-like
            Output destination (default is stdout via a pager)
        r
   zERROR: Nz!{}.{}(format='{}') documentation
.z general documentation
rM   r   )r   r   r   r	   r   rR   rb   r   r   rP   rB   rX   r{   linesepinspectcleandocpydocpagerr   )r   rb   outr   r   Zget_funcZread_write_funcerrZ
reader_docheaderdocr   r   r   r   help  s0    
zUnifiedReadWrite.helpc             C   sN   t | j| j }|d= |dkr0|jddd n|d|jddd |S )zPrint a list of available formats to console (or ``out`` filehandle)

        out : None or file handle object
            Output destination (default is stdout via a pager)
        z
Data classNrH   )rJ   rK   rO   )r   r   r   rV   pprintr   r[   rW   )r   r   tblr   r   r   list_formats  s    zUnifiedReadWrite.list_formats)NN)N)r   r   r   r   r   r   r   r   r   r   r   r     s   
0c               @   s    e Zd ZdZdd Zdd ZdS )r   a  Descriptor class for creating read() and write() methods in unified I/O.

    The canonical example is in the ``Table`` class, where the ``connect.py``
    module creates subclasses of the ``UnifiedReadWrite`` class.  These have
    custom ``__call__`` methods that do the setup work related to calling the
    registry read() or write() functions.  With this, the ``Table`` class
    defines read and write methods as follows::

      read = UnifiedReadWriteMethod(TableRead)
      write = UnifiedReadWriteMethod(TableWrite)

    Parameters
    ----------
    func : `~astropy.io.registry.UnifiedReadWrite` subclass
        Class that defines read or write functionality

    c             C   s
   || _ d S )N)func)r   r   r   r   r   r     s    zUnifiedReadWriteMethod.__init__c             C   s   |  ||S )N)r   )r   r   Z	owner_clsr   r   r   __get__  s    zUnifiedReadWriteMethod.__get__N)r   r   r   r   r   r   r   r   r   r   r     s   )NN)Fr   )Fr   )F),
contextlibrB   r   r   r{   collectionsr   operatorr   numpyr5   __all__Z__doctest_skip__r-   r.   r0   rR   r}   rz   r   r   r,   r   contextmanagerr   r   r   r   rh   r   ri   r   rk   r   rs   r   r	   r
   r   r/   r   r   r   r   r   r   r   r   <module>   sL   

	$
D>
!
!
5&7#]