B
    }d                 @   s   d Z ddlZddlZddlZddlmZ ddlmZ dZddl	m
Z
 e
ejejfZdZdd	 Zd
d ZdddZdd Zdd ZdS )z#Utilities for unified input/output
    N)wraps)urlparsez(Duncan Macleod <duncan.macleod@ligo.org>)IOBases   c                 s    fdd}|S )a  Factory function to create I/O identifiers for a set of extensions

    The returned function is designed for use in the unified I/O registry
    via the `astropy.io.registry.register_identifier` hool.

    Parameters
    ----------
    extensions : `str`
        one or more file extension strings

    Returns
    -------
    identifier : `callable`
        an identifier function that tests whether an incoming file path
        carries any of the given file extensions (using `str.endswith`)
    c                s   t |to| S )z<Identify the given extensions in a file object/path
        )
isinstancestrendswith)originfilepathfileobjargskwargs)
extensions Z/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/gwpy/io/utils.pyidentify9   s    
z"identify_factory.<locals>.identifyr   )r   r   r   )r   r   identify_factory(   s    r   c             O   sj   t | dr tj| f||S t| f||}|d}|d |tkrf|  tj| f||S |S )aR  Open a file handling optional gzipping

    If ``name`` ends with ``'.gz'``, or if the GZIP file signature is
    found at the beginning of the file, the file will be opened with
    `gzip.open`, otherwise a regular file will be returned from `open`.

    Parameters
    ----------
    name : `str`, `pathlib.Path`
        path or name of file to open.

    *args, **kwargs
        other arguments to pass to either `open` for regular files, or
        `gzip.open` for gzipped files.

    Returns
    -------
    file : `io.TextIoBase`, `file`, `gzip.GzipFile`
        the open file object
    z.gz   r   )r   r   gzipopenreadseekGZIP_SIGNATUREclose)namer   r   fobjsigr   r   r   gopenD   s    

r   rc                s    fdd}| r|| S |S )a  Decorate a function to ensure the chosen argument is an open file

    Parameters
    ----------
    func : `callable`
        the function to decorate

    mode : `str`, optional
        the mode with which to open files

    pos : `int`, optional
        which argument to look at

    Examples
    --------
    To ensure that the first argument is an open read-only file, just use
    the decorator without functional parentheses or arguments:

    >>> @with_open
    >>> def my_func(pathorfile, *args, **kwargs)
    >>>     ...

    To ensure that the second argument (position 1) is a file open for writing:

    >>> @with_open(mode="w", pos=1)
    >>> def my_func(stuff, pathorfile, *args, **kwargs)
    >>>     stuff.write_to(pathorfile, *args, **kwargs)
    c                s   t   fdd}|S )Nc           	      sJ   t |  ts@t|  d}t| } || <  | |S Q R X  | |S )N)mode)r   	FILE_LIKEr   list)r   r   r   )funcr   posr   r   wrapped_func   s    z3with_open.<locals>._decorator.<locals>.wrapped_func)r   )r!   r#   )r   r"   )r!   r   
_decorator   s    zwith_open.<locals>._decoratorr   )r!   r   r"   r$   r   )r   r"   r   	with_openg   s    r%   c          
   C   s   t | tr(| dr(ddlm} || S t | tr<| dS t | ttfrXttt	| S y
t	| gS  t
k
r } zd| df|_ W dd}~X Y nX dS )a  Parse a number of possible input types into a list of filepaths.

    Parameters
    ----------
    flist : `file-like` or `list-like` iterable
        the input data container, normally just a single file path, or a list
        of paths, but can generally be any of the following

        - `str` representing a single file path (or comma-separated collection)
        - open `file` or `~gzip.GzipFile` object
        - :class:`~lal.utils.CacheEntry`
        - `str` with ``.cache`` or ``.lcf`` extension
        - simple `list` or `tuple` of `str` paths

    Returns
    -------
    files : `list`
        `list` of `str` file paths

    Raises
    ------
    ValueError
        if the input `flist` cannot be interpreted as any of the above inputs
    )z.cachez.lcfz.ffl   )
read_cache,zCould not parse input z! as one or more file-like objectsN)r   r   r   cacher'   splitr    tuplemap	file_path
ValueErrorr   )flistr'   excr   r   r   	file_list   s    




r1   c             C   s~   t | tr| drt| jS t | ttjfr6t| S t | trPt| drP| j	S y| jS  t
k
rx   td| Y nX dS )a  Determine the path of a file.

    This doesn't do any sanity checking to check that the file
    actually exists, or is readable.

    Parameters
    ----------
    fobj : `file`, `str`, `CacheEntry`, ...
        the file object or path to parse

    Returns
    -------
    path : `str`
        the path of the underlying file

    Raises
    ------
    ValueError
        if a file path cannnot be determined

    Examples
    --------
    >>> from gwpy.io.utils import file_path
    >>> import pathlib
    >>> file_path("test.txt")
    'test.txt'
    >>> file_path(pathlib.Path('dir') / 'test.txt')
    'dir/test.txt'
    >>> file_path(open("test.txt", "r"))
    'test.txt'
    >>> file_path("file:///home/user/test.txt")
    '/home/user/test.txt'
    zfile:r   zCannot parse file name for N)r   r   
startswithr   pathosPathLiker   hasattrr   AttributeErrorr.   )r   r   r   r   r-      s    "
r-   )Nr   r   )__doc__r   r4   tempfile	functoolsr   urllib.parser   
__author__ior   GzipFile_TemporaryFileWrapperr   r   r   r   r%   r1   r-   r   r   r   r   <module>   s   #
34