o
    2wiV                     @   s  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	 d dl
Z
d dlZd dlmZ d dlmZ d dlmZmZ d dlmZmZ G dd deZG d	d
 d
eZG dd deZG dd deZG dd dZG dd dZG dd dZdddefddZdd Zdd Z dS )    N)	urlencode)encode_multipart_formdata)RequestField)
HTTPClientHTTPClientPool)URLto_key_val_listc                       s,   e Zd Zdd Zdd Z fddZ  ZS )ConnectionErrorc                 O   s   || _ | j| |r"t|d tr"|d d t|dd   | _nt|dkr.t|d nd| _|rV|  j| jr;dnd7  _ddd | D | _	|  j| j	7  _d S d| _d S )Nr   :     , c                 s   "    | ]\}}| d | V  qdS )=N .0keyvalr   r   W/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/geventhttpclient/useragent.py	<genexpr>        z+ConnectionError.__init__.<locals>.<genexpr>)
url__dict__update
isinstancestrtextlenjoinitemskw_text)selfr   argskwr   r   r   __init__   s    
zConnectionError.__init__c                 C   s&   | j rd| j d| j  S d| j S )NzURL r
   )r   r   r"   r   r   r   __str__"   s   zConnectionError.__str__c                    s.   t   }| jr|ddd| jdgS |S )N)r   r   )super__repr__r!   replacer   )r"   repr_str	__class__r   r   r*   (   s   
zConnectionError.__repr__)__name__
__module____qualname__r%   r'   r*   __classcell__r   r   r-   r   r	      s    r	   c                   @      e Zd ZdS )RetriesExceededNr/   r0   r1   r   r   r   r   r4   /       r4   c                   @   r3   )BadStatusCodeNr5   r   r   r   r   r7   3   r6   r7   c                   @   r3   )EmptyResponseNr5   r   r   r   r   r8   7   r6   r8   c                   @   s   e Zd ZdZd$ddZedd Zd%dd	Zd
d Zdd Z	dd Z
dd Zdd Zedd Zd%ddZdd Zdd Zdd Zdd Zd d! Zd"d# ZdS )&CompatRequestzqurllib.request.Request compatible request class.
    See also: http://docs.python.org/library/cookielib.html
    GETNc                 C   s2   | j ||d | jj| _| | _|| _|| _d S N)params)set_url	url_splithostoriginal_hostuppermethodheaderspayload)r"   r   rB   rC   rD   r<   r   r   r   r%   D   s
   


zCompatRequest.__init__c                 C      | j S Nr   r&   r   r   r   full_urlK      zCompatRequest.full_urlc                 C   s8   t |trt|| _|| _d S || _t| j|d| _d S r;   )r   r   r   r   r>   )r"   r   r<   r   r   r   r=   P   s
   


zCompatRequest.set_urlc                 C   rE   rF   rG   r&   r   r   r   get_full_urlX      zCompatRequest.get_full_urlc                 C      | j jS rF   )r>   r?   r&   r   r   r   get_host[      zCompatRequest.get_hostc                 C   rL   rF   )r>   schemer&   r   r   r   get_type^   rN   zCompatRequest.get_typec                 C   rE   rF   )r@   r&   r   r   r   get_origin_req_hosta   rK   z!CompatRequest.get_origin_req_hostc                 C      dS )zCSee http://tools.ietf.org/html/rfc2965.html. Not fully implemented!Fr   r&   r   r   r   is_unverifiabled      zCompatRequest.is_unverifiablec                 C   s   |   S rF   )rS   r&   r   r   r   unverifiableh      zCompatRequest.unverifiablec                 C   s   | j ||S rF   )rC   get)r"   header_namedefaultr   r   r   
get_headerl      zCompatRequest.get_headerc                 C   s
   || j v S rF   rC   )r"   rX   r   r   r   
has_headero      
zCompatRequest.has_headerc                 C   s   t | j S rF   )listrC   r    r&   r   r   r   header_itemsr   r[   zCompatRequest.header_itemsc                 C   s   | j || d S rF   )rC   add)r"   r   r   r   r   r   add_unredirected_headeru   s   z%CompatRequest.add_unredirected_headerc                 C   s&   d| _ d | _dD ]}| j| qd S )Nr:   )content-lengthcontent-typecontent-encoding)rB   rD   rC   discardr"   itemr   r   r   _drop_payloadx   s
   zCompatRequest._drop_payloadc                 C   s   dD ]}| j | qd S )N)cookiecookie2)rC   rf   rg   r   r   r   _drop_cookies~   s   zCompatRequest._drop_cookiesc                 C   s.   |  | j| |dv r|   |   dS )z7Modify the request inplace to point to the new location).  /  N)r=   r>   redirectri   rl   )r"   codelocationr   r   r   ro      s   zCompatRequest.redirect)r:   NNNrF   )r/   r0   r1   __doc__r%   propertyrH   r=   rJ   rM   rP   rQ   rS   rU   rZ   r]   r`   rb   ri   rl   ro   r   r   r   r   r9   ;   s(    




