a
    !f`<                  	   @   sp  d 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	 ddl
mZ ddlmZ ddlmZ ddlmZ ddlmZ d	Zd
Ze	je	je	je	jefZe	je	je	jejejeeeef	ZG dd de dg dZ!ej"d'ddZ#G dd de$Z%dd Z&e dg dZ'G dd de'Z(dd Z)dd Z*de)fddZ+dd de)e+fd!d"Z,g Z-d#d$ Z.d%d& Z/dS )(zwHTTP wrapper for apitools.

This library wraps the underlying http library we use, which is
currently :mod:`httplib2`.
    N)http_client)parse)BadStatusCodeError)RequestError)RetryAfterError)calculate_wait_for_retryi4  i  c                   @   s   e Zd ZdZdS )_ExceptionRetryArgsa  Bundle of information for retriable exceptions.

    :type http: :class:`httplib2.Http` (or conforming alternative)
    :param http: instance used to perform requests.

    :type http_request: :class:`Request`
    :param http_request: the request whose response was a retriable error

    :type exc: :class:`Exception` subclass
    :param exc: the exception being raised.

    :type num_retries: integer
    :param num_retries: Number of retries consumed; used for exponential
                        backoff.
    N)__name__
__module____qualname____doc__ r   r   ^/var/www/html/python-backend/venv/lib/python3.9/site-packages/gcloud/streaming/http_wrapper.pyr   A   s   r   )httphttp_requestexcZnum_retriesmax_retry_waitc                 c   s   | j du rdV  dS tj}i }|t_|dur^|j D ]&\}}d|vrHq6|j||< || q6dV  |t_|dur| D ]\}}|j| | qzdS )a  Temporarily change the value of httplib2.debuglevel, if necessary.

    If http_request has a `loggable_body` distinct from `body`, then we
    need to prevent httplib2 from logging the full body. This sets
    httplib2.debuglevel for the duration of the `with` block; however,
    that alone won't change the value of existing HTTP connections. If
    an httplib2.Http object is provided, we'll also change the level on
    any cached connections attached to it.

    :type http_request: :class:`Request`
    :param http_request: the request to be logged.

    :type level: integer
    :param level: the debuglevel for logging.

    :type http: :class:`httplib2.Http`, or ``None``
    :param http: the instance on whose connections to set the debuglevel.
    N:)loggable_bodyhttplib2
debuglevelconnectionsitemsset_debuglevel)r   levelr   Z	old_levelZhttp_levelsZconnection_key
connectionr   r   r   _httplib2_debug_levelV   s"    

r   c                   @   sN   e Zd ZdZdddZedd Zejd	d Zed
d Zejdd ZdS )Requestai  Encapsulates the data for an HTTP request.

    :type url: str
    :param url: the URL for the request

    :type http_method: str
    :param http_method: the HTTP method to use for the request

    :type headers: mapping or None
    :param headers: headers to be sent with the request

    :type body: str
    :param body: body to be sent with the request
     GETNc                 C   s,   || _ || _|pi | _d | _d | _|| _d S N)urlhttp_methodheaders_body_loggable_bodybody)selfr!   r"   r#   r&   r   r   r   __init__   s    
zRequest.__init__c                 C   s   | j S )zhRequest body for logging purposes

        :rtype: str
        :returns: The body to be logged.
        )r%   r'   r   r   r   r      s    zRequest.loggable_bodyc                 C   s   | j du rtd|| _dS )zUpdate request body for logging purposes

        :type value: str
        :param value: updated body

        :raises: :exc:`RequestError` if the request does not have a body.
        Nz0Cannot set loggable body on request with no body)r&   r   r%   )r'   valuer   r   r   r      s
    	
c                 C   s   | j S )zURequest body

        :rtype: str
        :returns: The body of the request.
        )r$   r)   r   r   r   r&      s    zRequest.bodyc                 C   sb   || _ |dur6t| j ddp$t| j }t|| jd< n| jdd t|tdtj	fs^d| _
dS )zUpdate the request body

        Handles logging and length measurement.

        :type value: str
        :param value: updated body
        Nlengthcontent-lengthz<media body>)r$   getattrlenstrr#   pop
isinstancetypesixstring_typesr   )r'   r*   body_lengthr   r   r   r&      s    	)r   r   Nr   )	r	   r
   r   r   r(   propertyr   setterr&   r   r   r   r   r      s   



r   c                 C   sD   |  d\}}}| d\}}}| d\}}}t|t| d S )a
  Convert a 'Content-Range' header into a length for the response.

    Helper for :meth:`Response.length`.

    :type content_range: str
    :param content_range: the header value being parsed.

    :rtype: integer
    :returns: the length of the response chunk.
     /-   )	partitionint)Zcontent_range_Z
range_specZ
byte_rangestartendr   r   r   _process_content_range   s    rA   ZHttpResponse)infocontentrequest_urlc                   @   sL   e Zd ZdZdZdd Zedd Zedd Zed	d
 Z	edd Z
dS )Responsez,Encapsulates data for an HTTP response.
    r   c                 C   s   | j S r    )r+   r)   r   r   r   __len__   s    zResponse.__len__c                 C   s^   d| j v r"d| j v r"t| j d S d| j v r<t| j dS d| j v rTt| j d S t| jS )zLength of this response.

        Exposed as an attribute since using ``len()`` directly can fail
        for responses larger than ``sys.maxint``.

        :rtype: integer or long
        :returns: The length of the response.
        zcontent-encodingzcontent-ranger,   )rB   rA   r=   getr.   rC   r)   r   r   r   r+      s    


zResponse.lengthc                 C   s   t | jd S )z^HTTP status code

        :rtype: integer
        :returns: The response status code.
        status)r=   rB   r)   r   r   r   status_code  s    zResponse.status_codec                 C   s   d| j v rt| j d S dS )z`Retry interval (if set).

        :rtype: integer
        :returns: interval in seconds
        zretry-afterN)rB   r=   r)   r   r   r   retry_after  s    
