o
    ÔèFh9  ã                   @   s<  d 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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dZdZdZdZdZdZe e¡Zdd„ Zefdd„Zefdd„Zd4d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%d*d+„ Z&d,d-„ Z'd.d/„ Z(d0d1„ Z)G d2d3„ d3e*ƒZ+dS )5z4Shared utilities used by both downloads and uploads.é    )Úabsolute_importN)Úparse_qs)Ú	urlencode)Úurlsplit)Ú
urlunsplit)ÚcommonÚrangezcontent-rangezcontent-encodingz¨Currently using crcmod in pure python form. This is a slow implementation. Python 3 has a faster implementation, `google-crc32c`, which will be used if it is installed.zx-goog-generationzx-goog-hashzx-goog-stored-content-encodingz·No {checksum_type} checksum was returned from the service while downloading {}
(which happens for composite objects), so client-side content integrity
checking is not being performed.c                   C   ó   dS )zSimple default callback.N© r
   r
   r
   úX/var/www/html/loop/nvenv/lib/python3.10/site-packages/google/resumable_media/_helpers.pyÚ
do_nothing5   ó    r   c                 C   s,   || ƒ}||vr|ƒ  t  | d|¡‚|| S )aš  Checks that a specific header is in a headers dictionary.

    Args:
        response (object): An HTTP response object, expected to have a
            ``headers`` attribute that is a ``Mapping[str, str]``.
        name (str): The name of a required header.
        get_headers (Callable[Any, Mapping[str, str]]): Helper to get headers
            from an HTTP response.
        callback (Optional[Callable]): A callback that takes no arguments,
            to be executed when an exception is being raised.

    Returns:
        str: The desired header.

    Raises:
        ~google.resumable_media.common.InvalidResponse: If the header
            is missing.
    z$Response headers must contain header)r   ÚInvalidResponse)ÚresponseÚnameÚget_headersÚcallbackÚheadersr
   r
   r   Úheader_required9   s   ÿr   c                 C   s<   || ƒ}||vr|t jvr|ƒ  t j| d|dg|¢R Ž ‚|S )a`  Require a response has a status code among a list.

    Args:
        response (object): The HTTP response object.
        status_codes (tuple): The acceptable status codes.
        get_status_code (Callable[Any, int]): Helper to get a status code
            from a response.
        callback (Optional[Callable]): A callback that takes no arguments,
            to be executed when an exception is being raised.

    Returns:
        int: The status code.

    Raises:
        ~google.resumable_media.common.InvalidResponse: If the status code
            is not one of the values in ``status_codes``.
    zRequest failed with status codezExpected one of)r   Ú	RETRYABLEr   )r   Ústatus_codesÚget_status_coder   Ústatus_coder
   r
   r   Úrequire_status_codeV   s   
üûr   ç       @c                 C   s0   ||  }||kr
|}t  dd¡}||d|  fS )aú  Calculate the amount of time to wait before a retry attempt.

    Wait time grows exponentially with the number of attempts, until
    ``max_sleep``.

    A random amount of jitter (between 0 and 1 seconds) is added to spread out
    retry attempts from different clients.

    Args:
        base_wait (float): The "base" wait time (i.e. without any jitter)
            that will be multiplied until it reaches the maximum sleep.
        max_sleep (float): Maximum value that a sleep time is allowed to be.
        multiplier (float): Multiplier to apply to the base wait.

    Returns:
        Tuple[float, float]: The new base wait time as well as the wait time
        to be applied (with a random amount of jitter between 0 and 1 seconds
        added).
    r   iè  gü©ñÒMbP?)ÚrandomÚrandint)Ú	base_waitÚ	max_sleepÚ
multiplierÚnew_base_waitÚ	jitter_msr
   r
   r   Úcalculate_retry_waitv   s
   r"   c                  C   s`   zddl } |  ¡ }W |S  ty/   zddl}|j d¡}tƒ  W Y |S  ty.   tdƒ‚w w )zªGet crc32c object
    Attempt to use the Google-CRC32c package. If it isn't available, try
    to use CRCMod. CRCMod might be using a 'slow' varietal. If so, warn...
    r   Nzcrc-32cz3Failed to import either `google-crc32c` or `crcmod`)Úgoogle_crc32cÚChecksumÚImportErrorÚcrcmodÚ
predefinedÚCrcÚ_is_fast_crcmod)r#   Úcrc_objr&   r
   r
   r   Ú_get_crc32c_object’   s   
