o
    oĎi%                     @   s   d dl m Z m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
 d dlmZmZmZmZmZ d dlZd dlZd dlZd dlmZmZ d dlmZ ddlmZ ed	G d
d deZeje_edG dd deZeje_dS )    )datetimetimezoneN)Path)IterableOptionalTupleUnionCallable)Clientregister_client_class)FileCacheMode   )HttpPathhttpc                       s  e Zd Zddejddddfdeeeef  deeee	j
f  dee deejj deeegee f  deeegef  d	ee f fd
dZdedefddZdedee fddZdedeee	j
f defddZdedefddZd3dedededefddZd3dededdfddZded edeeeef  fd!d"Zdeee	j
f dedefd#d$Zdedefd%d&Zd4ded(edefd)d*Z d+ed,edeeeef  fd-d.Z!d/ed0edee"j#j$e%f fd1d2Z  Z&S )5
HttpClientNPUTfile_cache_modelocal_cache_dircontent_type_methodauthcustom_list_page_parsercustom_dir_matcherwrite_file_http_methodc                    sd   t  ||| || _| jdu rtj | _ntj| j| _|| _|dur(|ndd | _|| _	dS )a  Class constructor. Creates an HTTP client that can be used to interact with HTTP servers
            using the cloudpathlib library.

        Args:
            file_cache_mode (Optional[Union[str, FileCacheMode]]): How often to clear the file cache; see
                [the caching docs](https://cloudpathlib.drivendata.org/stable/caching/) for more information
                about the options in cloudpathlib.eums.FileCacheMode.
            local_cache_dir (Optional[Union[str, os.PathLike]]): Path to directory to use as cache
                for downloaded files. If None, will use a temporary directory. Default can be set with
                the `CLOUDPATHLIB_LOCAL_CACHE_DIR` environment variable.
            content_type_method (Optional[Callable]): Function to call to guess media type (mimetype) when
                uploading files. Defaults to `mimetypes.guess_type`.
            auth (Optional[urllib.request.BaseHandler]): Authentication handler to use for the client. Defaults to None, which will use the default handler.
            custom_list_page_parser (Optional[Callable[[str], Iterable[str]]]): Function to call to parse pages that list directories. Defaults to looking for `<a>` tags with `href`.
            custom_dir_matcher (Optional[Callable[[str], bool]]): Function to call to identify a url that is a directory. Defaults to a lambda that checks if the path ends with a `/`.
            write_file_http_method (Optional[str]): HTTP method to use when writing files. Defaults to "PUT", but some servers may want "POST".
        Nc                 S   s
   |  dS )N/)endswith)x r   X/home/jeff/fluffinator/venv/lib/python3.10/site-packages/cloudpathlib/http/httpclient.py<lambda><   s   
 z%HttpClient.__init__.<locals>.<lambda>)
super__init__r   urllibrequestbuild_openeropenerr   dir_matcherr   )selfr   r   r   r   r   r   r   	__class__r   r   r       s   

zHttpClient.__init__
cloud_pathreturnc                 C   s   | j | 2}|jdd }|d ur!t|d}|jtj	d}t
|jdd||jdd dW  d    S 1 s=w   Y  d S )NzLast-Modifiedz%a, %d %b %Y %H:%M:%S %Z)tzinfozContent-Lengthr   Content-Type)sizelast_modifiedcontent_type)r$   openas_urlheadersgetr   strptimereplacer   utcint)r&   r)   responser.   r   r   r   _get_metadataA   s   $zHttpClient._get_metadatac                 C   s   |  | r	dS dS )Ndirfile)r%   r1   r&   r)   r   r   r   _is_file_or_dirR   s   zHttpClient._is_file_or_dir
local_pathc              	   C   s   t |}| j| 4}|jjddd |d}t|| W d    n1 s+w   Y  W d    |S W d    |S 1 sCw   Y  |S )NT)parentsexist_okwb)r   r$   r0   r1   parentmkdirshutilcopyfileobj)r&   r)   r>   r8   out_filer   r   r   _download_fileX   s   

zHttpClient._download_filec              
   C   s   t jj| dd}z| j|}|jdkW  d    W S 1 s"w   Y  W d S  t jjt jj	fyO } zt