r9   c                   @   s   e Zd ZdZdZd.ddZdd Zdd	 Zed
d Z	dd Z
dd Zdd Zdd Zd/ddZdd Zdd Zd0ddZedd Zd d! Zed"d# Zd$d% Zed&d' Zed(d) Zed*d+ Zd,d- ZdS )1CompatResponsez$Adapter for urllib3-style responses.)rC   	_response_request_sent_request_cached_contentNc                 C   s    || _ || _|| _| j j| _d S rF   )ru   rv   rw   _headers_indexrC   )r"   ghc_responserequestsent_requestr   r   r   r%      s   zCompatResponse.__init__c                 C      | S rF   r   r&   r   r   r   	__enter__      zCompatResponse.__enter__c                 G      |    d S rF   )release)r"   r#   r   r   r   __exit__      zCompatResponse.__exit__c                 C   
   | j  S )z!HTTP status code as plain integer)ru   get_coder&   r   r   r   status_code      
zCompatResponse.status_codec                 C   rL   )z0The content lengths as declared from the headers)ru   lengthr&   r   r   r   __len__   rV   zCompatResponse.__len__c                 C   rE   )zAdaption to http.client.r\   r&   r   r   r   info   s   zCompatResponse.infoc                 C   rR   )zKIf we have an empty response body, we still don't want to evaluate as falseTr   r&   r   r   r   __nonzero__   rT   zCompatResponse.__nonzero__c                 C   
   t | jS rF   )iterru   r&   r   r   r   __iter__   r^   zCompatResponse.__iter__c                 C   s   | j |S )z#Read n bytes from the response body)ru   read)r"   nr   r   r   r      s   zCompatResponse.readc                 C   r   rF   )ru   readliner&   r   r   r   r      r^   zCompatResponse.readlinec                 C   r   rF   )ru   r   r&   r   r   r   r      r^   zCompatResponse.releaseTFc                 C   s`   | j  }|rt|dtj S |rt|S z	t|tj W S  tjy/   t| Y S w )N   )ru   r   zlib
decompress	MAX_WBITSbrotlierror)r"   gzipbrbodystrr   r   r   unzipped   s   

zCompatResponse.unzippedc                 C   s,   z| j W S  ty   |  | _ | j  Y S w )zLUnzips if necessary and buffers the received body. Careful with large files!)rx   AttributeError_contentr&   r   r   r   content   s   

zCompatResponse.contentc                 C   s   z| j dd  }W n ty   d}Y nw |dkr#| jdd}n3|dkr.| jdd}n(|dkr8| j }n|d	krD| jddd
}n|dkrOtd| td| |   |S )Nre   r   identityr   T)r   deflateFr   )r   r   compressz Compression type not supported: zUnknown content encoding: )	rC   
getheaderslower
IndexErrorr   ru   r   
ValueErrorr   )r"   content_encodingretr   r   r   r      s$   zCompatResponse._contentc                 C   s   | j sdS z| jdd  }W n ty   | j   Y S w |drId}d|v rCz|ddd d d	 }W n	 tyB   Y nw | j |S | j S )
Nr   rd   r   r   utf-8charsetzcharset=r   
   )r   rC   r   r   r   decode
startswithsplit)r"   content_typecodecr   r   r   r      s"   
zCompatResponse.textc                 C   s
   t | S rF   )jsonlibloadr&   r   r   r   json   r^   zCompatResponse.jsonc                 C   r   )zHTTP status for urllib3)r   r   r&   r   r   r   status  r   zCompatResponse.statusc                 C   rE   )zContent for urllib3)r   r&   r   r   r   data  rI   zCompatResponse.datac                 C   rE   )zReadable stream for urllib3)ru   r&   r   r   r   stream  rI   zCompatResponse.streamc                 C   rL   )zClosed status for urllib3)ru   message_completer&   r   r   r   isclosed  rV   zCompatResponse.isclosed)NNrF   )TF)r/   r0   r1   rr   	__slots__r%   r~   r   rs   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rt      s:    








