U
    (dC                  	   @   s  U d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
Z
d dlZ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mZmZmZmZmZmZmZmZmZ d dlmZ d dlZd dlZd dl m!Z! ddl"m#Z#m$Z$ dZ%dUee& e'ee( ddd	d
Z)dVe'e'e(ddddZ*ee(e(e(gdf dddZ+dWe'e(e'dddZ,e'e'ee-dddZ.dXe'ee' e-dddZ/dYe'e(e'dddZ0e'ee' d d!d"Z1dZe'e'ee' ee' e(dd#d$d%Z2d[e'e-ee' d'd(d)Z3d\e'e'e-ee' d*d+d,Z4d]e(ee&ee& f d-d.d/Z5d^e'e'ee' ee' d0d1d2Z6e'e'ee' dd3d4d5Z7ej8ej9d6Z:ee'e(f e;d7< e'e'ee' dd3d8d9Z<e7e<d:Z=ee'ee'e'ee' gdf f e;d;< e j>ej>ej>d<Z?ee'ed=ef f e;d>< d?d?d@dAZ@ee'eee' ee' f f e;dB< e'ee'ee' ee' f dCdDdEZAd_e'ee' e-e'dFdGdHZBd`e'ee' e-e'dFdIdJZCdae'e'ee' ee' ee' e-ddKdLdMZDee'dNdOdPZEedQe'e&ZFdbeFee' eeF ee' eFdRdSdTZGdS )c    N)
AnyCallableListIterableOptionalTypeVarDictIOTupleIterator)urlparse)tqdm   )#_download_file_from_remote_location_is_remote_location_availablezpytorch/vision)contentdestinationlengthreturnc              
   C   sX   t |dD}t|d.}| D ]"}|s&q|| |t| qW 5 Q R X W 5 Q R X d S )Nwbtotal)openr   writeupdatelen)r   r   r   fhpbarchunk r   >/tmp/pip-unpacked-wheel-vx7f76es/torchvision/datasets/utils.py_save_response_content!   s    
r!      )urlfilename
chunk_sizer   c              	      sL   t jt jj| dtid&tt fddd|jd W 5 Q R X d S )N
User-Agentheadersc                      s
     S Nreadr   r%   responser   r    <lambda>2       z_urlretrieve.<locals>.<lambda>r/   )r   )urllibrequesturlopenRequest
USER_AGENTr!   iterr   )r#   r$   r%   r   r,   r    _urlretrieve0   s    r6   )r   c                     s$   t d td d  fdd} | S )NzSThe function `gen_bar_update` is deprecated since 0.13 and will be removed in 0.15.r   c                    s0    j d kr|r| _ | | } | j  d S r)   )r   r   n)count
block_sizeZ
total_sizeZprogress_bytesr   r   r    
bar_update9   s    z#gen_bar_updater.<locals>.bar_update)warningswarnr   )r;   r   r:   r    gen_bar_updater5   s    

r>      )fpathr%   r   c              	      sd   t jf tjdkrtddnt }t| d*t fdddD ]}|| qBW 5 Q R X | S )N)   	   F)Zusedforsecurityrbc                      s
     S r)   r*   r   r%   fr   r    r.   H   r/   zcalculate_md5.<locals>.<lambda>r/   )	hashlibmd5sysversion_infodictr   r5   r   	hexdigest)r@   r%   rG   r   r   rD   r    calculate_md5B   s
    "rL   )r@   rG   kwargsr   c                 K   s   |t | f|kS r)   )rL   )r@   rG   rM   r   r   r    	check_md5M   s    rN   )r@   rG   r   c                 C   s&   t j| sdS |d krdS t| |S )NFT)ospathisfilerN   )r@   rG   r   r   r    check_integrityQ   s
    rR   rA   )r#   max_hopsr   c                 C   s   | }dt d}t|d D ]V}tjtjj| |d4}|j| ksL|jd kr`| W  5 Q R    S |j} W 5 Q R X qtd| d| d|  dd S )	NHEAD)ZMethodr&      r'   zRequest to z
 exceeded z( redirects. The last redirect points to .)r4   ranger0   r1   r2   r3   r#   RecursionError)r#   rS   Zinitial_urlr(   _r-   r   r   r    _get_redirect_urlY   s    
rZ   )r#   r   c                 C   sB   t | }td|jd krd S td|j}|d kr8d S |dS )Nz(drive|docs)[.]google[.]comz/file/d/(?P<id>[^/]*)id)r   rematchnetlocrP   group)r#   partsr]   r   r   r    _get_google_drive_file_idi   s    ra   )r#   rootr$   rG   max_redirect_hopsr   c              
   C   s8  t j|}|st j| }t j||}t j|dd t||rRtd|  dS t rdt	||  nt
