o
    Mf6                     @   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 )a\  Batch updates / deletes of storage buckets / blobs.

A batch request is a single standard HTTP request containing multiple Cloud Storage JSON API calls.
Within this main HTTP request, there are multiple parts which each contain a nested HTTP request.
The body of each part is itself a complete HTTP request, with its own verb, URL, headers, and body.

Note that Cloud Storage does not support batch operations for uploading or downloading.
Additionally, the current batch design does not support library methods whose return values
depend on the response payload. See more details in the [Sending Batch Requests official guide](https://cloud.google.com/storage/docs/batch).

Examples of situations when you might want to use the Batch module:
``blob.patch()``
``blob.update()``
``blob.delete()``
``bucket.delete_blob()``
``bucket.patch()``
``bucket.update()``
    )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 rd}| 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/analyze/labelStudio/lib/python3.10/site-packages/google/cloud/storage/batch.py
<listcomp>K   s    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    C   s   




zMIMEApplicationHTTP.__init__)__name__
__module____qualname____doc__r    __classcell__r   r   r(   r   r   0   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)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 futureKeyError)r   defaultr   r   r   getX   s   z_FutureDict.getc                 C   s   t d|d)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 futurer0   )r!   r   r   r   r   __getitem__g   s   	z_FutureDict.__getitem__c                 C   s   t d|d|d)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 futurer0   )r!   r   r   r   r   r   __setitem__r   s   z_FutureDict.__setitem__N)r*   r+   r,   r-   staticmethodr3   r4   r5   r   r   r   r   r/   R   s    r/   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!   future_dictr(   r   r   r       s   
z_FutureResponse.__init__c                 C      | j S r6   r:   r!   r   r   r   r      s   z_FutureResponse.jsonc                 C   r=   r6   r>   r?   r   r   r   content   s   z_FutureResponse.content)	r*   r+   r,   r-   r    r   propertyr@   r.   r   r   r(   r   r8      s    r8   c                       sf   e Zd ZdZdZd fdd	ZefddZdd	 Zdd
dZ	dddZ
dd Zdd Zdd Z  ZS )Batcha  Proxy an underlying connection, batching up change operations.

    .. warning::

        Cloud Storage does not support batch operations for uploading or downloading.
        Additionally, the current batch design does not support library methods whose
        return values depend on the response payload.

    :type client: :class:`google.cloud.storage.client.Client`
    :param client: The client to use for making connections.

    :type raise_exception: bool
    :param raise_exception:
        (Optional) Defaults to True. If True, instead of adding exceptions
        to the list of return responses, the final exception will be raised.
        Note that exceptions are unwrapped after all operations are complete
        in success or failure, and only the last exception is raised.
    i  Tc                    sB   |j j}|j j}tt| j|||d g | _g | _g | _|| _	d S )N)client_infoapi_endpoint)
_connectionAPI_BASE_URL_client_infor   rB   r    	_requests_target_objects
_responses_raise_exception)r!   clientraise_exceptionrD   rC   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r*||_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   rH   _MAX_BATCH_SIZE
ValueErrorr   r/   rI   _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   rH   rO   r   r
   r   attachioStringIOr   flattengetvaluesplitr   _headers)r!   multirT   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 ]0\}}d|j  kr$dk s,n |r,|p*|}q|durEz| |_W q tyD   |j|_Y qw q|durOt	|dS )a  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.

        :type raise_exception: bool
        :param raise_exception:
            (Optional) Defaults to True. If True, instead of adding exceptions
            to the list of return responses, the final exception will be raised.
            Note that exceptions are unwrapped after all operations are complete
            in success or failure, and only the last exception is raised.

        :raises: :class:`ValueError` if no requests have been deferred.
        Nz&Expected a response for every request.   ,  )
r   rI   rO   zipr;   r   rP   r@   r   from_http_response)r!   	responsesrM   exception_argsrS   subresponser   r   r   _finish_futures   s    

zBatch._finish_futuresc                 C   sx   |   \}}}| j d}| jjjd||||d}d|j  kr$dk s*n t|tt	|}| j
||d || _|S )a3  Submit a single `multipart/mixed` request with deferred requests.

        :type raise_exception: bool
        :param raise_exception:
            (Optional) Defaults to True. If True, instead of adding exceptions
            to the list of return responses, the final exception will be raised.
            Note that exceptions are unwrapped after all operations are complete
            in success or failure, and only the last exception is raised.

        :rtype: list of tuples
        :returns: one ``(headers, payload)`` tuple per deferred request.
        z/batch/storage/v1POST)rR   r$   rT   rf   rg   rM   )re   rF   _client_base_connection_make_requestr;   r   ri   list_unpack_batch_responserm   rJ   )r!   rM   r$   r%   rT   rQ   responserj   r   r   r   finish!  s   

zBatch.finishc                 C   s   | j jS )z"Return the topmost batch, or None.)rp   current_batchr?   r   r   r   currentB  s   zBatch.currentc                 C   s   | j |  | S r6   )rp   _push_batchr?   r   r   r   	__enter__F  s   zBatch.__enter__c                 C   sD   z|d u r| j | jd W | j  d S W | j  d S | j  w )Nro   )rv   rK   rp   
_pop_batch)r!   exc_typeexc_valexc_tbr   r   r   __exit__J  s   zBatch.__exit__)T)r*   r+   r,   r-   rN   r    r
   rV   re   rm   rv   rx   rz   r   r.   r   r   r(   r   rB      s    
-

&!rB   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       s   Content-Type: s   
MIME-Version: 1.0

utf-8)r   	_to_bytesr$   r3   r   r@   parsestrdecode)parserru   content_typefaux_messager   r   r   _generate_faux_mime_messageR  s
   r   c                 c   s    t  }t|| }t|jtstd|jD ]K}|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
rW   r      z
Content-IDBATCHzcontentid://)r"   rQ   r   N)r   r   r   _payloadrs   rO   r]   r   r   r^   r3   requestsResponseRequestpreparerequestintr;   r$   updateencode_content)ru   r   messagera   status_linerestrd   statussub_messager'   msg_headers
content_idrl   r   r   r   rt   c  s.   	






rt   )r-   email.encodersr   email.generatorr   email.mime.applicationr   email.mime.multipartr   email.parserr   rY   r   r   google.cloudr   r   google.cloud.storage._httpr	   google.cloud.storage.constantsr
   r   objectr/   r   r8   rB   r   rt   r   r   r   r   <module>   s(   "/ B