|t jj	sC|jdkrJW Y d }~dS  d }~ww )NHEADmethod     F)r!   r"   Requestr1   r$   r0   statuserror	HTTPErrorURLError
isinstancecode)r&   r)   r"   r8   er   r   r   _existsa   s   (zHttpClient._existsTsrcdst
remove_srcc                 C   s`   |  |j| |r.z| | W |S  ty- } ztd| d| d| t  d }~ww |S )Nz"File was successfully uploaded to z but failed to remove original z: )_upload_filefspath_remove	ExceptionwarningswarnUserWarning)r&   rV   rW   rX   rT   r   r   r   
_move_filek   s   zHttpClient._move_file
missing_okc              
   C   s   t jj| dd}z(| j|}|jdkrtd| dW d    W d S 1 s+w   Y  W d S  t jj	yW } z|j
dkrD|rDntd| dW Y d }~d S d }~ww )NDELETErI      zFailed to delete .rL   )r!   r"   rM   r1   r$   r0   rN   r\   rO   rP   rS   FileNotFoundError)r&   r)   ra   r"   r8   rT   r   r   r   r[   y   s   
&zHttpClient._remove	recursivec              
   c   s    zB| j | /}| j|  t|dD ]\}}||fV  |r/|r/| j|ddE d H  qW d    W d S 1 s<w   Y  W d S  tyV } zt	d| d }~ww )N)base_urlT)rf   z{Unable to parse response as a listing of files; please provide a custom parser as `custom_list_page_parser`. Error raised: )
r$   r0   r1   _parse_list_dir_responsereaddecodestr	_list_dirr\   NotImplementedError)r&   r)   rf   r8   pathis_dirrT   r   r   r   rl      s$   
&zHttpClient._list_dirc           	   	   C   s   t |}| jd ur| |\}}d|pdi}|dK}tjj| | | j|d}| j	|}|j
dkrG|j
dkrGtd| d| d	W d    n1 sQw   Y  W d    |S W d    |S 1 siw   Y  |S )
Nr,   zapplication/octet-streamrb)datarJ   r2      rK   zFailed to upload z to rd   )r   r   r0   r!   r"   rM   r1   ri   r   r$   rN   r\   )	r&   r>   r)   r/   _r2   	file_datar"   r8   r   r   r   rY      s.   





zHttpClient._upload_filec                 C   s   |  S N)r1   r<   r   r   r   _get_public_url      zHttpClient._get_public_url  expire_secondsc                 C   s   t d)Nz.Presigned URLs are not supported using urllib.)rm   )r&   r)   ry   r   r   r   _generate_presigned_url   rw   z"HttpClient._generate_presigned_urlr8   rg   c                 #   s`      ds
 d7  dtdtt fdd}jd urjn|} fdd||D E d H  d S )Nr   htmlr*   c                 S   s   t d| S )Nz<a\s+href="([^"]+)")refindall)r{   r   r   r   _simple_links   s   z:HttpClient._parse_list_dir_response.<locals>._simple_linksc                 3   s.    | ]} tj ||fV  qd S ru   )	CloudPathr!   parseurljoinr%   ).0matchrg   r&   r   r   	<genexpr>   s
    
z6HttpClient._parse_list_dir_response.<locals>.<genexpr>)r   rk   r   r   )r&   r8   rg   r~   parserr   r   r   rh      s   

z#HttpClient._parse_list_dir_responseurlrJ   c                 K   sX   t jj| fd|i|}| j|}|| fW  d    S 1 s%w   Y  d S )NrJ   )r!   r"   rM   r1   r$   r0   ri   )r&   r   rJ   kwargsr"   r8   r   r   r   r"      s   
$zHttpClient.request)T)rx   )'__name__
__module____qualname__	mimetypes
guess_typer   r   rk   r   osPathLiker	   r!   r"   BaseHandlerr   boolr    r   dictr9   r=   r   rG   rU   r`   r[   r   rl   rY   rv   r7   rz   rh   r   clientHTTPResponsebytes__classcell__r   r   r'   r   r      s^    
+ 	
" 
r   httpsc                   @   s   e Zd ZdS )HttpsClientN)r   r   r   r   r   r   r   r      s    r   )r   r   r   r   r|   urllib.requestr!   urllib.parseurllib.errorpathlibr   typingr   r   r   r   r	   rD   r   r]   cloudpathlib.clientr
   r   cloudpathlib.enumsr   httppathr   r   r   r   	HttpsPathr   r   r   r   <module>   s,     ;