a
    !f                     @   sL  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 ed dZdZd	Zd
Zi Zdd ZedddddeefddZeddddeefddZeddddddddeef
ddZedddddddeef	ddZeddeefddZdd Zdd Zdd Zd d! Zd"d# ZG d$d% d%ZdS )&zGConcurrent media operations. This is a PREVIEW FEATURE: API may change.    N)
exceptions)Client)BlobzThe module `transfer_manager` is a preview feature. Functionality and API may change. This warning will be removed in a future release.i      processthreadc                    s    fdd}|S )Nc                     s   t  j| i |}|jd}|r|jd}|jd}|sF|rNtdtd |j} |j	}t
|d< ||d<  | i |S  | i |S d S )Nthreadsworker_typemax_workerszuThe `threads` parameter is deprecated and conflicts with its replacement parameters, `worker_type` and `max_workers`.zeThe `threads` parameter is deprecated. Please use `worker_type` and `max_workers` parameters instead.)inspect	signaturebind	argumentsget
ValueErrorwarningswarnargskwargsTHREAD)r   r   Zbindingr   r	   r
   func f/var/www/html/python-backend/venv/lib/python3.9/site-packages/google/cloud/storage/transfer_manager.pyconvert_threads_or_raise1   s$    z:_deprecate_threads_param.<locals>.convert_threads_or_raiser   )r   r   r   r   r   _deprecate_threads_param0   s    r   Fc              
   C   s.  |du ri }|r |  }d|d< t|\}}	||d}
g }| D ]V\}}|	r^t|ts^td||
jt|	rtt|n|t|trdnd|fi | q@t	j
j||t	j
jd W d   n1 s0    Y  g }|D ]T}| }|r|s|| q|r|rt|tjr|| q||  q|S )	ax  Upload many files concurrently via a worker pool.

    This function is a PREVIEW FEATURE: the API may change in a future version.

    :type file_blob_pairs: List(Tuple(IOBase or str, 'google.cloud.storage.blob.Blob'))
    :param file_blob_pairs:
        A list of tuples of a file or filename and a blob. Each file will be
        uploaded to the corresponding blob by using blob.upload_from_file() or
        blob.upload_from_filename() as appropriate.

        File handlers are only supported if worker_type is set to THREAD.
        If worker_type is set to PROCESS, please use filenames only.

    :type skip_if_exists: bool
    :param skip_if_exists:
        If True, blobs that already have a live version will not be overwritten.
        This is accomplished by setting "if_generation_match = 0" on uploads.
        Uploads so skipped will result in a 412 Precondition Failed response
        code, which will be included in the return value but not raised
        as an exception regardless of the value of raise_exception.

    :type upload_kwargs: dict
    :param upload_kwargs:
        A dictionary of keyword arguments to pass to the upload method. Refer
        to the documentation for blob.upload_from_file() or
        blob.upload_from_filename() for more information. The dict is directly
        passed into the upload methods and is not validated by this function.

    :type threads: int
    :param threads:
        ***DEPRECATED*** Sets `worker_type` to THREAD and `max_workers` to the
        number specified. If `worker_type` or `max_workers` are set explicitly,
        this parameter should be set to None. Please use `worker_type` and
        `max_workers` instead of this parameter.

    :type deadline: int
    :param deadline:
        The number of seconds to wait for all threads to resolve. If the
        deadline is reached, all threads will be terminated regardless of their
        progress and concurrent.futures.TimeoutError will be raised. This can be
        left as the default of None (no deadline) for most use cases.

    :type raise_exception: bool
    :param raise_exception:
        If True, instead of adding exceptions to the list of return values,
        instead they will be raised. Note that encountering an exception on one
        operation will not prevent other operations from starting. Exceptions
        are only processed and potentially raised after all operations are
        complete in success or failure.

        If skip_if_exists is True, 412 Precondition Failed responses are
        considered part of normal operation and are not raised as an exception.

    :type worker_type: str
    :param worker_type:
        The worker type to use; one of google.cloud.storage.transfer_manager.PROCESS
        or google.cloud.storage.transfer_manager.THREAD.

        Although the exact performance impact depends on the use case, in most
        situations the PROCESS worker type will use more system resources (both
        memory and CPU) and result in faster operations than THREAD workers.

        Because the subprocesses of the PROCESS worker type can't access memory
        from the main process, Client objects have to be serialized and then
        recreated in each subprocess. The serialization of the Client object
        for use in subprocesses is an approximation and may not capture every
        detail of the Client object, especially if the Client was modified after
        its initial creation or if `Client._http` was modified in any way.

        THREAD worker types are observed to be relatively efficient for
        operations with many small files, but not for operations with large
        files. PROCESS workers are recommended for large file operations.

        PROCESS workers do not support writing to file handlers. Please refer
        to files by filename only when using PROCESS workers.

    :type max_workers: int
    :param max_workers:
        The maximum number of workers to create to handle the workload.

        With PROCESS workers, a larger number of workers will consume more
        system resources (memory and CPU) at once.

        How many workers is optimal depends heavily on the specific use case,
        and the default is a conservative number that should work okay in most
        cases without consuming excessive resources.

    :raises: :exc:`concurrent.futures.TimeoutError` if deadline is exceeded.

    :rtype: list
    :returns: A list of results corresponding to, in order, each item in the
        input list. If an exception was received, it will be the result
        for that operation. Otherwise, the return value from the successful
        upload method is used (typically, None).
    Nr   Zif_generation_matchr
   Passing in a file object is only supported by the THREAD worker type. Please either select THREAD workers, or pass in filenames only.Zupload_from_filenameZupload_from_filetimeoutreturn_when)copy _get_pool_class_and_requirements