rt   c                
   @   s   e Zd ZeZeZeg dZeg dZ						d"ddZ
dd	 Zd
d Zdd Zd#ddZd#ddZd#ddZdeddddddddf
ddZdd Zed$ddZd%ddZd&d d!ZdS )'	UserAgent)      -  rm   rn   3  )r   rm   rn   r      r   Nc                 K   sP   t || _t || _|| _tj | _|r| j| || _	t
di || _d S )Nr   )intmax_redirectsmax_retriesretry_delayr   DEFAULT_HEADERScopydefault_headersr   	cookiejarr   
clientpool)r"   r   r   r   r   rC   r$   r   r   r   r%     s   
	
zUserAgent.__init__c                 C   s   | j   d S rF   )r   closer&   r   r   r   r   -  r[   zUserAgent.closec                 C   r}   rF   r   r&   r   r   r   r~   0  r   zUserAgent.__enter__c                 C   r   rF   )r   )r"   exc_typeexc_valexc_tbr   r   r   r   3  r   zUserAgent.__exit__c                 C   s   || j vrt||ddS )Hook for subclassing)rp   N)valid_response_codesr7   )r"   r   r   r   r   r   _verify_status6  s   
zUserAgent._verify_statusc                 C   s|   t |tjtjfr|S t |tjr |jtjtjtj	tj
hv r |S t |tjr.dt|v r.|S t |tr5|S |t d )zHook for subclassing. Raise the error to interrupt further retrying,
        return it to continue retries and save the error, when retries
        exceed the limit.
        Temporary errors should be swallowed here for automatic retries.
        zread operation timed out   )r   sockettimeoutgeventTimeoutr   errno	ETIMEDOUTENOLINKENOENTEPIPEsslSSLErrorr   r8   with_tracebacksysexc_info)r"   er   r   r   r   _handle_error;  s   
zUserAgent._handle_errorc                 C   s   t || j|d)r   )original)r4   r   )r"   r   
last_errorr   r   r   _handle_retries_exceededP  s   z"UserAgent._handle_retries_exceededr:   Fc                 K   s\  | j  }|r|| |r7| dkr&|du r|}nt|tr%|| n|du r-|}n
t|tr7|| t||||||| jd}|	durKt|	n| j	}	|
durVt|
n| j
}
t|	d D ]F}|dkro| jrot| j t|
d D ]}| jdur| j| z| |}W n& tjy     ty } z||_| j||jd}W Y d}~ nd}~ww |dur|| j|j||jdd  | jdur| j|| z| j|j|jd W n1 ty } z$||_||_| j|j||jd|_|   | j||jd}W Y d}~ nd}~ww |j!"d	}t|t#r|$d
}|j| j%v rR|rR|   z	|&|j| W qu tyQ } z| j||jd}W Y d}~ nYd}~ww |s[|    S z|j'}W n ty| } z| j||jd}W Y d}~ n.d}~ww |st(|d}| j||jd} n|    S t)|d| j
 d}| j||d}q_| j*||dS )z?Open a URL, do retries and redirects and verify the status codePOSTN)rC   rD   r<   filesrequest_typer   r   rG   )rD   

rq   r   zEmpty response body receivedzRedirection limit reached (r(   r   )+r   r   r   rA   r   dict_make_requestr   r   r   r   ranger   r   sleepr   add_cookie_header_urlopenGreenletExitBaseExceptionr{   r   r   write_conversation_strrD   extract_cookiesr   r   	Exceptionresponsehttp_logr   rC   rW   bytesr   redirect_resonse_codesro   r   r8   r4   r   )r"   r   rB   response_codesrC   rD   	to_stringdebug_streamr<   r   r   r   r$   req_headersreqretry_respr   r   redirectionr   r   r   r   urlopenT  s   





	





zUserAgent.urlopenc                 C   s<   | j |j}|j|j|jj|j|jd}| j|||j	dS )N)bodyrC   )r{   r|   )
r   
get_clientr>   r{   rB   
quoted_urirD   rC   response_typerw   )r"   r{   clientr   r   r   r   r     s   zUserAgent._urlopenr   c                 C   s   d dd |j D }d| d |j }|rAt|tr6z|||d 7 }W n ty5   |d7 }Y nw t|trA||d 7 }|d|j	j
 d t|j d | d |j| 7 }|S )	N
c                 s   r   )r
   Nr   r   r   r   r   r     r   z.UserAgent._conversation_str.<locals>.<genexpr>z	REQUEST: r   zUnicodeDecodeError

