B
    T\                 @   s   d dl mZmZmZ d dlZd dlZd dlZd dlmZ ddl	m
Z
mZ dddZddd	Ze
rrG d
d deZneZddddZdd Zdd ZdddZdd ZdS )    )print_functiondivisionabsolute_importN)identity   )PY2urlsplitc             C   s  t d| rd| dS t| }|jp&d}|j}|dkrRt d|}|rRd|  }|dkrd|| dS ||d}|jr|jddd	 d
dd }|dkr||d  |d< n||d< |jr|j|d< |j	r|j	|d< |j
r|j
|d< |jr|j|d< |jr|j|d< |rt|| |S )a   Infer storage options from URL path and merge it with existing storage
    options.

    Parameters
    ----------
    urlpath: str or unicode
        Either local absolute file path or URL (hdfs://namenode:8020/file.csv)
    storage_options: dict (optional)
        Its contents will get merged with the inferred information from the
        given path

    Returns
    -------
    Storage options dict.

    Examples
    --------
    >>> infer_storage_options('/mnt/datasets/test.csv')  # doctest: +SKIP
    {"protocol": "file", "path", "/mnt/datasets/test.csv"}
    >>> infer_storage_options(
    ...          'hdfs://username:pwd@node:123/mnt/datasets/test.csv?q=1',
    ...          inherit_storage_options={'extra': 'value'})  # doctest: +SKIP
    {"protocol": "hdfs", "username": "username", "password": "pwd",
    "host": "node", "port": 123, "path": "/mnt/datasets/test.csv",
    "url_query": "q=1", "extra": "value"}
    z^[a-zA-Z]:[\\/]file)protocolpathz^/([a-zA-Z])[:|]([\\/].*)$z%s:%s)ZhttpZhttps@   :r   )Zs3ZgcsZgsr   hostportusernamepasswordZ	url_queryZurl_fragment)rematchr   Zschemer   groupsZnetlocrsplitr   r   r   ZqueryZfragmentupdate_storage_options)ZurlpathZinherit_storage_optionsZparsed_pathr
   r   Zwindows_pathoptionsr    r   /lib/python3.7/site-packages/dask/bytes/utils.pyinfer_storage_options   s@    







r   c             C   sJ   |si }t | t |@ }|r<ddd |D }td| | | d S )N
c             s   s   | ]}d | V  qdS )z- %rNr   ).0kr   r   r   	<genexpr>e   s    z)update_storage_options.<locals>.<genexpr>z<Collision between inferred and specified storage options:
%s)setjoinKeyErrorupdate)r   Z	inheritedZ
collisionsr   r   r   r   `   s    r   c               @   sD   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dS )SeekableFilec             C   s   t |tr|j}|| _d S )N)
isinstancer%   r	   )selfr	   r   r   r   __init__m   s    
zSeekableFile.__init__c             C   s   dS )NTr   )r'   r   r   r   seekabler   s    zSeekableFile.seekablec             C   s,   y
| j  S  tk
r&   d| j jkS X d S )Nr)r	   readableAttributeErrormode)r'   r   r   r   r+   u   s    
zSeekableFile.readablec             C   s,   y
| j  S  tk
r&   d| j jkS X d S )Nw)r	   writabler,   r-   )r'   r   r   r   r/   {   s    
zSeekableFile.writablec             O   s   | j j||S )N)r	   read)r'   argskwargsr   r   r   read1   s    zSeekableFile.read1c             C   s
   | j  S )N)r	   __iter__)r'   r   r   r   r4      s    zSeekableFile.__iter__c             C   s   t | j|S )N)getattrr	   )r'   keyr   r   r   __getattr__   s    zSeekableFile.__getattr__N)
__name__
__module____qualname__r(   r)   r+   r/   r3   r4   r7   r   r   r   r   r%   l   s   r%   Zgzipbz2xz)Zgzr;   r<   c             C   s"   t j| d d}t|d S )Nr   .)osr   splitextstripcompressionsget)filename	extensionr   r   r   infer_compression   s    rE   c          	   C   s   |   dkrdS d}xz| |}|s(dS || }y0||}| |   t||  t|  dS  ttfk
rx   Y nX |t| d }qW dS )a   Seek current file to next byte after a delimiter bytestring

    This seeks the file to the next byte following the delimiter.  It does
    not return anything.  Use ``file.tell()`` to see location afterwards.

    Parameters
    ----------
    file: a file
    delimiter: bytes
        a delimiter like ``b'
'`` or message sentinel
    blocksize: int
        Number of bytes to read from the file at once.
    r   N    )tellr0   indexseeklenOSError
ValueError)r	   	delimiterZ	blocksizeZlastZcurrentZfullir   r   r   seek_delimiter   s    

"rO   c          	   C   s   ||   kr| | |s6|dkr6|   dkr6|  S |rt| |d |   }||| 8 }y| ||  t| |d W n$ ttfk
r   | dd Y nX |   }|}|| }| | | |S )a   Read a block of bytes from a file

    Parameters
    ----------
    f: File
    offset: int
        Byte offset to start read
    length: int
        Number of bytes to read
    delimiter: bytes (optional)
        Ensure reading starts and stops at delimiter bytestring

    If using the ``delimiter=`` keyword argument we ensure that the read
    starts and stops at delimiter boundaries that follow the locations
    ``offset`` and ``offset + length``.  If ``offset`` is zero then we
    start at zero.  The bytestring returned WILL include the
    terminating delimiter string.

    Examples
    --------

    >>> from io import BytesIO  # doctest: +SKIP
    >>> f = BytesIO(b'Alice, 100\nBob, 200\nCharlie, 300')  # doctest: +SKIP
    >>> read_block(f, 0, 13)  # doctest: +SKIP
    b'Alice, 100\nBo'

    >>> read_block(f, 0, 13, delimiter=b'\n')  # doctest: +SKIP
    b'Alice, 100\nBob, 200\n'

    >>> read_block(f, 10, 10, delimiter=b'\n')  # doctest: +SKIP
    b'Bob, 200\nCharlie, 300'
    Nr   i   r   )rG   rI   r0   rO   rK   rL   )foffsetlengthrM   startendr   r   r   
read_block   s$    !

rU   c                s,   | d7 } t tt|   fdd}|S )a   Returns a function that receives a single integer
    and returns it as a string padded by enough zero characters
    to align with maximum possible integer

    >>> name_f = build_name_function(57)

    >>> name_f(7)
    '07'
    >>> name_f(31)
    '31'
    >>> build_name_function(1000)(42)
    '0042'
    >>> build_name_function(999)(42)
    '042'
    >>> build_name_function(0)(0)
    '0'
    g:0yE>c                s   t |  S )N)strzfill)rN   )
pad_lengthr   r   name_function  s    z*build_name_function.<locals>.name_function)intmathZceilZlog10)Zmax_intrY   r   )rX   r   build_name_function   s    r\   )N)N)N)Z
__future__r   r   r   r[   r>   r   Ztoolzr   Zcompatibilityr   r   r   r   objectr%   rA   rE   rO   rU   r\   r   r   r   r   <module>   s   
T
!
;