ö
ýÿùr+   c                  C   s:   t dtƒ tƒ dgdƒ} t| ddƒ}|stjttdd� |S )Nzcrcmod.crcmodÚ_usingExtensionr   Fé   )Ú
stacklevel)Ú
__import__ÚglobalsÚlocalsÚgetattrÚwarningsÚwarnÚ_SLOW_CRC32C_WARNINGÚRuntimeWarning)Únested_crcmodÚfast_crcr
   r
   r   r)   ¨   s   ûr)   c                 C   s   | dkrdS | S )NÚmd5Úmd5Hashr
   ©Úchecksum_typer
   r
   r   Ú_get_metadata_key·   s   r=   c                 C   s   t  | ¡}| d¡S )zÈConvert a checksum object into a digest encoded for an HTTP header.

    Args:
        bytes: A checksum digest bytestring.

    Returns:
        str: A base64 string representation of the input.
    zutf-8)Úbase64Ú	b64encodeÚdecode)Údigest_bytestringÚencoded_digestr
   r
   r   Úprepare_checksum_digest¾   s   
	
rC   c                 C   sž   |dvrt dƒ‚|dv rF|| ƒ}t| t¡| |d�}|du r3tj|| ¡ d�}t |¡ t	ƒ }||fS |dkr?t
 ¡ }||fS tƒ }||fS d}t	ƒ }||fS )aÒ  Get the expected checksum and checksum object for the download response.

    Args:
        response (~requests.Response): The HTTP response object.
        get_headers (callable: response->dict): returns response headers.
        media_url (str): The URL containing the media to be downloaded.
        checksum_type Optional(str): The checksum type to read from the headers,
            exactly as it will appear in the headers (case-sensitive). Must be
            "md5", "crc32c" or None.

    Returns:
        Tuple (Optional[str], object): The expected checksum of the response,
        if it can be detected from the ``X-Goog-Hash`` header, and the
        appropriate checksum object for the expected checksum.
    ©r9   Úcrc32cNú4checksum must be ``'md5'``, ``'crc32c'`` or ``None``©r9   rE   ©Úchecksum_labelNr;   r9   )Ú
ValueErrorÚ_parse_checksum_headerÚgetÚ_HASH_HEADERÚ_MISSING_CHECKSUMÚformatÚupperÚ_LOGGERÚinfoÚ_DoNothingHashÚhashlibr9   r+   )r   r   Ú	media_urlr<   r   Úexpected_checksumÚmsgÚchecksum_objectr
   r
   r   Ú_get_expected_checksumÌ   s,   ÿÿ

øûýrY   c                 C   s@   |dvrt dƒ‚|dv r|| ƒ}t| t¡| |d�}|S d}|S )a�  Get the computed checksum and checksum object from the response headers.

    Args:
        response (~requests.Response): The HTTP response object.
        get_headers (callable: response->dict): returns response headers.
        checksum_type Optional(str): The checksum type to read from the headers,
            exactly as it will appear in the headers (case-sensitive). Must be
            "md5", "crc32c" or None.

    Returns:
        Tuple (Optional[str], object): The checksum of the response,
        if it can be detected from the ``X-Goog-Hash`` header, and the
        appropriate checksum object for the expected checksum.
    rD   rF   rG   rH   N)rJ   rK   rL   rM   )r   r   r<   r   Úremote_checksumr
   r
   r   Ú#_get_uploaded_checksum_from_headersö   s   ÿþr[   c                 C   s€   | du rdS g }|   d¡D ]}|  dd¡\}}| ¡ |kr"| |¡ qt|ƒdkr+dS t|ƒdkr5|d S t |d |¡| |¡‚)aD  Parses the checksum header from an ``X-Goog-Hash`` value.

    .. _header reference: https://cloud.google.com/storage/docs/                          xml-api/reference-headers#xgooghash

    Expects ``header_value`` (if not :data:`None`) to be in one of the three
    following formats:

    * ``crc32c=n03x6A==``
    * ``md5=Ojk9c3dhfxgoKVVHYwFbHQ==``
    * ``crc32c=n03x6A==,md5=Ojk9c3dhfxgoKVVHYwFbHQ==``

    See the `header reference`_ for more information.

    Args:
        header_value (Optional[str]): The ``X-Goog-Hash`` header from
            a download response.
        response (~requests.Response): The HTTP response object.
        checksum_label (str): The label of the header value to read, as in the
            examples above. Typically "md5" or "crc32c"

    Returns:
        Optional[str]: The expected checksum of the response, if it
        can be detected from the ``X-Goog-Hash`` header; otherwise, None.

    Raises:
        ~google.resumable_media.common.InvalidResponse: If there are
            multiple checksums of the requested type in ``header_value``.
    Nú,ú=é   r   z.X-Goog-Hash header had multiple ``{}`` values.)ÚsplitÚlstripÚappendÚlenr   r   rO   )Úheader_valuer   rI   ÚmatchesÚchecksumr   Úvaluer
   r
   r   rK     s$   
