a
    !f,                     @   s   d 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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 G dd deZG dd deZG dd dejZG dd deZdd Zdd ZdS )zyBatch updates / deletes of storage buckets / blobs.

See https://cloud.google.com/storage/docs/json_api/v1/how-tos/batch
    )encode_noop)	Generator)MIMEApplication)MIMEMultipart)ParserN)_helpers)
exceptions)
Connection)_DEFAULT_TIMEOUTc                       s    e Zd ZdZ fddZ  ZS )MIMEApplicationHTTPa?  MIME type for ``application/http``.

    Constructs payload from headers and body

    :type method: str
    :param method: HTTP method

    :type uri: str
    :param uri: URI for HTTP request

    :type headers:  dict
    :param headers: HTTP headers

    :type body: str
    :param body: (Optional) HTTP payload

    c                    s   t |tr(t|}d|d< t||d< |d u r4d}| d| dg}|dd t| D  |d || d		|}t
 |d
t d S )Nzapplication/jsonzContent-TypezContent-Length  z	 HTTP/1.1c                 S   s   g | ]\}}| d | qS )z:  ).0keyvaluer   r   [/var/www/html/python-backend/venv/lib/python3.9/site-packages/google/cloud/storage/batch.py
<listcomp>=       z0MIMEApplicationHTTP.__init__.<locals>.<listcomp>z
http)
isinstancedictjsondumpslenextendsorteditemsappendjoinsuper__init__r   )selfmethoduriheadersbodylinespayload	__class__r   r   r!   5   s    




zMIMEApplicationHTTP.__init__)__name__
__module____qualname____doc__r!   __classcell__r   r   r)   r   r   "   s   r   c                   @   s.   e Zd ZdZed	ddZdd Zdd ZdS )
_FutureDictzvClass to hold a future value for a deferred request.

    Used by for requests that get sent in a :class:`Batch`.
    Nc                 C   s   t d| d|ddS )a,  Stand-in for dict.get.

        :type key: object
        :param key: Hashable dictionary key.

        :type default: object
        :param default: Fallback value to dict.get.

        :raises: :class:`KeyError` always since the future is intended to fail
                 as a dictionary.
        zCannot get(z
, default=z) on a futureNKeyError)r   defaultr   r   r   getJ   s    z_FutureDict.getc                 C   s   t d|ddS )zStand-in for dict[key].

        :type key: object
        :param key: Hashable dictionary key.

        :raises: :class:`KeyError` always since the future is intended to fail
                 as a dictionary.
        zCannot get item z from a futureNr1   )r"   r   r   r   r   __getitem__Y   s    	z_FutureDict.__getitem__c                 C   s   t d|d|ddS )a'  Stand-in for dict[key] = value.

        :type key: object
        :param key: Hashable dictionary key.

        :type value: object
        :param value: Dictionary value.

        :raises: :class:`KeyError` always since the future is intended to fail
                 as a dictionary.
        zCannot set z -> z on a futureNr1   )r"   r   r   r   r   r   __setitem__d   s    z_FutureDict.__setitem__)N)r+   r,   r-   r.   staticmethodr4   r5   r6   r   r   r   r   r0   D   s
   r0   c                       s4   e Zd ZdZ fddZdd Zedd Z  ZS )_FutureResponsezEReponse that returns a placeholder dictionary for a batched requests.c                    s   t t|   || _d| _d S )N   )r    r8   r!   _future_dictstatus_code)r"   Zfuture_dictr)   r   r   r!   v   s    z_FutureResponse.__init__c                 C   s   | j S Nr:   r"   r   r   r   r   {   s    z_FutureResponse.jsonc                 C   s   | j S r<   r=   r>   r   r   r   content~   s    z_FutureResponse.content)	r+   r,   r-   r.   r!   r   propertyr?   r/   r   r   r)   r   r8   s   s
   r8   c                       s`   e Zd ZdZdZ fddZefddZdd Zd	d
 Z	dd Z
dd Zdd Zdd Z  ZS )BatchzProxy an underlying connection, batching up change operations.

    :type client: :class:`google.cloud.storage.client.Client`
    :param client: The client to use for making connections.
    i  c                    s6   |j j}|j j}tt| j|||d g | _g | _d S )N)client_infoapi_endpoint)_connectionAPI_BASE_URLZ_client_infor    rA   r!   	_requests_target_objects)r"   clientrC   rB   r)   r   r   r!      s    
zBatch.__init__c                 C   s\   t | j| jkrtd| j | j|||||f t }| j| |durT||_t|S )au  Override Connection:  defer actual HTTP request.

        Only allow up to ``_MAX_BATCH_SIZE`` requests to be deferred.

        :type method: str
        :param method: The HTTP method to use in the request.

        :type url: str
        :param url: The URL to send the request to.

        :type headers: dict
        :param headers: A dictionary of HTTP headers to send with the request.

        :type data: str
        :param data: The data to send as the body of the request.

        :type target_object: object
        :param target_object:
            (Optional) This allows us to enable custom behavior in our batch
            connection. Here we defer an HTTP request and complete
            initialization of the object at a later time.

        :type timeout: float or tuple
        :param timeout:
            (Optional) The amount of time, in seconds, to wait
            for the server response.  See: :ref:`configuring_timeouts`

        :rtype: tuple of ``response`` (a dictionary of sorts)
                and ``content`` (a string).
        :returns: The HTTP response object and the content of the response.
        z#Too many deferred requests (max %d)N)	r   rF   _MAX_BATCH_SIZE
ValueErrorr   r0   rG   _propertiesr8   )r"   r#   urlr%   datatarget_objecttimeoutresultr   r   r   _do_request   s    "zBatch._do_requestc                 C   s   t | jdkrtdt }t}| jD ]*\}}}}}t||||}|| |}q&t }	t	|	dd}
|

| |	 }|dd\}}t|j||fS )zPrepares headers and body for a batch request.

        :rtype: tuple (dict, str)
        :returns: The pair of headers and body of the batch request to be sent.
        :raises: :class:`ValueError` if no requests have been deferred.
        r   zNo deferred requestsFz

   )r   rF   rJ   r   r
   r   attachioStringIOr   flattengetvaluesplitr   _headers)r"   multirO   r#   r$   r%   r&   _timeout
subrequestbuf	generatorr(   _r   r   r   _prepare_batch_request   s    

zBatch._prepare_batch_requestc              	   C   s   d}t | jt |krtdt| j|D ]\\}}d|j  krHdk sTn |pP|}q*|dur*z| |_W q* ty   |j|_Y q*0 q*|durt	|dS )a6  Apply all the batch responses to the futures created.

        :type responses: list of (headers, payload) tuples.
        :param responses: List of headers and payloads from each response in
                          the batch.

        :raises: :class:`ValueError` if no requests have been deferred.
        Nz&Expected a response for every request.   ,  )
r   rG   rJ   zipr;   r   rK   r?   r   from_http_response)r"   	responsesZexception_argsrN   subresponser   r   r   _finish_futures   s    
zBatch._finish_futuresc                 C   sn   |   \}}}| j d}| jjjd||||d}d|j  krHdk sTn t|tt	|}| 
| |S )zSubmit a single `multipart/mixed` request with deferred requests.

        :rtype: list of tuples
        :returns: one ``(headers, payload)`` tuple per deferred request.
        z/batch/storage/v1POST)rM   r%   rO   ra   rb   )r`   rE   _clientZ_base_connection_make_requestr;   r   rd   list_unpack_batch_responserg   )r"   r%   r&   rO   rL   responsere   r   r   r   finish   s    


