o
    ~j6h
                    @   sN  d Z ddlmZ dZddlZddl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ZddlZddlZddlZddlZzddlZW n eyR   e ZY nw ej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dl$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z* ddl+m,Z, e
-e.Z/dZ0dZ1dZ2dZ3dZ4dZ5dd Z6dd Z7G dd deZ8G dd deZ9G 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$eZ>G d%d& d&eZ?G d'd( d(eZ@G d)d* d*eZAG d+d, d,eZBG d-d. d.eZCG d/d0 d0eZDG d1d2 d2eZEd3d4 ZFd5d6 ZGd7d8 ZHdS )9zClasses to encapsulate a single HTTP request.

The classes implement a command pattern, with every
object supporting an execute() method that does the
actual HTTP request.
    )absolute_importz$jcgregorio@google.com (Joe Gregorio)N)	Generator)MIMEMultipart)MIMENonMultipart)
FeedParser)_auth)_helpers)
BatchError	HttpErrorInvalidChunkSizeErrorResumableUploadErrorUnexpectedBodyErrorUnexpectedMethodError)	JsonModeli  @i   i  i  <   z https://www.googleapis.com/batchc              
      s   d}| dkrdS | t krdS | tjkr||sdS zEt|d t trQt fdddD d	}|rP d
 | }t|t	rPt
|dkrP|d }d|v rP|d }n
 d d
 d d }W n tttfyo   td| Y dS w td| |dv r|dS dS )zDetermines whether a response should be retried.

    Args:
      resp_status: The response status received.
      content: The response content body.

    Returns:
      True if the response should be retried, otherwise False.
    Ni  TFutf-8c                 3   s     | ]}| d  v r|V  qdS )errorN ).0kwdatar   c/var/www/html/chefvision.cloud.itp360.com/venv/lib/python3.10/site-packages/googleapiclient/http.py	<genexpr>w   s    z)_should_retry_response.<locals>.<genexpr>)errorsstatusmessage r   r   reasonr   z&Invalid JSON content from response: %sz*Encountered 403 Forbidden with reason "%s")userRateLimitExceededrateLimitExceeded)_TOO_MANY_REQUESTShttp_client	FORBIDDENjsonloadsdecode
isinstancedictnextlistlenUnicodeDecodeError
ValueErrorKeyErrorLOGGERwarning)resp_statuscontentr   error_detail_keywordr   r   r   _should_retry_responseP   sD   



	r4   c                 O   s  d}	d}
d}t |d D ]}|dkr.| d|  }td|||||||	r'|	jn| || zd}| j||g|R i |\}	}
W nm tyU } z|}W Y d}~n^d}~w tjyi } z|}W Y d}~nJd}~w ty| } z|}W Y d}~n7d}~w t	y } ztj
j|j
dvr |}W Y d}~nd}~w tjy } z|}W Y d}~nd}~ww |r||kr|qt|	j|
s |	|
fS q|	|
fS )a  Retries an HTTP request multiple times while handling errors.

    If after all retries the request still fails, last error is either returned as
    return value (for HTTP 5xx errors) or thrown (for ssl.SSLError).

    Args:
      http: Http object to be used to execute request.
      num_retries: Maximum number of retries.
      req_type: Type of the request (used for logging retries).
      sleep, rand: Functions to sleep for random time between retries.
      uri: URI to be requested.
      method: HTTP method to be used.
      args, kwargs: Additional arguments passed to http.request.

    Returns:
      resp, content - Response from the http request (may be HTTP 5xx).
    N   r      zCSleeping %.2f seconds before retry %d of %d for %s: %s %s, after %s>   EPIPE	ETIMEDOUT
ECONNRESETECONNABORTEDECONNREFUSEDWSAETIMEDOUT)ranger/   r0   r   request_ssl_SSLErrorsockettimeoutConnectionErrorOSErrorerrno	errorcodegethttplib2ServerNotFoundErrorr4   )httpnum_retriesreq_typesleeprandurimethodargskwargsrespr2   	exception	retry_num
sleep_time	ssl_errorsocket_timeoutconnection_errorsocket_errorserver_not_found_errorr   r   r   _retry_request   s^   
"r[   c                   @       e Zd ZdZdd Zdd ZdS )MediaUploadProgresszStatus of a resumable upload.c                 C      || _ || _dS )zConstructor.

        Args:
          resumable_progress: int, bytes sent so far.
          total_size: int, total bytes in complete upload, or None if the total
            upload size isn't known ahead of time.
        Nresumable_progress
total_sizeselfr`   ra   r   r   r   __init__   s   
zMediaUploadProgress.__init__c                 C   ,   | j dur| j dkrt| jt| j  S dS )zPercent of upload completed, as a float.

        Returns:
          the percentage complete as a float, returning 0.0 if the total size of
          the upload is unknown.
        Nr           ra   floatr`   rc   r   r   r   progress      zMediaUploadProgress.progressN__name__
__module____qualname____doc__rd   rj   r   r   r   r   r]      s    r]   c                   @   r\   )MediaDownloadProgresszStatus of a resumable download.c                 C   r^   )zConstructor.

        Args:
          resumable_progress: int, bytes received so far.
          total_size: int, total bytes in complete download.
        Nr_   rb   r   r   r   rd     s   
zMediaDownloadProgress.__init__c                 C   re   )zPercent of download completed, as a float.

        Returns:
          the percentage complete as a float, returning 0.0 if the total size of
          the download is unknown.
        Nr   rf   rg   ri   r   r   r   rj     rk   zMediaDownloadProgress.progressNrl   r   r   r   r   rq     s    