isinstancestrr   appendsubmit"_call_method_on_maybe_pickled_blob_pickle_blob
concurrentfutureswaitALL_COMPLETED	exceptionr   ZPreconditionFailedresult)file_blob_pairsskip_if_existsupload_kwargsr   deadlineraise_exceptionr	   r
   
pool_classneeds_picklingexecutorr*   path_or_fileblobresultsfutureexpr   r   r   upload_manyJ   sJ    j
$r<   c              
   C   s   |du ri }t |\}}||d}	g }
| D ]V\}}|rJt|tsJtd|
|	jt|r`t|n|t|trpdnd|fi | q,tj	j
|
|tj	jd W d   n1 s0    Y  g }|
D ].}|s| }|r|| q||  q|S )a  Download many blobs concurrently via a worker pool.

    This function is a PREVIEW FEATURE: the API may change in a future version.

    :type blob_file_pairs: List(Tuple('google.cloud.storage.blob.Blob', IOBase or str))
    :param blob_file_pairs:
        A list of tuples of blob and a file or filename. Each blob will be
        downloaded to the corresponding blob by using blob.download_to_file() or
        blob.download_to_filename() as appropriate.

        Note that blob.download_to_filename() does not delete the destination
        file if the download fails.

        File handlers are only supported if worker_type is set to THREAD.
        If worker_type is set to PROCESS, please use filenames only.

    :type download_kwargs: dict
    :param download_kwargs:
        A dictionary of keyword arguments to pass to the download method. Refer
        to the documentation for blob.download_to_file() or
        blob.download_to_filename() for more information. The dict is directly
        passed into the download methods and is not validated by this function.

    :type threads: int
    :param threads:
        ***DEPRECATED*** Sets `worker_type` to THREAD and `max_workers` to the
        number specified. If `worker_type` or `max_workers` are set explicitly,
        this parameter should be set to None. Please use `worker_type` and
        `max_workers` instead of this parameter.

    :type deadline: int
    :param deadline:
        The number of seconds to wait for all threads to resolve. If the
        deadline is reached, all threads will be terminated regardless of their
        progress and concurrent.futures.TimeoutError will be raised. This can be
        left as the default of None (no deadline) for most use cases.

    :type raise_exception: bool
    :param raise_exception:
        If True, instead of adding exceptions to the list of return values,
        instead they will be raised. Note that encountering an exception on one
        operation will not prevent other operations from starting. Exceptions
        are only processed and potentially raised after all operations are
        complete in success or failure.

    :type worker_type: str
    :param worker_type:
        The worker type to use; one of google.cloud.storage.transfer_manager.PROCESS
        or google.cloud.storage.transfer_manager.THREAD.

        Although the exact performance impact depends on the use case, in most
        situations the PROCESS worker type will use more system resources (both
        memory and CPU) and result in faster operations than THREAD workers.

        Because the subprocesses of the PROCESS worker type can't access memory
        from the main process, Client objects have to be serialized and then
        recreated in each subprocess. The serialization of the Client object
        for use in subprocesses is an approximation and may not capture every
        detail of the Client object, especially if the Client was modified after
        its initial creation or if `Client._http` was modified in any way.

        THREAD worker types are observed to be relatively efficient for
        operations with many small files, but not for operations with large
        files. PROCESS workers are recommended for large file operations.

        PROCESS workers do not support writing to file handlers. Please refer
        to files by filename only when using PROCESS workers.

    :type max_workers: int
    :param max_workers:
        The maximum number of workers to create to handle the workload.

        With PROCESS workers, a larger number of workers will consume more
        system resources (memory and CPU) at once.

        How many workers is optimal depends heavily on the specific use case,
        and the default is a conservative number that should work okay in most
        cases without consuming excessive resources.

    :raises: :exc:`concurrent.futures.TimeoutError` if deadline is exceeded.

    :rtype: list
    :returns: A list of results corresponding to, in order, each item in the
        input list. If an exception was received, it will be the result
        for that operation. Otherwise, the return value from the successful
        download method is used (typically, None).
    Nr   r   Zdownload_to_filenamedownload_to_filer   )r"   r#   r$   r   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   )blob_file_pairsdownload_kwargsr   r2   r3   r	   r
   r4   r5   r6   r*   r8   r7   r9   r:   r;   r   r   r   download_many   sD    b
$
r@    c              	   C   sf   |du ri }g }|D ]:}t j||}|| }| j|fi |}|||f qt|||||	|
|dS )aV  Upload many files concurrently by their filenames.

    This function is a PREVIEW FEATURE: the API may change in a future version.

    The destination blobs are automatically created, with blob names based on
    the source filenames and the blob_name_prefix.

    For example, if the `filenames` include "images/icon.jpg",
    `source_directory` is "/home/myuser/", and `blob_name_prefix` is "myfiles/",
    then the file at "/home/myuser/images/icon.jpg" will be uploaded to a blob
    named "myfiles/images/icon.jpg".

    :type bucket: 'google.cloud.storage.bucket.Bucket'
    :param bucket:
        The bucket which will contain the uploaded blobs.

    :type filenames: list(str)
    :param filenames:
        A list of filenames to be uploaded. This may include part of the path.
        The full path to the file must be source_directory + filename.

    :type source_directory: str
    :param source_directory:
        A string that will be prepended (with os.path.join()) to each filename
        in the input list, in order to find the source file for each blob.
        Unlike the filename itself, the source_directory does not affect the
        name of the uploaded blob.

        For instance, if the source_directory is "/tmp/img/" and a filename is
        "0001.jpg", with an empty blob_name_prefix, then the file uploaded will
        be "/tmp/img/0001.jpg" and the destination blob will be "0001.jpg".

        This parameter can be an empty string.

        Note that this parameter allows directory traversal (e.g. "/", "../")
        and is not intended for unsanitized end user input.

    :type blob_name_prefix: str
    :param blob_name_prefix:
        A string that will be prepended to each filename in the input list, in
        order to determine the name of the destination blob. Unlike the filename
        itself, the prefix string does not affect the location the library will
        look for the source data on the local filesystem.

        For instance, if the source_directory is "/tmp/img/", the
        blob_name_prefix is "myuser/mystuff-" and a filename is "0001.jpg" then
        the file uploaded will be "/tmp/img/0001.jpg" and the destination blob
        will be "myuser/mystuff-0001.jpg".

        The blob_name_prefix can be blank (an empty string).

    :type skip_if_exists: bool
    :param skip_if_exists:
        If True, blobs that already have a live version will not be overwritten.
        This is accomplished by setting "if_generation_match = 0" on uploads.
        Uploads so skipped will result in a 412 Precondition Failed response
        code, which will be included in the return value, but not raised
        as an exception regardless of the value of raise_exception.

    :type blob_constructor_kwargs: dict
    :param blob_constructor_kwargs:
        A dictionary of keyword arguments to pass to the blob constructor. Refer
        to the documentation for blob.Blob() for more information. The dict is
        directly passed into the constructor and is not validated by this
        function. `name` and `bucket` keyword arguments are reserved by this
        function and will result in an error if passed in here.

    :type upload_kwargs: dict
    :param upload_kwargs:
        A dictionary of keyword arguments to pass to the upload method. Refer
        to the documentation for blob.upload_from_file() or
        blob.upload_from_filename() for more information. The dict is directly
        passed into the upload methods and is not validated by this function.

    :type threads: int
    :param threads:
        ***DEPRECATED*** Sets `worker_type` to THREAD and `max_workers` to the
        number specified. If `worker_type` or `max_workers` are set explicitly,
        this parameter should be set to None. Please use `worker_type` and
        `max_workers` instead of this parameter.

    :type deadline: int
    :param deadline:
        The number of seconds to wait for all threads to resolve. If the
        deadline is reached, all threads will be terminated regardless of their
        progress and concurrent.futures.TimeoutError will be raised. This can be
        left as the default of None (no deadline) for most use cases.

    :type raise_exception: bool
    :param raise_exception:
        If True, instead of adding exceptions to the list of return values,
        instead they will be raised. Note that encountering an exception on one
        operation will not prevent other operations from starting. Exceptions
        are only processed and potentially raised after all operations are
        complete in success or failure.

        If skip_if_exists is True, 412 Precondition Failed responses are
        considered part of normal operation and are not raised as an exception.

    :type worker_type: str
    :param worker_type:
        The worker type to use; one of google.cloud.storage.transfer_manager.PROCESS
        or google.cloud.storage.transfer_manager.THREAD.

        Although the exact performance impact depends on the use case, in most
        situations the PROCESS worker type will use more system resources (both
        memory and CPU) and result in faster operations than THREAD workers.

        Because the subprocesses of the PROCESS worker type can't access memory
        from the main process, Client objects have to be serialized and then
        recreated in each subprocess. The serialization of the Client object
        for use in subprocesses is an approximation and may not capture every
        detail of the Client object, especially if the Client was modified after
        its initial creation or if `Client._http` was modified in any way.

        THREAD worker types are observed to be relatively efficient for
        operations with many small files, but not for operations with large
        files. PROCESS workers are recommended for large file operations.

    :type max_workers: int
    :param max_workers:
        The maximum number of workers to create to handle the workload.

        With PROCESS workers, a larger number of workers will consume more
        system resources (memory and CPU) at once.

        How many workers is optimal depends heavily on the specific use case,
        and the default is a conservative number that should work okay in most
        cases without consuming excessive resources.

    :raises: :exc:`concurrent.futures.TimeoutError` if deadline is exceeded.

    :rtype: list
    :returns: A list of results corresponding to, in order, each item in the
        input list. If an exception was received, it will be the result
        for that operation. Otherwise, the return value from the successful
        upload method is used (typically, None).
    N)r0   r1   r2   r3   r	   r
   )ospathjoinr8   r%   r<   )bucket	filenamesZsource_directoryblob_name_prefixr0   Zblob_constructor_kwargsr1   r   r2   r3   r	   r
   r/   filenamerC   	blob_namer8   r   r   r   upload_many_from_filenamess  s$     rJ   Tc                 C   sn   g }|D ]P}|| }t j||}|rDt j|\}}t j|dd || ||f qt|||||	|
dS )a  Download many files concurrently by their blob names.

    This function is a PREVIEW FEATURE: the API may change in a future version.

    The destination files are automatically created, with paths based on the
    source blob_names and the destination_directory.

    The destination files are not automatically deleted if their downloads fail,
    so please check the return value of this function for any exceptions, or
    enable `raise_exception=True`, and process the files accordingly.

    For example, if the `blob_names` include "icon.jpg", `destination_directory`
    is "/home/myuser/", and `blob_name_prefix` is "images/", then the blob named
    "images/icon.jpg" will be downloaded to a file named
    "/home/myuser/icon.jpg".

    :type bucket: 'google.cloud.storage.bucket.Bucket'
    :param bucket:
        The bucket which contains the blobs to be downloaded

    :type blob_names: list(str)
    :param blob_names:
        A list of blobs to be downloaded. The blob name in this string will be
        used to determine the destination file path as well.

        The full name to the blob must be blob_name_prefix + blob_name. The
        blob_name is separate from the blob_name_prefix because the blob_name
        will also determine the name of the destination blob. Any shared part of
        the blob names that need not be part of the destination path should be
        included in the blob_name_prefix.

    :type destination_directory: str
    :param destination_directory:
        A string that will be prepended (with os.path.join()) to each blob_name
        in the input list, in order to determine the destination path for that
        blob.

        For instance, if the destination_directory string is "/tmp/img" and a
        blob_name is "0001.jpg", with an empty blob_name_prefix, then the source
        blob "0001.jpg" will be downloaded to destination "/tmp/img/0001.jpg" .

        This parameter can be an empty string.

        Note that this parameter allows directory traversal (e.g. "/", "../")
        and is not intended for unsanitized end user input.

    :type blob_name_prefix: str
    :param blob_name_prefix:
        A string that will be prepended to each blob_name in the input list, in
        order to determine the name of the source blob. Unlike the blob_name
        itself, the prefix string does not affect the destination path on the
        local filesystem. For instance, if the destination_directory is
        "/tmp/img/", the blob_name_prefix is "myuser/mystuff-" and a blob_name
        is "0001.jpg" then the source blob "myuser/mystuff-0001.jpg" will be
        downloaded to "/tmp/img/0001.jpg". The blob_name_prefix can be blank
        (an empty string).

    :type download_kwargs: dict
    :param download_kwargs:
        A dictionary of keyword arguments to pass to the download method. Refer
        to the documentation for blob.download_to_file() or
        blob.download_to_filename() for more information. The dict is directly
        passed into the download methods and is not validated by this function.

    :type threads: int
    :param threads:
        ***DEPRECATED*** Sets `worker_type` to THREAD and `max_workers` to the
        number specified. If `worker_type` or `max_workers` are set explicitly,
        this parameter should be set to None. Please use `worker_type` and
        `max_workers` instead of this parameter.

    :type deadline: int
    :param deadline:
        The number of seconds to wait for all threads to resolve. If the
        deadline is reached, all threads will be terminated regardless of their
        progress and concurrent.futures.TimeoutError will be raised. This can be
        left as the default of None (no deadline) for most use cases.

    :type create_directories: bool
    :param create_directories:
        If True, recursively create any directories that do not exist. For
        instance, if downloading object "images/img001.png", create the
        directory "images" before downloading.

    :type raise_exception: bool
    :param raise_exception:
        If True, instead of adding exceptions to the list of return values,
        instead they will be raised. Note that encountering an exception on one
        operation will not prevent other operations from starting. Exceptions
        are only processed and potentially raised after all operations are
        complete in success or failure. If skip_if_exists is True, 412
        Precondition Failed responses are considered part of normal operation
        and are not raised as an exception.

    :type worker_type: str
    :param worker_type:
        The worker type to use; one of google.cloud.storage.transfer_manager.PROCESS
        or google.cloud.storage.transfer_manager.THREAD.

        Although the exact performance impact depends on the use case, in most
        situations the PROCESS worker type will use more system resources (both
        memory and CPU) and result in faster operations than THREAD workers.

        Because the subprocesses of the PROCESS worker type can't access memory
        from the main process, Client objects have to be serialized and then
        recreated in each subprocess. The serialization of the Client object
        for use in subprocesses is an approximation and may not capture every
        detail of the Client object, especially if the Client was modified after
        its initial creation or if `Client._http` was modified in any way.

        THREAD worker types are observed to be relatively efficient for
        operations with many small files, but not for operations with large
        files. PROCESS workers are recommended for large file operations.

    :type max_workers: int
    :param max_workers:
        The maximum number of workers to create to handle the workload.

        With PROCESS workers, a larger number of workers will consume more
        system resources (memory and CPU) at once.

        How many workers is optimal depends heavily on the specific use case,
        and the default is a conservative number that should work okay in most
        cases without consuming excessive resources.

    :raises: :exc:`concurrent.futures.TimeoutError` if deadline is exceeded.

    :rtype: list
    :returns: A list of results corresponding to, in order, each item in the
        input list. If an exception was received, it will be the result
        for that operation. Otherwise, the return value from the successful
        download method is used (typically, None).
    T)exist_ok)r?   r2   r3   r	   r
   )rB   rC   rD   splitmakedirsr%   r8   r@   )rE   Z
blob_namesZdestination_directoryrG   r?   r   r2   Zcreate_directoriesr3   r	   r
   r>   rI   Zfull_blob_namerC   	directory_r   r   r   download_many_to_path"  s"     rP   c                 C   s   |du ri }d|v sd|v r$t d| jr0| js8|   t|\}}|rPt| n| }	g }
t|d}W d   n1 sx0    Y  ||dl}d}| j}||k r|}t|| |}|
|j	t
|	|||d |d	 qtjj|
|tjjd
 W d   n1 s0    Y  |
D ]}|  qdS )ax  Download a single file in chunks, concurrently.

    This function is a PREVIEW FEATURE: the API may change in a future version.

    In some environments, using this feature with mutiple processes will result
    in faster downloads of large files.

    Using this feature with multiple threads is unlikely to improve download
    performance under normal circumstances due to Python interpreter threading
    behavior. The default is therefore to use processes instead of threads.

    Checksumming (md5 or crc32c) is not supported for chunked operations. Any
    `checksum` parameter passed in to download_kwargs will be ignored.

    :type bucket: 'google.cloud.storage.bucket.Bucket'
    :param bucket:
        The bucket which contains the blobs to be downloaded

    :type blob: `google.cloud.storage.Blob`
    :param blob:
        The blob to be downloaded.

    :type filename: str
    :param filename:
        The destination filename or path.

    :type download_kwargs: dict
    :param download_kwargs:
        A dictionary of keyword arguments to pass to the download method. Refer
        to the documentation for blob.download_to_file() or
        blob.download_to_filename() for more information. The dict is directly
        passed into the download methods and is not validated by this function.

        Keyword arguments "start" and "end" which are not supported and will
        cause a ValueError if present.

    :type deadline: int
    :param deadline:
        The number of seconds to wait for all threads to resolve. If the
        deadline is reached, all threads will be terminated regardless of their
        progress and concurrent.futures.TimeoutError will be raised. This can be
        left as the default of None (no deadline) for most use cases.

    :type worker_type: str
    :param worker_type:
        The worker type to use; one of google.cloud.storage.transfer_manager.PROCESS
        or google.cloud.storage.transfer_manager.THREAD.

        Although the exact performance impact depends on the use case, in most
        situations the PROCESS worker type will use more system resources (both
        memory and CPU) and result in faster operations than THREAD workers.

        Because the subprocesses of the PROCESS worker type can't access memory
        from the main process, Client objects have to be serialized and then
        recreated in each subprocess. The serialization of the Client object
        for use in subprocesses is an approximation and may not capture every
        detail of the Client object, especially if the Client was modified after
        its initial creation or if `Client._http` was modified in any way.

        THREAD worker types are observed to be relatively efficient for
        operations with many small files, but not for operations with large
        files. PROCESS workers are recommended for large file operations.

    :type max_workers: int
    :param max_workers:
        The maximum number of workers to create to handle the workload.

        With PROCESS workers, a larger number of workers will consume more
        system resources (memory and CPU) at once.

        How many workers is optimal depends heavily on the specific use case,
        and the default is a conservative number that should work okay in most
        cases without consuming excessive resources.

    :raises: :exc:`concurrent.futures.TimeoutError` if deadline is exceeded.
    NstartendzWDownload arguments 'start' and 'end' are not supported by download_chunks_concurrently.wbr   r      )rQ   rR   r?   r   )r   sizeZ
generationreloadr"   r(   openminr%   r&   "_download_and_write_chunk_in_placer)   r*   r+   r,   r.   )r8   rH   
chunk_sizer?   r2   r	   r
   r4   r5   maybe_pickled_blobr*   rO   r6   cursorrR   rQ   r:   r   r   r   download_chunks_concurrently  sF    V
$r]   c                 C   sj   t | tr| }n
t| }t|d2}|| |j|f||d|W  d    S 1 s\0    Y  d S )Nzrb+)rQ   rR   )r#   r   pickleloadsrW   seekr=   )r[   rH   rQ   rR   r?   r8   fr   r   r   rY   O  s    


rY   c                 O   s.   t | tr| }n
t| }t|||i |S )zHelper function that runs inside a thread or subprocess.

    `maybe_pickled_blob` is either a blob (for threads) or a specially pickled
    blob (for processes) because the default pickling mangles clients which are
    attached to blobs.)r#   r   r^   r_   getattr)r[   method_namer   r   r8   r   r   r   r'   ]  s    	

r'   c                 C   s8   t | }| j}| j}d}| j}| j}t||||||ffS )zBReplicate a Client by constructing a new one with the same params.N)idprojectZ_initial_credentialsZ_initial_client_infoZ_initial_client_options_LazyClient)clZclient_object_idre   credentialsZ_httpZclient_infoZclient_optionsr   r   r   _reduce_clientm  s    ri   c                 C   s:   t  }t|}tj |_t|jt< |	|  |
 S )zBPickle a Blob (and its Bucket and Client) and return a bytestring.)ioBytesIOr^   Picklercopyregdispatch_tabler!   ri   r   dumpgetvalue)r8   ra   pr   r   r   r(     s    	


r(   c                 C   s4   | t krtjjdfS | tkr(tjjdfS tddS )zDReturns the pool class, and whether the pool requires pickled Blobs.TFzuThe worker_type must be google.cloud.storage.transfer_manager.PROCESS or google.cloud.storage.transfer_manager.THREADN)PROCESSr)   r*   ProcessPoolExecutorr   ThreadPoolExecutorr   )r	   r   r   r   r"     s    r"   c                   @   s   e Zd ZdZdd ZdS )rf   zBAn object that will transform into either a cached or a new Clientc                 O   s0   t |}|r|S t|i |}|t |< |S d S )N)_cached_clientsr   r   )clsrd   r   r   Zcached_clientr   r   r   __new__  s    
z_LazyClient.__new__N)__name__
__module____qualname____doc__rw   r   r   r   r   rf     s   rf   ) r{   concurrent.futuresr)   rj   r   rB   r   r^   rm   Zgoogle.api_corer   Zgoogle.cloud.storager   r   r   ZTM_DEFAULT_CHUNK_SIZEZDEFAULT_MAX_WORKERSrr   r   ru   r   r<   r@   rJ   rP   r]   rY   r'   ri   r(   r"   rf   r   r   r   r   <module>   s      / *
 