zResponse.retry_afterc                 C   s   | j tv od| jv S )zDoes this response contain a redirect

        :rtype: boolean
        :returns: True if the status code indicates a redirect and the
                  'location' header is present.
        location)rI   _REDIRECT_STATUS_CODESrB   r)   r   r   r   is_redirect  s    
zResponse.is_redirectN)r	   r
   r   r   	__slots__rF   r6   r+   rI   rJ   rM   r   r   r   r   rE      s   


	rE   c                 C   sF   | du rt dn0| jdks&| jtkr2t| n| jrBt| dS )a  Validate a response

    :type response: :class:`Response`
    :param response: the response to validate

    :raises: :exc:`gcloud.streaming.exceptions.RequestError` if response is
             None, :exc:`gcloud.streaming.exceptions.BadStatusCodeError` if
             response status code indicates an error, or
             :exc:`gcloud.streaming.exceptions.RetryAfterError` if response
             indicates a retry interval.
    Nz"Request did not return a response.i  )r   rI   TOO_MANY_REQUESTSr   Zfrom_responserJ   r   )responser   r   r   _check_response!  s    
rQ   c                 C   s4   t | ddr0t| j D ]}d|v r| j|= qdS )a  Rebuild all http connections in the httplib2.Http instance.

    httplib2 overloads the map in http.connections to contain two different
    types of values:
    { scheme string:  connection class } and
    { scheme + authority string : actual http connection }
    Here we remove all of the entries for actual connections so that on the
    next request httplib2 will rebuild them from the connection types.

    :type http: :class:`httplib2.Http`
    :param http: the instance whose connections are to be rebuilt
    r   Nr   )r-   listr   keys)r   Zconn_keyr   r   r   _reset_http_connections8  s    rT      c           
   	   C   s   d}t | ddr6t|jj}|r6|| jv r6| j| }tjdkrDdnd}t||| d: | j	t