rq   c                   @   sp   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
eddddZdd Zedd ZdS )MediaUploada  Describes a media object to upload.

    Base class that defines the interface of MediaUpload subclasses.

    Note that subclasses of MediaUpload may allow you to control the chunksize
    when uploading a media object. It is important to keep the size of the chunk
    as large as possible to keep the upload efficient. Other factors may influence
    the size of the chunk you use, particularly if you are working in an
    environment where individual HTTP requests may have a hardcoded time limit,
    such as under certain classes of requests under Google App Engine.

    Streams are io.Base compatible objects that support seek(). Some MediaUpload
    subclasses support using streams directly to upload data. Support for
    streaming may be indicated by a MediaUpload sub-class and if appropriate for a
    platform that stream will be used for uploading the media object. The support
    for streaming is indicated by has_stream() returning True. The stream() method
    should return an io.Base object that supports seek(). On platforms where the
    underlying httplib module supports streaming, for example Python 2.6 and
    later, the stream will be passed into the http library which will result in
    less memory being used and possibly faster uploads.

    If you need to upload media that can't be uploaded using any of the existing
    MediaUpload sub-class then you can sub-class MediaUpload for your particular
    needs.
    c                 C      t  z[Chunk size for resumable uploads.

        Returns:
          Chunk size in bytes.
        NotImplementedErrorri   r   r   r   	chunksize8     zMediaUpload.chunksizec                 C      dS )FMime type of the body.

        Returns:
          Mime type.
        application/octet-streamr   ri   r   r   r   mimetype@     zMediaUpload.mimetypec                 C   ry   )fSize of upload.

        Returns:
          Size of the body, or None of the size is unknown.
        Nr   ri   r   r   r   sizeH  r}   zMediaUpload.sizec                 C   ry   )iWhether this upload is resumable.

        Returns:
          True if resumable upload or False.
        Fr   ri   r   r   r   	resumableP  r}   zMediaUpload.resumablec                 C   rs   )a  Get bytes from the media.

        Args:
          begin: int, offset from beginning of file.
          length: int, number of bytes to read, starting at begin.

        Returns:
          A string of bytes read. May be shorter than length if EOF was reached
          first.
        ru   )rc   beginendr   r   r   getbytesX  s   zMediaUpload.getbytesc                 C   ry   ),  Does the underlying upload support a streaming interface.

        Streaming means it is an io.IOBase subclass that supports seek, i.e.
        seekable() returns True.

        Returns:
          True if the call to stream() will return an instance of a seekable io.Base
          subclass.
        Fr   ri   r   r   r   
has_streame     
zMediaUpload.has_streamc                 C   rs   zA stream interface to the data being uploaded.

        Returns:
          The returned value is an io.IOBase subclass that supports seek, i.e.
          seekable() returns True.
        ru   ri   r   r   r   streamq     zMediaUpload.streamr5   Nc                 C   sJ   t | }t| j}|dur|D ]}||= q|j|d< |j|d< t|S )a'  Utility function for creating a JSON representation of a MediaUpload.

        Args:
          strip: array, An array of names of members to not include in the JSON.

        Returns:
           string, a JSON representation of this instance, suitable to pass to
           from_json().
        N_class_module)typecopy__dict__rm   rn   r$   dumps)rc   striptdmemberr   r   r   _to_jsonz  s   


zMediaUpload._to_jsonc                 C   s   |   S )zCreate a JSON representation of an instance of MediaUpload.

        Returns:
           string, a JSON representation of this instance, suitable to pass to
           from_json().
        r   ri   r   r   r   to_json  s   zMediaUpload.to_jsonc                 C   sL   t |}|d }t||ddd d}t||d }t|d}||S )a+  Utility class method to instantiate a MediaUpload subclass from a JSON
        representation produced by to_json().

        Args:
          s: string, JSON from to_json().

        Returns:
          An instance of the subclass of MediaUpload that was serialized with
          to_json().
        r   .N)fromlistr   	from_json)r$   r%   
__import__splitgetattr)clssr   modulemklsr   r   r   r   new_from_json  s   

zMediaUpload.new_from_jsonN)rm   rn   ro   rp   rw   r|   r   r   r   r   r   util
positionalr   r   classmethodr   r   r   r   r   rr     s    		rr   c                       sp   e Zd ZdZededf fdd	Zdd Zdd	 Z	d
d Z
dd Zdd Zdd Zdd Zdd Z  ZS )MediaIoBaseUploada  A MediaUpload for a io.Base objects.

    Note that the Python file object is compatible with io.Base and can be used
    with this class also.

      fh = BytesIO('...Some data to upload...')
      media = MediaIoBaseUpload(fh, mimetype='image/png',
        chunksize=1024*1024, resumable=True)
      farm.animals().insert(
          id='cow',
          name='cow.png',
          media_body=media).execute()

    Depending on the platform you are working on, you may pass -1 as the
    chunksize, which indicates that the entire file should be uploaded in a single
    request. If the underlying platform supports streams, such as Python 2.6 or
    later, then this can be very efficient as it avoids multiple connections, and
    also avoids loading the entire file into memory before sending it. Note that
    Google App Engine has a 5MB limit on request size, so you should never set
    your chunksize larger than 5MB, or to -1.
       Fc                    s\   t t|   || _|| _|dks|dkst || _|| _| jdt	j
 | j | _dS )a;  Constructor.

        Args:
          fd: io.Base or file object, The source of the bytes to upload. MUST be
            opened in blocking mode, do not use streams opened in non-blocking mode.
            The given stream must be seekable, that is, it must be able to call
            seek() on fd.
          mimetype: string, Mime-type of the file.
          chunksize: int, File will be uploaded in chunks of this many bytes. Only
            used if resumable=True. Pass in a value of -1 if the file is to be
            uploaded as a single chunk. Note that Google App Engine has a 5MB limit
            on request size, so you should never set your chunksize larger than 5MB,
            or to -1.
          resumable: bool, True if this is a resumable upload. False means upload
            in a single request.
        r   r   N)superr   rd   _fd	_mimetyper   