z
RESPONSE:  )r   rC   r    rw   r   r   r   UnicodeDecodeErrorr   ru   versionr   r   )clsr   r   rD   encoding
header_strr   r   r   r   r     s:   



zUserAgent._conversation_str @  c                 K   s  | dd  | di }d|d< |rtj|rtj|}nd}t| jd D ]}|rdd| d|d	< | j|fd|i|}	|	j	d
}
|	j
dks^|
r^|
dr^|
d dd t|sd|	  d}|sw| d	d  | j|fd|i|}	t||r}dndf}|r||tj z'|	|}|	 |r|| |	|}|sW d    n1 sw   Y  W n+ ty } z| j||d |	j	ddkr| }W Y d }~W d    q(d }~ww W d     |	S 1 sw   Y   |	S | j||d |	S )Nr   rC   z
Keep-Alive
Connectionr   r   zbytes=-RangezContent-Ranger   r   abwbrG   zaccept-rangesr   )popospathisfilegetsizer   r   r  rC   rW   r   r   r   r   r   openseekSEEK_SETr   r   r   r   tellr   )r"   r   fpath
chunk_sizeresumer$   rC   offsetr   r   crfr   r   r   r   r   download  sj   




	
zUserAgent.downloadc              	   C   s   t ||||||| jdS )z#Backwards compatibility for locust.)rB   rC   rD   r<   r   r   )r   r   )r"   r   rB   rC   rD   r<   r   r   r   r   r     s   zUserAgent._make_request)r   r   r   NNrF   )Nr   )r  F)r:   NNNN)r/   r0   r1   rt   r  r9   r   	frozensetr   r   r%   r   r~   r   r   r   r   r  r   classmethodr   r#  r   r   r   r   r   r     sB    




t

/r   c                 C   s   | dd }|rt||\}}||d< t||d< n6|rPt|tr4|s'd|d< t| }t||d< n|sJt|trJd|d< | }t||d< n|sPd|d< || ||||dS )Nrd   rc   z0application/x-www-form-urlencoded; charset=utf-8ztext/plain; charset=utf-8zapplication/octet-stream)rB   rC   rD   r<   )rW   _encode_multipart_formdatar   r   r   r   encoder   )r   rB   rC   rD   r<   r   r   r   r   r   r   r   &  s$   
r   c                 C   s`   t | dd}|rt|ttfsdS t|tr| }|d dkr,|d dkr.tj|S dS dS )z0Tries to guess the filename of the given object.nameNr   <>)getattrr   r   r   r   r  r  basename)filer(  r   r   r   _guess_filename?  s   
r/  c                 C   s  | st dt|ttfrt dg }t|pi }t| pi } |D ]@\}}t|ttfs1t|ds4|g}|D ]*}|dur`t|tsEt|}|t|trQ|dn|t|tr\|dn|f q6q!| D ]t\}}d}d}	d}
t|t	t
frt|dkr|\}}n)t|dkr|\}}}nt|dkr|\}}}}	n|\}}}}	}
nt|p|}|}t|tttfr|}nt|d	r| }n|du rqd|}t||||	d
}|j|d || qdt||
\}}||fS )a  
    Method taken from models in requests library , usage is the same. The only difference is that
    you can add custom boundary in 5-tuple version.

    Build the body for a multipart/form-data request.

    Will successfully encode files when passed as a dict or a list of
    tuples. Order is retained if data is a list of tuples but arbitrary
    if parameters are supplied as a dict.

    The tuples may be
    2-tuples (filename, fileobj),
    3-tuples (filename, fileobj, contentype),
    4-tuples (filename, fileobj, contentype, custom_headers) or
    5-tuples (filename, fileobj, contentype, custom_headers, custom boundary).

    example:
    files = {'file': ('report.xls', body, 'application/vnd.ms-excel', {'Expires': '0'}, 'custom_boundary')}

    zFiles must be provided.zData must not be a string.r   Nr   r   r      r   )r(  r   filenamerC   )r   )r   r   r   r   r   hasattrappendr   r'  tupler_   r   r/  	bytearrayr   r   make_multipartr   )r   r   
new_fieldsfieldsfieldr   vkftfhboundaryfnfpfdatarfr  r   r   r   r   r&  J  s^   



r&  )!r   r   r   r  r   r   r   r   urllib.parser   r   r   urllib3r   urllib3.fieldsr   geventhttpclient.clientr   r   geventhttpclient.urlr   r   r   r	   r4   r7   r8   r9   rt   r   r   r/  r&  r   r   r   r   <module>   s8    O   