| |d} t| }|dk	rt||||S z"td|  d |  t| | W nn tjjtfk
r } zF| dd d	kr
| d
d} td|  d |  t| | n|W 5 d}~X Y nX t||s4tddS )a  Download a file from a url and place it in root.

    Args:
        url (str): URL to download file from
        root (str): Directory to place downloaded file in
        filename (str, optional): Name to save the file under. If None, use the basename of the URL
        md5 (str, optional): MD5 checksum of the download. If None, do not check
        max_redirect_hops (int, optional): Maximum number of redirect hops allowed
    Texist_okz$Using downloaded and verified file: N)rS   zDownloading  to    httpszhttps:zhttp:z;Failed download. Trying https -> http instead. Downloading zFile not found or corrupted.)rO   rP   
expanduserbasenamejoinmakedirsrR   printr   r   rZ   ra   download_file_from_google_driver6   r0   errorURLErrorOSErrorreplaceRuntimeError)r#   rb   r$   rG   rc   r@   file_ider   r   r    download_urlv   s2    
rv   F)rb   prefixr   c                    sB   t j   fddt  D }|dkr> fdd|D }|S )a  List all directories at a given root

    Args:
        root (str): Path to directory whose folders need to be listed
        prefix (bool, optional): If true, prepends the path to each result, otherwise
            only returns the name of the directories found
    c                    s&   g | ]}t jt j |r|qS r   )rO   rP   isdirrk   .0prb   r   r    
<listcomp>   s      zlist_dir.<locals>.<listcomp>Tc                    s   g | ]}t j |qS r   rO   rP   rk   rz   dr|   r   r    r}      s     rO   rP   ri   listdir)rb   rw   directoriesr   r|   r    list_dir   s
    r   )rb   suffixrw   r   c                    sD   t j   fddt  D }|dkr@ fdd|D }|S )a  List all files ending with a suffix at a given root

    Args:
        root (str): Path to directory whose folders need to be listed
        suffix (str or tuple): Suffix of the files to match, e.g. '.png' or ('.jpg', '.png').
            It uses the Python "str.endswith" method and is passed directly
        prefix (bool, optional): If true, prepends the path to each result, otherwise
            only returns the name of the files found
    c                    s0   g | ](}t jt j |r|r|qS r   )rO   rP   rQ   rk   endswithry   rb   r   r   r    r}      s      
 zlist_files.<locals>.<listcomp>Tc                    s   g | ]}t j |qS r   r~   r   r|   r   r    r}      s     r   )rb   r   rw   filesr   r   r    
list_files   s
    
r   )r%   r   c                 C   st   |  |}d }|st|}qt|g|}z(td| }|d k	rL|d nd }W n tk
rj   d }Y nX ||fS )Nz3<title>Google Drive - (?P<api_response>.+?)</title>api_response)iter_contentnext	itertoolschainr\   searchdecodeUnicodeDecodeError)r-   r%   r   Zfirst_chunkr]   r   r   r   r    _extract_gdrive_api_response   s    


r   )rt   rb   r$   rG   c              
   C   s  t j|}|s| }t j||}t j|dd t||rZtd|rFdnd d|  dS d}t| d	d
}t	 }|j
||dd}|j D ]\}	}
|	dr|
} qqt|\}}|dkrdnd}|dk	r|j
|t||ddd}t|\}}|dkrtd| dt|| W 5 Q R X t |jdk rtt@ t|,}| }td|rntd|  W 5 Q R X W 5 Q R X |rt||std| ddS )af  Download a Google Drive file from  and place it in root.

    Args:
        file_id (str): id of file to be downloaded
        root (str): Directory to place downloaded file in
        filename (str, optional): Name to save the file under. If None, use the id of the file.
        md5 (str, optional): MD5 checksum of the download. If None, do not check
    Trd   zUsing downloaded zand verified  zfile: Nzhttps://drive.google.com/ucdownload)r[   export)paramsstreamZdownload_warningzVirus scan warningt)ZconfirmzQuota exceededzThe daily quota of the file z} is exceeded and it can't be downloaded. This is a limitation of Google Drive and can only be overcome by trying again later.i (  z5</?\s*[a-z-][^>]*\s*>|(&(?:[\w\d]+|#\d+|#x[a-f\d]+);)zWe detected some HTML elements in the downloaded file. This most likely means that the download triggered an unhandled API response by GDrive. Please report this to torchvision at https://github.com/pytorch/vision/issues including the response:

z&The MD5 checksum of the download file z does not match the one on record.Please delete the file and try again. If the issue persists, please report this to torchvision at https://github.com/pytorch/vision/issues.)rO   rP   ri   rk   rl   rR   rm   rJ   requestsSessiongetcookiesitems
startswithr   rs   r!   statst_size
contextlibsuppressr   r   r+   r\   r   r<   r=   rN   )rt   rb   r$   rG   r@   r#   r   sessionr-   keyvaluetokenr   r   r   textr   r   r    rn      sJ    