_chunksize
_resumableseekosSEEK_ENDtell_size)rc   fdr|   rw   r   	__class__r   r   rd     s   zMediaIoBaseUpload.__init__c                 C      | j S rt   )r   ri   r   r   r   rw     rx   zMediaIoBaseUpload.chunksizec                 C   r   )rz   )r   ri   r   r   r   r|     rx   zMediaIoBaseUpload.mimetypec                 C   r   )r~   )r   ri   r   r   r   r     rx   zMediaIoBaseUpload.sizec                 C   r   )r   )r   ri   r   r   r   r     rx   zMediaIoBaseUpload.resumablec                 C   s   | j | | j |S )a  Get bytes from the media.

        Args:
          begin: int, offset from beginning of file.
          length: int, number of bytes to read, starting at begin.

        Returns:
          A string of bytes read. May be shorted than length if EOF was reached
          first.
        )r   r   read)rc   r   lengthr   r   r   r      s   zMediaIoBaseUpload.getbytesc                 C   ry   )r   Tr   ri   r   r   r   r     r   zMediaIoBaseUpload.has_streamc                 C   r   r   )r   ri   r   r   r   r     r   zMediaIoBaseUpload.streamc                 C   s   t d)z%This upload type is not serializable.z&MediaIoBaseUpload is not serializable.ru   ri   r   r   r   r   #     zMediaIoBaseUpload.to_json)rm   rn   ro   rp   r   r   DEFAULT_CHUNK_SIZErd   rw   r|   r   r   r   r   r   r   __classcell__r   r   r   r   r     s    	r   c                       sN   e Zd ZdZeddedf fdd	Zdd Zd	d
 Z	e
dd Z  ZS )MediaFileUploada  A MediaUpload for a file.

    Construct a MediaFileUpload and pass as the media_body parameter of the
    method. For example, if we had a service that allowed uploading images:

      media = MediaFileUpload('cow.png', mimetype='image/png',
        chunksize=1024*1024, resumable=True)
      farm.animals().insert(
          id='cow',
          name='cow.png',
          media_body=media).execute()

    Depending on the platform you are working on, you may pass -1 as the
    chunksize, which indicates that the entire file should be uploaded in a single
    request. If the underlying platform supports streams, such as Python 2.6 or
    later, then this can be very efficient as it avoids multiple connections, and
    also avoids loading the entire file into memory before sending it. Note that
    Google App Engine has a 5MB limit on request size, so you should never set
    your chunksize larger than 5MB, or to -1.
    r6   NFc                    sZ   d| _ || _t| jd| _ |du rt|\}}|du rd}tt| j| j |||d dS )a  Constructor.

        Args:
          filename: string, Name of the file.
          mimetype: string, Mime-type of the file. If None then a mime-type will be
            guessed from the file extension.
          chunksize: int, File will be uploaded in chunks of this many bytes. Only
            used if resumable=True. Pass in a value of -1 if the file is to be
            uploaded in a single chunk. Note that Google App Engine has a 5MB limit
            on request size, so you should never set your chunksize larger than 5MB,
            or to -1.
          resumable: bool, True if this is a resumable upload. False means upload
            in a single request.
        Nrbr{   rw   r   )r   	_filenameopen	mimetypes
guess_typer   r   rd   )rc   filenamer|   rw   r   _r   r   r   rd   >  s   


zMediaFileUpload.__init__c                 C   s   | j r
| j   d S d S r   )r   closeri   r   r   r   __del__]  s   zMediaFileUpload.__del__c                 C   s   | j dgdS )zCreating a JSON representation of an instance of MediaFileUpload.

        Returns:
           string, a JSON representation of this instance, suitable to pass to
           from_json().
        r   )r   r   ri   r   r   r   r   a  s   zMediaFileUpload.to_jsonc                 C   s*   t | }t|d |d |d |d dS )Nr   r   r   r   )r|   rw   r   )r$   r%   r   )r   r   r   r   r   r   j  s   
zMediaFileUpload.from_json)rm   rn   ro   rp   r   r   r   rd   r   r   staticmethodr   r   r   r   r   r   r   (  s    	r   c                       s2   e Zd ZdZeddedf fdd	Z  ZS )MediaInMemoryUploadzMediaUpload for a chunk of bytes.

    DEPRECATED: Use MediaIoBaseUpload with either io.TextIOBase or io.StringIO for
    the stream.
    r6   r{   Fc                    s&   t |}tt| j||||d dS )a&  Create a new MediaInMemoryUpload.

        DEPRECATED: Use MediaIoBaseUpload with either io.TextIOBase or io.StringIO for
        the stream.

        Args:
          body: string, Bytes of body content.
          mimetype: string, Mime-type of the file or default of
            'application/octet-stream'.
          chunksize: int, File will be uploaded in chunks of this many bytes. Only
            used if resumable=True.
          resumable: bool, True if this is a resumable upload. False means upload
            in a single request.
        r   N)ioBytesIOr   r   rd   )rc   bodyr|   rw   r   r   r   r   r   rd   |  s   


zMediaInMemoryUpload.__init__)	rm   rn   ro   rp   r   r   r   rd   r   r   r   r   r   r   u  s    r   c                   @   s:   e Zd ZdZedefddZedd
ddZd	S )MediaIoBaseDownloada   "Download media resources.

    Note that the Python file object is compatible with io.Base and can be used
    with this class also.


    Example:
      request = farms.animals().get_media(id='cow')
      fh = io.FileIO('cow.png', mode='wb')
      downloader = MediaIoBaseDownload(fh, request, chunksize=1024*1024)

      done = False
      while done is False:
        status, done = downloader.next_chunk()
        if status:
          print "Download %d%%." % int(status.progress() * 100)
      print "Download Complete!"
    r   c                 C   sp   || _ || _|j| _|| _d| _d| _d| _tj	| _
tj| _i | _|j D ]\}}| dvr5|| j|< q&dS )aB  Constructor.

        Args:
          fd: io.Base or file object, The stream in which to write the downloaded
            bytes.
          request: googleapiclient.http.HttpRequest, the media request to perform in
            chunks.
          chunksize: int, File will be downloaded in chunks of this many bytes.
        r   NF)acceptzaccept-encoding