|jt
|j|j|j||d\}}W d   n1 s0    Y  |du rt t|||j}	||	 |	S )a4  Send an HTTP request via the given http instance.

    This wrapper exists to handle translation between the plain httplib2
    request/response types and the Request and Response types above.

    :type http: :class:`httplib2.Http`
    :param http: an instance which impelements the `Http` API.

    :type http_request: :class:`Request`
    :param http_request: the request to send.

    :type redirections: integer
    :param redirections: Number of redirects to follow.

    :type check_response_func: function taking (response, content, url).
    :param check_response_func: Function to validate the HTTP response.

    :rtype: :class:`Response`
    :returns: an object representing the server's response

    :raises: :exc:`gcloud.streaming.exceptions.RequestError` if no response
             could be parsed.
    Nr      r   )r   )methodr&   r#   redirectionsconnection_type)r-   r   urlsplitr!   schemer   r   r   r   requestr/   r"   r&   r#   r   rE   )
r   r   rX   check_response_funcrY   
url_schemeZnew_debuglevelrB   rC   rP   r   r   r   _make_api_request_no_retryK  s"    
(r_      <   c           
   
   C   s   d}z|| |||dW S  t y } zd|d7 }||kr8 t|dd}	|	du rVt||}	t|  td|jt|j t	
|	 W Y d}~qd}~0 0 qdS )ay  Send an HTTP request via the given http, performing error/retry handling.

    :type http: :class:`httplib2.Http`
    :param http: an instance which impelements the `Http` API.

    :type http_request: :class:`Request`
    :param http_request: the request to send.

    :type retries: integer
    :param retries: Number of retries to attempt on retryable
                    responses (such as 429 or 5XX).

    :type max_retry_wait: integer
    :param max_retry_wait: Maximum number of seconds to wait when retrying.

    :type redirections: integer
    :param redirections: Number of redirects to follow.

    :type check_response_func: function taking (response, content, url).
    :param check_response_func: Function to validate the HTTP response.

    :type wo_retry_func: function taking
                         (http, request, redirections, check_response_func)
    :param wo_retry_func: Function to make HTTP request without retries.

    :rtype: :class:`Response`
    :returns: an object representing the server's response

    :raises: :exc:`gcloud.streaming.exceptions.RequestError` if no response
             could be parsed.
    r   )rX   r]   r;   rJ   Nz-Retrying request to url %s after exception %s)_RETRYABLE_EXCEPTIONSr-   r   rT   loggingdebugr!   r2   r	   timesleep)
r   r   retriesr   rX   r]   Zwo_retry_funcretryr   rJ   r   r   r   make_api_request}  s$    %
ri   c                 C   s   t |  dS )a2  Register a custom HTTP factory.

    :type factory: callable taking keyword arguments, returning an Http
                   instance (or an instance implementing the same API);
    :param factory: the new factory (it may return ``None`` to defer to
                    a later factory or the default).
    N)_HTTP_FACTORIESappend)factoryr   r   r   _register_http_factory  s    rm   c                  K   s8   t D ]"}|f i | }|dur|  S qtjf i | S )zConstruct an Http instance.

    :type kwds: dict
    :param kwds:  keyword arguments to pass to factories.

    :rtype: :class:`httplib2.Http` (or a workalike)
    :returns: The HTTP object created.
    N)rj   r   ZHttp)kwdsrl   r   r   r   r   get_http  s
    	
ro   )N)0r   collections
contextlibrc   socketre   r   r3   Z	six.movesr   Zsix.moves.urllibr   Zgcloud.streaming.exceptionsr   r   r   Zgcloud.streaming.utilr   RESUME_INCOMPLETErO   MOVED_PERMANENTLYFOUND	SEE_OTHERTEMPORARY_REDIRECTrL   BadStatusLineIncompleteReadResponseNotReadyerrorZServerNotFoundError
ValueErrorrb   
namedtupler   contextmanagerr   objectr   rA   Z_ResponseTuplerE   rQ   rT   r_   ri   rj   rm   ro   r   r   r   r   <module>   sv   

*M<
3
9