zBatch.finishc                 C   s   | j jS )z"Return the topmost batch, or None.)ri   Zcurrent_batchr>   r   r   r   current  s    zBatch.currentc                 C   s   | j |  | S r<   )ri   Z_push_batchr>   r   r   r   	__enter__  s    zBatch.__enter__c                 C   s0   z|d u r|    W | j  n| j  0 d S r<   )rn   ri   Z
_pop_batch)r"   exc_typeexc_valexc_tbr   r   r   __exit__  s    
zBatch.__exit__)r+   r,   r-   r.   rI   r!   r
   rQ   r`   rg   rn   ro   rp   rt   r/   r   r   r)   r   rA      s   

-rA   c                 C   s8   t |jdd}dd|d|jg}| |dS )zdConvert response, content -> (multipart) email.message.

    Helper for _unpack_batch_response.
    zcontent-typer   r   s   Content-Type: s   
MIME-Version: 1.0

utf-8)r   	_to_bytesr%   r4   r   r?   parsestrdecode)parserrm   content_typeZfaux_messager   r   r   _generate_faux_mime_message#  s
    r{   c                 c   s   t  }t|| }t|jts$td|jD ]}|jdd\}}|dd\}}}||}|j}	t|j	}
|

d}t }tjdd| d	 |_t||_|j|
 |	d
|_|V  q*dS )a  Convert requests.Response -> [(headers, payload)].

    Creates a generator of tuples of emulating the responses to
    :meth:`requests.Session.request`.

    :type response: :class:`requests.Response`
    :param response: HTTP response / headers from a request.
    zBad response:  not multi-part
rR   r      z
Content-IDZBATCHzcontentid://)r#   rL   ru   N)r   r{   r   _payloadrk   rJ   rX   rw   r   rY   r4   requestsResponseRequestpreparerequestintr;   r%   updateencode_content)rm   ry   messager\   Zstatus_linerestr_   statusZsub_messager(   Zmsg_headersZ
content_idrf   r   r   r   rl   4  s&    	






rl   )r.   email.encodersr   email.generatorr   Zemail.mime.applicationr   Zemail.mime.multipartr   email.parserr   rT   r   r   Zgoogle.cloudr   r   Zgoogle.cloud.storage._httpr	   Zgoogle.cloud.storage.constantsr
   r   objectr0   r   r8   rA   r{   rl   r   r   r   r   <module>   s&   "/ !