user-agent)r   _requestrN   _urir   	_progress_total_size_donetimerL   _sleeprandom_rand_headersheadersitemslower)rc   r   r>   rw   kvr   r   r   rd     s   
zMediaIoBaseDownload.__init__r5   r   c              
   C   sl  | j  }d| j| j| j d f |d< | jj}t||d| j| j| j	d|d\}}|j
dv rd|v r>|d | j	kr>|d | _	|  jt|7  _| j| d	|v rc|d	 }|d
dd }t|| _nd|v rnt|d | _| jdu sy| j| jkr|d| _t| j| j| jfS |j
dkr|d	 }|d
dd }t|| _| jdkrd| _t| j| j| jfS t||| j	d)a  Get the next chunk of the download.

        Args:
          num_retries: Integer, number of times to retry with randomized
                exponential backoff. If all retries fail, the raised HttpError
                represents the last request. If zero (default), we attempt the
                request only once.

        Returns:
          (status, done): (MediaDownloadProgress, boolean)
             The value of 'done' will be True when the media has been fully
             downloaded or the total size of the media is unknown.

        Raises:
          googleapiclient.errors.HttpError if the response was not a 2xx.
          httplib2.HttpLib2Error if a transport error has occurred.
        zbytes=%d-%dr5   r=   zmedia downloadGETr   )      zcontent-locationzcontent-range/content-lengthNTi  r   rN   )r   r   r   r   r   rI   r[   r   r   r   r   r+   r   writersplitintr   r   rq   r
   )rc   rJ   r   rI   rR   r2   content_ranger   r   r   r   
next_chunk  sP   







zMediaIoBaseDownload.next_chunkN)r   )	rm   rn   ro   rp   r   r   r   rd   r   r   r   r   r   r     s    r   c                   @   s"   e Zd ZdZdd ZdddZdS )	_StreamSlicea  Truncated stream.

    Takes a stream and presents a stream that is a slice of the original stream.
    This is used when uploading media in chunks. In later versions of Python a
    stream can be passed to httplib in place of the string of data to send. The
    problem is that httplib just blindly reads to the end of the stream. This
    wrapper presents a virtual stream that only reads to the end of the chunk.
    c                 C   s"   || _ || _|| _| j | dS )zConstructor.

        Args:
          stream: (io.Base, file object), the stream to wrap.
          begin: int, the seek position the chunk begins at.
          chunksize: int, the size of the chunk.
        N)_stream_beginr   r   )rc   r   r   rw   r   r   r   rd     s   z_StreamSlice.__init__r   c                 C   s>   | j  }| j| j }|dks|| |kr|| }| j |S )zRead n bytes.

        Args:
          n, int, the number of bytes to read.

        Returns:
          A string of length 'n', or less if EOF is reached.
        r   )r   r   r   r   r   )rc   ncurr   r   r   r   r   &  s
   

z_StreamSlice.readN)r   )rm   rn   ro   rp   rd   r   r   r   r   r   r     s    	r   c                   @   s   e Zd ZdZed					dddZeddd	d
Zeddd ZeddddZ	dd Z
dd Zedd Zedd ZdS )HttpRequestz#Encapsulates a single HTTP request.   r   Nc	           	      C   sp   || _ || _|| _|pi | _|| _|| _|| _|| _g | _d| _	t
| jp%d| _d| _d| _tj| _tj| _dS )a  Constructor for an HttpRequest.

        Args:
          http: httplib2.Http, the transport object to use to make a request
          postproc: callable, called on the HTTP response and content to transform
                    it into a data object before returning, or raising an exception
                    on an error.
          uri: string, the absolute URI to send the request to
          method: string, the HTTP method to use
          body: string, the request body of the HTTP request,
          headers: dict, the HTTP request headers
          methodId: string, a unique identifier for the API method being called.
          resumable: MediaUpload, None if this is not a resumbale request.
        Fr   Nr   )rN   rO   r   r   methodIdrI   postprocr   response_callbacks_in_error_stater+   	body_sizeresumable_urir`   r   r   r   rL   r   )	rc   rI   r   rN   rO   r   r   r   r   r   r   r   rd   :  s   
zHttpRequest.__init__r5   r   c           	      C   sB  |du r| j }| jrd}|du r| j||d\}}|du s|S d| jvr,t| j| jd< t| jtkrk| j	dkrkd| _	d| jd< d| jd< t
j| j}t
j|j|j|j|jddf| _|j| _tt| j| jd< t||d	| j| jt| jt| j	| j| jd
	\}}| jD ]}|| q|jdkrt||| jd| ||S )a  Execute the request.

        Args:
          http: httplib2.Http, an http object to be used in place of the
                one the HttpRequest request object was constructed with.
          num_retries: Integer, number of times to retry with randomized
                exponential backoff. If all retries fail, the raised HttpError
                represents the last request. If zero (default), we attempt the
                request only once.

        Returns:
          A deserialized object model of the response body as determined
          by the postproc.

        Raises:
          googleapiclient.errors.HttpError if the response was not a 2xx.
          httplib2.HttpLib2Error if a transport error has occurred.
        N)rI   rJ   r   r   POSTx-http-method-overridez!application/x-www-form-urlencodedcontent-typer>   rO   r   r   ,  r   )rI   r   r   r   strr   r+   rN   MAX_URI_LENGTHrO   urllibparseurlparse
urlunparseschemenetlocpathparamsqueryr   r[   r   r   r   r   r
   r   )	rc   rI   rJ   r   r   parsedrR   r2   callbackr   r   r   executel  sH   






zHttpRequest.executer6   c                 C   s   | j | dS )zadd_response_headers_callback

        Args:
          cb: Callback to be called on receiving the response headers, of signature:

          def cb(resp):
            # Where resp is an instance of httplib2.Response
        N)r   append)rc   cbr   r   r   add_response_callback  s   
z!HttpRequest.add_response_callbackc                 C   s  |du r| j }| j du rd}nt| j }| jdu rat| j}| j |d< |dkr2||d< t| j|d< t	||d| j
| j| j| j| j|d	\}}|jdkr\d	|v r\|d	 | _n(t||| jrd
| dd}|j| jd|d\}}| ||\}}	|	r||	fS | j r| j }
| j dkr|
| j | j | j d }nCt|
| j| j }
t| j| j  d | j d }n&| j| j| j }
t|
| j k rt| jt|
 }| jt|
 d }dt|| j d i}|dkrd| j||f |d< t|d D ]@}|dkr)| 
|  d|   td|| j| j|jf  z|j| jd|
|d\}}W n   d| _ t |j|sH nq	| ||S )a  Execute the next step of a resumable upload.

        Can only be used if the method being executed supports media uploads and
        the MediaUpload object passed in was flagged as using resumable upload.

        Example:

          media = MediaFileUpload('cow.png', mimetype='image/png',
                                  chunksize=1000, resumable=True)
          request = farm.animals().insert(
              id='cow',
              name='cow.png',
              media_body=media)

          response = None
          while response is None:
            status, response = request.next_chunk()
            if status:
              print "Upload %d%% complete." % int(status.progress() * 100)


        Args:
          http: httplib2.Http, an http object to be used in place of the
                one the HttpRequest request object was constructed with.
          num_retries: Integer, number of times to retry with randomized
                exponential backoff. If all retries fail, the raised HttpError
                represents the last request. If zero (default), we attempt the
                request only once.

        Returns:
          (status, body): (ResumableMediaStatus, object)
             The body will be None until the resumable media is fully uploaded.

        Raises:
          googleapiclient.errors.HttpError if the response was not a 2xx.
          httplib2.HttpLib2Error if a transport error has occurred.
        N*zX-Upload-Content-TypezX-Upload-Content-Lengthr   zresumable URI requestr   r   locationz
bytes */%s0)Content-Ranger   PUTr   r   r5   zContent-Lengthzbytes %d-%d/%sr  r   r6   z7Retry #%d for media upload: %s %s, following status: %dT)!rI   r   r   r   r   r   r   r|   r   r[   r   r   rN   rO   r   r   r   r   r>   _process_responser   r   rw   r   r`   r   minr   r+   r=   r/   r0   r4   )rc   rI   rJ   r   start_headersrR   r2   r   r   r   r   	chunk_endrT   r   r   r   r     s   '





	