€ürK   c                 C   s2   | dkrt  ¡ S | dkrtƒ S | du rdS tdƒ‚)z~Respond with a checksum object for a supported type, if not None.

    Raises ValueError if checksum_type is unsupported.
    r9   rE   NrF   )rT   r9   r+   rJ   r;   r
   r
   r   Ú_get_checksum_objectG  s   rg   c                 C   s(   || ƒ}|  td¡}|du rdS t|ƒS )a�  Parses the generation header from an ``X-Goog-Generation`` value.

    Args:
        response (~requests.Response): The HTTP response object.
        get_headers (callable: response->dict): returns response headers.

    Returns:
        Optional[long]: The object generation from the response, if it
        can be detected from the ``X-Goog-Generation`` header; otherwise, None.
    N)rL   Ú_GENERATION_HEADERÚint)r   r   r   Úobject_generationr
   r
   r   Ú_parse_generation_headerV  s
   rk   c                 C   s>   t | ƒ\}}}}}t|ƒ}| dd¡}|du rdS t|d ƒS )zÿRetrieve the object generation query param specified in the media url.

    Args:
        media_url (str): The URL containing the media to be downloaded.

    Returns:
        long: The object generation from the media url if exists; otherwise, None.
    Ú
generationNr   )r   r   rL   ri   )rU   Ú_ÚqueryÚquery_paramsrj   r
   r
   r   Ú_get_generation_from_urlj  s   
rp   c           	      C   sT   t |ƒdkr| S t| ƒ\}}}}}t|ƒ}i |¥|¥}t|dd�}t|||||fƒS )a  Add query parameters to a base url.

    Args:
        media_url (str): The URL containing the media to be downloaded.
        query_params (dict): Names and values of the query parameters to add.

    Returns:
        str: URL with additional query strings appended.
    r   T)Údoseq)rb   r   r   r   r   )	rU   ro   ÚschemeÚnetlocÚpathrn   ÚfragÚparamsÚ
new_paramsr
   r
   r   Úadd_query_parameters~  s   rx   c                 C   s$   || ƒ}|  t¡dko|  t¡dkS )a  Returns True if the object was served decompressed. This happens when the
    "x-goog-stored-content-encoding" header is "gzip" and "content-encoding" header
    is not "gzip". See more at: https://cloud.google.com/storage/docs/transcoding#transcoding_and_gzip
    Args:
        response (~requests.Response): The HTTP response object.
        get_headers (callable: response->dict): returns response headers.
    Returns:
        bool: Returns True if decompressive transcoding has occurred; otherwise, False.
    Úgzip)rL   Ú_STORED_CONTENT_ENCODING_HEADERÚCONTENT_ENCODING_HEADER)r   r   r   r
   r
   r   Ú_is_decompressive_transcoding“  s   
þr|   c                   @   s   e Zd ZdZdd„ ZdS )rS   z«Do-nothing hash object.

    Intended as a stand-in for ``hashlib.md5`` or a crc32c checksum
    implementation in cases where it isn't necessary to compute the hash.
    c                 C   r	   )z¹Do-nothing ``update`` method.

        Intended to match the interface of ``hashlib.md5`` and other checksums.

        Args:
            unused_chunk (bytes): A chunk of data.
        Nr
   )ÚselfÚunused_chunkr
   r
   r   Úupdate«  r   z_DoNothingHash.updateN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r
   r
   r
   r   rS   ¤  s    rS   )r   ),rƒ   Ú
__future__r   r>   rT   Úloggingr   r3   Úurllib.parser   r   r   r   Úgoogle.resumable_mediar   ÚRANGE_HEADERÚCONTENT_RANGE_HEADERr{   r5   rh   rM   rz   rN   Ú	getLoggerr€   rQ   r   r   r   r"   r+   r)   r=   rC   rY   r[   rK   rg   rk   rp   rx   r|   ÚobjectrS   r
   r
   r
   r   Ú<module>   sN   ÿ

 *5