rn   )	from_pathto_pathcompressionr   c              	   C   s<   t | |rd|dd   nd}|| W 5 Q R X d S )Nzr:rU   r)tarfiler   
extractall)r   r   r   tarr   r   r    _extract_tar  s    $r   ).bz2.xz_ZIP_COMPRESSION_MAPc              	   C   s8   t j| d|rt| nt jd}|| W 5 Q R X d S )Nr   )r   )zipfileZipFiler   
ZIP_STOREDr   )r   r   r   zipr   r   r    _extract_zip*  s      r   ).tarz.zip_ARCHIVE_EXTRACTORS)r   .gzr   ._COMPRESSED_FILE_OPENERS)r   r   )r   r   )z.tbzz.tbz2z.tgz_FILE_TYPE_ALIASES)filer   c                 C   s   t | j}|s td|  d|d }|tkr>|ft| S |tkrP||dfS |tkrt|dkr|d }|tkr|| ||fS |d|fS tt	tt	tB t	tB }td| d| d	dS )
a  Detect the archive type and/or compression of a file.

    Args:
        file (str): the filename

    Returns:
        (tuple): tuple of suffix, archive type, and compression

    Raises:
        RuntimeError: if file has no suffix or suffix is not supported
    zFile 'zP' has no suffixes that could be used to detect the archive type and compression.NrU   z&Unknown compression or archive type: 'z'.
Known suffixes are: 'z'.)
pathlibPathsuffixesrs   r   r   r   r   sortedset)r   r   r   Zsuffix2Zvalid_suffixesr   r   r    _detect_file_typeA  s$    


r   )r   r   remove_finishedr   c           	   
   C   s   t | \}}}|s"td| d|dkrB| ||dk	r<|nd}t| }|| d*}t|d}||  W 5 Q R X W 5 Q R X |rt|  |S )a  Decompress a file.

    The compression is automatically detected from the file name.

    Args:
        from_path (str): Path to the file to be decompressed.
        to_path (str): Path to the decompressed file. If omitted, ``from_path`` without compression extension is used.
        remove_finished (bool): If ``True``, remove the file after the extraction.

    Returns:
        (str): Path to the decompressed file.
    z*Couldn't detect a compression from suffix rV   Nr   rC   r   )	r   rs   rr   r   r   r   r+   rO   remove)	r   r   r   r   archive_typer   Zcompressed_file_openerZrfhZwfhr   r   r    _decompressl  s    "
r   c              	   C   st   |dkrt j| }t| \}}}|sNt| t j|t j| |d|dS t| }|| || |rpt 	|  |S )aD  Extract an archive.

    The archive type and a possible compression is automatically detected from the file name. If the file is compressed
    but not an archive the call is dispatched to :func:`decompress`.

    Args:
        from_path (str): Path to the file to be extracted.
        to_path (str): Path to the directory the file will be extracted to. If omitted, the directory of the file is
            used.
        remove_finished (bool): If ``True``, remove the file after the extraction.

    Returns:
        (str): Path to the directory the file was extracted to.
    Nr   )r   )
rO   rP   dirnamer   r   rk   rj   rr   r   r   )r   r   r   r   r   r   Z	extractorr   r   r    extract_archive  s    
r   )r#   download_rootextract_rootr$   rG   r   r   c                 C   sh   t j|}|d kr|}|s(t j| }t| ||| t j||}td| d|  t||| d S )NzExtracting rf   )rO   rP   ri   rj   rv   rk   rm   r   )r#   r   r   r$   rG   r   archiver   r   r    download_and_extract_archive  s    r   )iterabler   c                 C   s   dd dd | D  d S )N'z', 'c                 S   s   g | ]}t |qS r   )str)rz   itemr   r   r    r}     s     z#iterable_to_str.<locals>.<listcomp>)rk   )r   r   r   r    iterable_to_str  s    r   T)r   argvalid_values
custom_msgr   c                 C   s   t | tjjs:|d krd}nd}|jt| |d}t||d krF| S | |kr||d k	r\|}nd}|j| |t|d}t|| S )Nz'Expected type str, but got type {type}.z:Expected type str for argument {arg}, but got type {type}.)typer   zPUnknown value '{value}' for argument {arg}. Valid values are {{{valid_values}}}.)r   r   r   )
isinstancetorchZ_sixZstring_classesformatr   
ValueErrorr   )r   r   r   r   msgr   r   r    verify_str_arg  s    r   )N)r"   )r?   )N)rA   )NNrA   )F)F)r"   )NN)NF)NF)NNNF)NNN)Hbz2r   gziprF   r   lzmarO   os.pathr   r\   rH   r   r0   urllib.errorurllib.requestr<   r   typingr   r   r   r   r   r   r   r	   r
   r   urllib.parser   r   r   Ztorch.utils.model_zoor   Z_internally_replaced_utilsr   r   r4   bytesr   intr!   r6   r>   rL   boolrN   rR   rZ   ra   rv   r   r   r   rn   r   	ZIP_BZIP2ZIP_LZMAr   __annotations__r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    <module>   s    0          4E(&"+ '       