zHttpRequest.next_chunkc                 C   s   |j dv rd| _d| ||fS |j dkr?d| _zt|d dd d | _W n ty4   d| _Y nw d	|v r>|d	 | _nd
| _t||| j	dt
| j| j dfS )a  Process the response from a single chunk upload.

        Args:
          resp: httplib2.Response, the response object.
          content: string, the content of the response.

        Returns:
          (status, body): (ResumableMediaStatus, object)
             The body will be None until the resumable media is fully uploaded.

        Raises:
          googleapiclient.errors.HttpError if the response was not a 2xx or a 308.
        )r      FN4  r=   -r5   r   r  Tr   )r   r   r   r   r   r`   r.   r   r
   rN   r]   r   r   )rc   rR   r2   r   r   r   r  G  s$   

 

zHttpRequest._process_responsec                 C   sH   t  | j}|d dur| j |d< |d= |d= |d= |d= t|S )z1Returns a JSON representation of the HttpRequest.r   NrI   r   r   r   )r   r   r   r   r$   r   )rc   r   r   r   r   r   k  s   
zHttpRequest.to_jsonc              
   C   sX   t | }|d durt|d |d< t|||d |d |d |d |d |d dS )	z>Returns an HttpRequest populated with info from a JSON object.r   NrN   rO   r   r   r   )rN   rO   r   r   r   r   )r$   r%   rr   r   r   )r   rI   r   r   r   r   r   r   w  s   
zHttpRequest.from_jsonc                 C   s   | |fS r   r   )rR   contentsr   r   r   null_postproc  r   zHttpRequest.null_postprocr   NNNN)Nr   )rm   rn   ro   rp   r   r   rd   r  r  r   r  r   r   r   r  r   r   r   r   r   7  s,    1@
 $
r   c                   @   s   e Zd ZdZeddddZdd Zdd	 Zd
d Z	dd Z
dd Zdd ZeddddZdd ZeddddZdS )BatchHttpRequesta  Batches multiple HttpRequest objects into a single HTTP request.

    Example:
      from googleapiclient.http import BatchHttpRequest

      def list_animals(request_id, response, exception):
        """Do something with the animals list response."""
        if exception is not None:
          # Do something with the exception.
          pass
        else:
          # Do something with the response.
          pass

      def list_farmers(request_id, response, exception):
        """Do something with the farmers list response."""
        if exception is not None:
          # Do something with the exception.
          pass
        else:
          # Do something with the response.
          pass

      service = build('farm', 'v2')

      batch = BatchHttpRequest()

      batch.add(service.animals().list(), list_animals)
      batch.add(service.farmers().list(), list_farmers)
      batch.execute(http=http)
    r5   Nc                 C   sZ   |du rt }|t krtdt  || _|| _i | _i | _g | _d| _d| _	i | _
i | _dS )a  Constructor for a BatchHttpRequest.

        Args:
          callback: callable, A callback to be called for each response, of the
            form callback(id, response, exception). The first parameter is the
            request id, and the second is the deserialized response object. The
            third is an googleapiclient.errors.HttpError exception object if an HTTP error
            occurred while processing the request, or None if no error occurred.
          batch_uri: string, URI to send batch requests to.
        Na  You have constructed a BatchHttpRequest using the legacy batch endpoint %s. This endpoint will be turned down on August 12, 2020. Please provide the API-specific endpoint or use service.new_batch_http_request(). For more details see https://developers.googleblog.com/2018/03/discontinuing-support-for-json-rpc-and.htmland https://developers.google.com/api-client-library/python/guide/batch.r   )_LEGACY_BATCH_URIr/   r0   
_batch_uri	_callback	_requests
_callbacks_order_last_auto_id_base_id
_responses_refreshed_credentials)rc   r
  	batch_urir   r   r   rd     s    	
zBatchHttpRequest.__init__c                 C   s   d}d}|j durt|j }d}|du r|durt|}|dur5t|| jvr5t| d| jt|< |j du s<|sEt||j dS dS )zRefresh the credentials and apply to the request.

        Args:
          request: HttpRequest, the request.
          http: httplib2.Http, the global http object for the batch.
        NFTr5   )rI   r   get_credentials_from_httpidr(  refresh_credentialsapply_credentialsr   )rc   r>   rI   credsrequest_credentialsr   r   r   _refresh_and_apply_credentials  s   



z/BatchHttpRequest._refresh_and_apply_credentialsc                 C   s*   | j du r
t | _ d| j tj|f S )aA  Convert an id to a Content-ID header value.

        Args:
          id_: string, identifier of individual request.

        Returns:
          A Content-ID header with the id_ encoded into it. A UUID is prepended to
          the value because Content-ID headers are supposed to be universally
          unique.
        Nz	<%s + %s>)r&  uuiduuid4r   r  quote)rc   id_r   r   r   _id_to_header  s   

zBatchHttpRequest._id_to_headerc                 C   s\   |d dks|d dkrt d| d|vrt d| |dd dd\}}tj|S )	ab  Convert a Content-ID header value to an id.

        Presumes the Content-ID header conforms to the format that _id_to_header()
        returns.

        Args:
          header: string, Content-ID header value.

        Returns:
          The extracted id value.

        Raises:
          BatchError if the header is not in the expected format.
        r   <r   >z Invalid value for Content-ID: %s+r5   z + )r	   r   r   r  unquote)rc   headerbaser4  r   r   r   _header_to_id  s   zBatchHttpRequest._header_to_idc                 C   s*  t j|j}t jdd|j|j|jdf}|jd | d }|j	
ddd\}}t||}|j	 }|jdurJt|j}	|	durJt|	| d|v rQ|d= | D ]\}
}|||
< qU|j|d< |d |jdur|||j tt|j|d	< t }t|d
d}|j|dd | }|| S )zConvert an HttpRequest object into a string.

        Args:
          request: HttpRequest, the request to serialize.

        Returns:
          The request as a string in application/http format.
        r    z
 HTTP/1.1
r   zapplication/jsonr   NHostr   r   )maxheaderlenFunixfrom)r   r  r  rN   r  r  r  r  rO   r   rF   r   r   r   rI   r   r*  r-  r   r  set_unixfromr   set_payloadr   r+   r   StringIOr   flattengetvalue)rc   r>   r	  request_linestatus_linemajorminormsgr   credentialskeyvaluefpgr   r   r   r   _serialize_request)  s8   







z#BatchHttpRequest._serialize_requestc           
      C   s   | dd\}}| dd\}}}t }|| | }||d< t|}||_t| ddd dd|_	| d	dd }	||	fS )
zConvert string into httplib2 response and content.

        Args:
          payload: string, headers and body as a string.

        Returns:
          A pair (resp, content), such as would be returned from httplib2.request.
        
r5   r=  r6   r   r   r   r   z

)
r   r   feedr   rG   Responser   r   replaceversion)
rc   payloadrH  protocolr   r   parserrK  rR   r2   r   r   r   _deserialize_responseY  s   


z&BatchHttpRequest._deserialize_responsec                 C   sF   |  j d7  _ t| j | jv r|  j d7  _ t| j | jv st| j S )zCreate a new id.

        Auto incrementing number that avoids conflicts with ids already used.

        Returns:
           string, a new unique id.
        r5   )r%  r   r"  ri   r   r   r   _new_idu  s
   
zBatchHttpRequest._new_idr6   c                 C   sv   t | jtkrtdt |du r|  }|jdurtd|| jv r)td| || j|< || j|< | j	| dS )a9  Add a new request.

        Every callback added will be paired with a unique id, the request_id. That
        unique id will be passed back to the callback when the response comes back
        from the server. The default behavior is to have the library generate it's
        own unique id. If the caller passes in a request_id then they must ensure
        uniqueness for each request_id, and if they are not an exception is
        raised. Callers should either supply all request_ids or never supply a
        request id, to avoid such an error.

        Args:
          request: HttpRequest, Request to add to the batch.
          callback: callable, A callback to be called for this response, of the
            form callback(id, response, exception). The first parameter is the
            request id, and the second is the deserialized response object. The
            third is an googleapiclient.errors.HttpError exception object if an HTTP error
            occurred while processing the request, or None if no errors occurred.
          request_id: string, A unique id for the request. The id will be passed
            to the callback with the response.

        Returns:
          None

        Raises:
          BatchError if a media request is added to a batch.
          KeyError is the request_id is not unique.
        z9Exceeded the maximum calls(%d) in a single batch request.Nz1Media requests cannot be used in a batch request.z)A request with this ID already exists: %s)
r+   r$  MAX_BATCH_LIMITr	   r[  r   r"  r.   r#  r  )rc   r>   r
  
request_idr   r   r   add  s   



zBatchHttpRequest.addc                 C   sx  t d}t|ddd  |D ]%}|| }tdd}d|d< | ||d	< | |}|| || qt }	t	|	d
d}
|
j
|d
d |	 }i }d|  |d< |j| jd||d\}}|jdkrlt||| jdd|d  }|d}|| }t }|| | }| std||d| D ]#}| |d	 }| | \}}t|tr|d}||f| j|< qdS )a  Serialize batch request, send to server, process response.

        Args:
          http: httplib2.Http, an http object to be used to make the request with.
          order: list, list of request ids in the order they were added to the
            batch.
          requests: list, list of request objects to send.

        Raises:
          httplib2.HttpLib2Error if a transport error has occurred.
          googleapiclient.errors.BatchError if the response is the wrong format.
        mixed_write_headersc                 S      d S r   r   ri   r   r   r   <lambda>  s    z+BatchHttpRequest._execute.<locals>.<lambda>applicationrI   binaryzContent-Transfer-Encodingz
Content-IDF)mangle_from_r@  zmultipart/mixed; boundary="%s"r   r   r   r   r   zcontent-type: %s

r   z'Response not in multipart/mixed format.)rR   r2   N)r   setattrr   r5  rQ  rC  attachr   rD  r   rE  rF  get_boundaryr>   r   r   r
   r&   r   rS  r   is_multipartr	   get_payloadr<  rZ  r'   r   encoder'  )rc   rI   orderrequestsr   r]  r>   rK  r   rO  rP  r   rR   r2   r:  
for_parserrY  mime_responsepartresponser   r   r   _execute  sP   









zBatchHttpRequest._executec                 C   s  t | jdkr	dS |du r!| jD ]}| j| }|dur |j} nq|du r)tdt|}|durAt|sAt	d t
| | || j| j i }g }| jD ]#}| j| \}}|d dkrt|| | j| }| || |||< qQ|r~| ||| | jD ]W}| j| \}}| j| }| j| }	d}
d}z|jdkrt|||jd|||}
W n ty } z|}W Y d}~nd}~ww |	dur|	||
| | jdur| ||
| qdS )	a  Execute all the requests as a single batched HTTP request.

        Args:
          http: httplib2.Http, an http object to be used in place of the one the
            HttpRequest request object was constructed with. If one isn't supplied
            then use a http object from the requests in this batch.

        Returns:
          None

        Raises:
          httplib2.HttpLib2Error if a transport error has occurred.
          googleapiclient.errors.BatchError if the response is the wrong format.
        r   NzMissing a valid http object.z1Attempting refresh to obtain initial access_tokenr   401r   r   )r+   r$  r"  rI   r-   r   r*  is_validr/   infor,  rr  r'  r  r0  r#  r   r
   rN   r   r!  )rc   rI   r]  r>   r.  redo_requests
redo_orderrR   r2   r
  rq  rS   er   r   r   r    sb   













zBatchHttpRequest.executeNNr   )rm   rn   ro   rp   r   r   rd   r0  r5  r<  rQ  rZ  r[  r^  rr  r  r   r   r   r   r    s     20,Hr  c                   @   s"   e Zd ZdZdd ZdddZdS )HttpRequestMockzYMock of HttpRequest.

    Do not construct directly, instead use RequestMockBuilder.
    c                 C   sL   || _ || _|| _|du rtddd| _ d| j v r$| j d | j _dS dS )aY  Constructor for HttpRequestMock

        Args:
          resp: httplib2.Response, the response to emulate coming from the request
          content: string, the response body
          postproc: callable, the post processing function usually supplied by
                    the model class. See model.JsonModel.response() as an example.
        Nr   OK)r   r   r   )rR   r2   r   rG   rT  r   )rc   rR   r2   r   r   r   r   rd   O  s   	
zHttpRequestMock.__init__Nc                 C   s   |  | j| jS )zExecute the request.

        Same behavior as HttpRequest.execute(), but the response is
        mocked and not really from an HTTP request/response.
        )r   rR   r2   )rc   rI   r   r   r   r  `  s   zHttpRequestMock.executer   )rm   rn   ro   rp   rd   r  r   r   r   r   rz  I  s    rz  c                   @   s.   e Zd ZdZd	ddZ					d
ddZdS )RequestMockBuildera  A simple mock of HttpRequest

    Pass in a dictionary to the constructor that maps request methodIds to
    tuples of (httplib2.Response, content, opt_expected_body) that should be
    returned when that method is called. None may also be passed in for the
    httplib2.Response, in which case a 200 OK response will be generated.
    If an opt_expected_body (str or dict) is provided, it will be compared to
    the body and UnexpectedBodyError will be raised on inequality.

    Example:
      response = '{"data": {"id": "tag:google.c...'
      requestBuilder = RequestMockBuilder(
        {
          'plus.activities.get': (None, response),
        }
      )
      googleapiclient.discovery.build("plus", "v1", requestBuilder=requestBuilder)

    Methods that you do not supply a response for will return a
    200 OK with an empty string as the response content or raise an excpetion
    if check_unexpected is set to True. The methodId is taken from the rpcName
    in the discovery document.

    For more details see the project wiki.
    Fc                 C   r^   )a  Constructor for RequestMockBuilder

        The constructed object should be a callable object
        that can replace the class HttpResponse.

        responses - A dictionary that maps methodIds into tuples
                    of (httplib2.Response, content). The methodId
                    comes from the 'rpcName' field in the discovery
                    document.
        check_unexpected - A boolean setting whether or not UnexpectedMethodError
                           should be raised on unsupplied method.
        N)	responsescheck_unexpected)rc   r}  r~  r   r   r   rd     s   
zRequestMockBuilder.__init__r   Nc	                 C   s   || j v rG| j | }	|	dd \}
}t|	dkrA|	d }t|t|kr)t||t|tr3t|}t|}||krAt||t|
||S | j	rOt
|dtd}tdd|jS )a  Implements the callable interface that discovery.build() expects
        of requestBuilder, which is to build an object compatible with
        HttpRequest.execute(). See that method for the description of the
        parameters and the expected response.
        Nr6   )r   Fz{})r}  r+   boolr   r'   r   r$   r%   rz  r~  r   r   rq  )rc   rI   r   rN   rO   r   r   r   r   rq  rR   r2   expected_bodymodelr   r   r   __call__  s"   







zRequestMockBuilder.__call__)Fr  )rm   rn   ro   rp   rd   r  r   r   r   r   r|  i  s    
r|  c                   @   s6   e Zd ZdZdddZ					dddZd	d
 ZdS )HttpMockzMock of httplib2.HttpNc                 C   sx   |du rddi}|r%t |d}| | _W d   n1 sw   Y  nd| _|| _d| _d| _d| _d| _d| _dS )z
        Args:
          filename: string, absolute filename to read response from
          headers: dict, header to return with response
        Nr   200r   )r   r   r   response_headersr   rN   rO   r   )rc   r   r   fr   r   r   rd     s   
zHttpMock.__init__r   r5   c                 C   s*   || _ || _|| _|| _t| j| jfS r   )rN   rO   r   r   rG   rT  r  r   )rc   rN   rO   r   r   redirectionsconnection_typer   r   r   r>     s
   	zHttpMock.requestc                 C   ra  r   r   ri   r   r   r   r     s   zHttpMock.closery  r   NNr5   N)rm   rn   ro   rp   rd   r>   r   r   r   r   r   r    s    

r  c                   @   s,   e Zd ZdZdd Z					d	ddZdS )
HttpMockSequencea  Mock of httplib2.Http

    Mocks a sequence of calls to request returning different responses for each
    call. Create an instance initialized with the desired response headers
    and content and then use as if an httplib2.Http instance.

      http = HttpMockSequence([
        ({'status': '401'}, ''),
        ({'status': '200'}, '{"access_token":"1/3w","expires_in":3600}'),
        ({'status': '200'}, 'echo_request_headers'),
        ])
      resp, content = http.request("http://examples.com")

    There are special values you can pass in for content to trigger
    behavours that are helpful in testing.

    'echo_request_headers' means return the request headers in the response body
    'echo_request_headers_as_json' means return the request headers in
       the response body
    'echo_request_body' means return the request body in the response body
    'echo_request_uri' means return the request uri in the response body
    c                 C   s   || _ d| _t | _dS )z\
        Args:
          iterable: iterable, a sequence of pairs of (headers, body)
        TN)	_iterablefollow_redirectsr*   request_sequence)rc   iterabler   r   r   rd     s   zHttpMockSequence.__init__r   Nr5   c           	      C   s   | j ||||f | jd\}}t|tr|d}|dkr#|}n!|dkr-t|}n|dkr>t	|dr;|
 }n	|}n|dkrD|}t|trN|d}t||fS )Nr   r   s   echo_request_headerss   echo_request_headers_as_jsons   echo_request_bodyr   s   echo_request_uri)r  r  r  popr'   r   rk  r$   r   hasattrr   rG   rT  )	rc   rN   rO   r   r   r  r  rR   r2   r   r   r   r>     s"   






zHttpMockSequence.requestr  )rm   rn   ro   rp   rd   r>   r   r   r   r   r    s    r  c                    s,   | j  dddtjdf fdd	}|| _ | S )a  Set the user-agent on every request.

    Args:
       http - An instance of httplib2.Http
           or something that acts like it.
       user_agent: string, the value for the user-agent header.

    Returns:
       A modified instance of http that was passed in.

    Example:

      h = httplib2.Http()
      h = set_user_agent(h, "my-app-name/6.0")

    Most of the time the user-agent will be set doing auth, this is for the rare
    cases where you are accessing an unauthenticated endpoint.
    r   Nc                    sR   |du ri }d|v rd |d  |d< n|d<  | |||||d\}}||fS )1Modify the request headers to add the user-agent.Nr   r=  rO   r   r   r  r  r   rN   rO   r   r   r  r  rR   r2   request_orig
user_agentr   r   new_request;  s   	
z#set_user_agent.<locals>.new_requestr>   rG   DEFAULT_MAX_REDIRECTS)rI   r  r  r   r  r   set_user_agent%  s   r  c                    s*   | j  dddtjdf fdd	}|| _ | S )a  Tunnel PATCH requests over POST.
    Args:
       http - An instance of httplib2.Http
           or something that acts like it.

    Returns:
       A modified instance of http that was passed in.

    Example:

      h = httplib2.Http()
      h = tunnel_patch(h, "my-app-name/6.0")

    Useful if you are running on a platform that doesn't support PATCH.
    Apply this last if you are using OAuth 1.0, as changing the method
    will result in a different signature.
    r   Nc                    sZ   |du ri }|dkrd| ddv rtd d|d< d} | |||||d	\}}||fS )
r  NPATCHoauth_tokenauthorizationr   z;OAuth 1.0 request made with Credentials after tunnel_patch.r   r   r  )rF   r/   r0   r  r  r   r   r  m  s$   	
z!tunnel_patch.<locals>.new_requestr  )rI   r  r   r  r   tunnel_patchX  s   r  c                  C   sP   t  durt  } nt} tj| d}z
|jdh |_W |S  ty'   Y |S w )a  Builds httplib2.Http object

    Returns:
    A httplib2.Http object, which is used to make http requests, and which has timeout set by default.
    To override default timeout call

      socket.setdefaulttimeout(timeout_in_sec)

    before interacting with this method.
    N)rA   r  )r@   getdefaulttimeoutDEFAULT_HTTP_TIMEOUT_SECrG   Httpredirect_codesAttributeError)http_timeoutrI   r   r   r   
build_http  s   
r  )Irp   
__future__r   
__author__r   http.clientclientr"   r   r$   loggingr   r   r   r@   r   r   r1  rG   sslImportErrorobjectr?   SSLErroremail.generatorr   email.mime.multipartr   email.mime.nonmultipartr   email.parserr   googleapiclientr   r   r   googleapiclient.errorsr	   r
   r   r   r   r   googleapiclient.modelr   	getLoggerrm   r/   r   r   r\  r!   r  r  r4   r[   r]   rq   rr   r   r   r   r   r   r   r  rz  r|  r  r  r  r  r  r   r   r   r   <module>   s|   
 
FR |M#w(  X   ? R*@35