ó V!¶\c @s®dZddlZddlZddlZddlZddlZddlZddlZddl m Z ddl m Z ddl m Z ddl mZddlmZddlmZdd lmZdd lmZdd lmZdd lmZdd lmZddlmZddlmZejeƒZdZejdddddddgƒZ ejddddddddgƒZ!ej"d„ƒZ#d„Z$de%fd„ƒYZ&de%fd „ƒYZ'd!efd"„ƒYZ(d#efd$„ƒYZ)d%e%fd&„ƒYZ*d'e%fd(„ƒYZ+d)e%fd*„ƒYZ,d+efd,„ƒYZ-e-j.d'e+ƒd-ej/fd.„ƒYZ0d/e0fd0„ƒYZ1d1e0fd2„ƒYZ2dS(3sCSpeeds up S3 throughput by using processes Getting Started =============== The :class:`ProcessPoolDownloader` can be used to download a single file by calling :meth:`ProcessPoolDownloader.download_file`: .. code:: python from s3transfer.processpool import ProcessPoolDownloader with ProcessPoolDownloader() as downloader: downloader.download_file('mybucket', 'mykey', 'myfile') This snippet downloads the S3 object located in the bucket ``mybucket`` at the key ``mykey`` to the local file ``myfile``. Any errors encountered during the transfer are not propagated. To determine if a transfer succeeded or failed, use the `Futures`_ interface. The :class:`ProcessPoolDownloader` can be used to download multiple files as well: .. code:: python from s3transfer.processpool import ProcessPoolDownloader with ProcessPoolDownloader() as downloader: downloader.download_file('mybucket', 'mykey', 'myfile') downloader.download_file('mybucket', 'myotherkey', 'myotherfile') When running this snippet, the downloading of ``mykey`` and ``myotherkey`` happen in parallel. The first ``download_file`` call does not block the second ``download_file`` call. The snippet blocks when exiting the context manager and blocks until both downloads are complete. Alternatively, the ``ProcessPoolDownloader`` can be instantiated and explicitly be shutdown using :meth:`ProcessPoolDownloader.shutdown`: .. code:: python from s3transfer.processpool import ProcessPoolDownloader downloader = ProcessPoolDownloader() downloader.download_file('mybucket', 'mykey', 'myfile') downloader.download_file('mybucket', 'myotherkey', 'myotherfile') downloader.shutdown() For this code snippet, the call to ``shutdown`` blocks until both downloads are complete. Additional Parameters ===================== Additional parameters can be provided to the ``download_file`` method: * ``extra_args``: A dictionary containing any additional client arguments to include in the `GetObject `_ API request. For example: .. code:: python from s3transfer.processpool import ProcessPoolDownloader with ProcessPoolDownloader() as downloader: downloader.download_file( 'mybucket', 'mykey', 'myfile', extra_args={'VersionId': 'myversion'}) * ``expected_size``: By default, the downloader will make a HeadObject call to determine the size of the object. To opt-out of this additional API call, you can provide the size of the object in bytes: .. code:: python from s3transfer.processpool import ProcessPoolDownloader MB = 1024 * 1024 with ProcessPoolDownloader() as downloader: downloader.download_file( 'mybucket', 'mykey', 'myfile', expected_size=2 * MB) Futures ======= When ``download_file`` is called, it immediately returns a :class:`ProcessPoolTransferFuture`. The future can be used to poll the state of a particular transfer. To get the result of the download, call :meth:`ProcessPoolTransferFuture.result`. The method blocks until the transfer completes, whether it succeeds or fails. For example: .. code:: python from s3transfer.processpool import ProcessPoolDownloader with ProcessPoolDownloader() as downloader: future = downloader.download_file('mybucket', 'mykey', 'myfile') print(future.result()) If the download succeeds, the future returns ``None``: .. code:: python None If the download fails, the exception causing the failure is raised. For example, if ``mykey`` did not exist, the following error would be raised .. code:: python botocore.exceptions.ClientError: An error occurred (404) when calling the HeadObject operation: Not Found .. note:: :meth:`ProcessPoolTransferFuture.result` can only be called while the ``ProcessPoolDownloader`` is running (e.g. before calling ``shutdown`` or inside the context manager). Process Pool Configuration ========================== By default, the downloader has the following configuration options: * ``multipart_threshold``: The threshold size for performing ranged downloads in bytes. By default, ranged downloads happen for S3 objects that are greater than or equal to 8 MB in size. * ``multipart_chunksize``: The size of each ranged download in bytes. By default, the size of each ranged download is 8 MB. * ``max_request_processes``: The maximum number of processes used to download S3 objects. By default, the maximum is 10 processes. To change the default configuration, use the :class:`ProcessTransferConfig`: .. code:: python from s3transfer.processpool import ProcessPoolDownloader from s3transfer.processpool import ProcessTransferConfig config = ProcessTransferConfig( multipart_threshold=64 * 1024 * 1024, # 64 MB max_request_processes=50 ) downloader = ProcessPoolDownloader(config=config) Client Configuration ==================== The process pool downloader creates ``botocore`` clients on your behalf. In order to affect how the client is created, pass the keyword arguments that would have been used in the :meth:`botocore.Session.create_client` call: .. code:: python from s3transfer.processpool import ProcessPoolDownloader from s3transfer.processpool import ProcessTransferConfig downloader = ProcessPoolDownloader( client_kwargs={'region_name': 'us-west-2'}) This snippet ensures that all clients created by the ``ProcessPoolDownloader`` are using ``us-west-2`` as their region. iÿÿÿÿN(tMB(tALLOWED_DOWNLOAD_ARGS(tMAXINT(t BaseManager(tCancelledError(tRetriesExceededError(tBaseTransferFuture(tBaseTransferMeta(tS3_RETRYABLE_DOWNLOAD_ERRORS(tcalculate_num_parts(tcalculate_range_parameter(tOSUtils(tCallArgstSHUTDOWNtDownloadFileRequestt transfer_idtbuckettkeytfilenamet extra_argst expected_sizet GetObjectJobt temp_filenametoffsetccs%tƒ}dVtjtj|ƒdS(N(t"_add_ignore_handler_for_interruptstsignaltSIGINT(toriginal_handler((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyt ignore_ctrl_cþs cCstjtjtjƒS(N(RRtSIG_IGN(((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRstProcessTransferConfigcBs"eZdededd„ZRS(ii cCs||_||_||_dS(suConfiguration for the ProcessPoolDownloader :param multipart_threshold: The threshold for which ranged downloads occur. :param multipart_chunksize: The chunk size of each ranged download. :param max_request_processes: The maximum number of processes that will be making S3 API transfer-related requests at a time. N(tmultipart_thresholdtmultipart_chunksizetmax_request_processes(tselfRR R!((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyt__init__ s  (t__name__t __module__RR#(((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR stProcessPoolDownloadercBs­eZddd„Zddd„Zd„Zd„Zd„Zd„Zd„Z d„Z d„Z d „Z d „Z d „Zd „Zd „Zd„Zd„Zd„ZRS(cCs¸|dkri}nt|ƒ|_||_|dkrHtƒ|_ntjdƒ|_tjdƒ|_t ƒ|_ t |_ t jƒ|_d|_d|_d|_g|_dS(s­Downloads S3 objects using process pools :type client_kwargs: dict :param client_kwargs: The keyword arguments to provide when instantiating S3 clients. The arguments must match the keyword arguments provided to the `botocore.session.Session.create_client()` method. :type config: ProcessTransferConfig :param config: Configuration for the downloader ièN(tNonet ClientFactoryt_client_factoryt_transfer_configRtmultiprocessingtQueuet_download_request_queuet _worker_queueR t_osutiltFalset_startedt threadingtLockt _start_lockt_managert_transfer_monitort _submittert_workers(R"t client_kwargstconfig((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR# s         c CsÅ|jƒ|dkri}n|j|ƒ|jjƒ}td|d|d|d|d|d|ƒ}tjd|ƒ|jj |ƒt d|d|d|d|d|ƒ}|j ||ƒ} | S( ssDownloads the object's contents to a file :type bucket: str :param bucket: The name of the bucket to download from :type key: str :param key: The name of the key to download from :type filename: str :param filename: The name of a file to download to. :type extra_args: dict :param extra_args: Extra arguments that may be passed to the client operation :type expected_size: int :param expected_size: The expected size in bytes of the download. If provided, the downloader will not call HeadObject to determine the object's size and use the provided value instead. The size is needed to determine whether to do a multipart download. :rtype: s3transfer.futures.TransferFuture :returns: Transfer future representing the download RRRRRRs%Submitting download file request: %s.N( t_start_if_neededR't_validate_all_known_argsR6tnotify_new_transferRtloggertdebugR-tputR t_get_transfer_future( R"RRRRRRtdownload_file_requestt call_argstfuture((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyt download_fileAs"        cCs|jƒdS(shShutdown the downloader It will wait till all downloads are complete before returning. N(t_shutdown_if_needed(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pytshutdownnscCs|S(N((R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyt __enter__uscGs?t|tƒr1|jdk r1|jjƒq1n|jƒdS(N(t isinstancetKeyboardInterruptR6R'tnotify_cancel_all_in_progressRG(R"texc_typet exc_valuetargs((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyt__exit__xscCs*|j|js |jƒnWdQXdS(N(R4R1t_start(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR;~s  cCs+|jƒ|jƒ|jƒt|_dS(N(t_start_transfer_monitor_managert_start_submittert_start_get_object_workerstTrueR1(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRPƒs   cCsCx<|D]4}|tkrtd|djtƒfƒ‚qqWdS(Ns/Invalid extra_args key '%s', must be one of: %ss, (Rt ValueErrortjoin(R"tprovidedtkwarg((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR<‰s   cCs1td|d|ƒ}td|jd|ƒ}|S(NRCRtmonitortmeta(tProcessPoolTransferMetatProcessPoolTransferFutureR6(R"RRCRZRD((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRA‘s cCs?tjdƒtƒ|_|jjtƒ|jjƒ|_dS(Ns$Starting the TransferMonitorManager.(R>R?tTransferMonitorManagerR5tstartRtTransferMonitorR6(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRQ˜s  c Cs`tjdƒtd|jd|jd|jd|jd|jd|jƒ|_ |j j ƒdS(Ns Starting the GetObjectSubmitter.ttransfer_configtclient_factoryttransfer_monitortosutiltdownload_request_queuet worker_queue( R>R?tGetObjectSubmitterR*R)R6R/R-R.R7R^(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRR¢s      c Cs~tjd|jjƒxat|jjƒD]M}td|jd|jd|jd|j ƒ}|j ƒ|j j |ƒq)WdS(NsStarting %s GetObjectWorkers.tqueueRaRbRc( R>R?R*R!trangetGetObjectWorkerR.R)R6R/R^R8tappend(R"t_tworker((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRS®s       cCs*|j|jr |jƒnWdQXdS(N(R4R1t _shutdown(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRF»s  cCs+|jƒ|jƒ|jƒt|_dS(N(t_shutdown_submittert_shutdown_get_object_workerst"_shutdown_transfer_monitor_managerR0R1(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRmÀs   cCstjdƒ|jjƒdS(Ns)Shutting down the TransferMonitorManager.(R>R?R5RG(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRpÆs cCs.tjdƒ|jjtƒ|jjƒdS(Ns%Shutting down the GetObjectSubmitter.(R>R?R-R@tSHUTDOWN_SIGNALR7RV(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRnÊs cCsStjdƒx!|jD]}|jjtƒqWx|jD]}|jƒq;WdS(Ns#Shutting down the GetObjectWorkers.(R>R?R8R.R@RqRV(R"RkRl((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRoÏs  N(R$R%R'R#RERGRHROR;RPR<RARQRRRSRFRmRpRnRo(((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR&s$! ,           R\cBs;eZd„Zed„ƒZd„Zd„Zd„ZRS(cCs||_||_dS(saThe future associated to a submitted process pool transfer request :type monitor: TransferMonitor :param monitor: The monitor associated to the proccess pool downloader :type meta: ProcessPoolTransferMeta :param meta: The metadata associated to the request. This object is visible to the requester. N(t_monitort_meta(R"RYRZ((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR#Øs cCs|jS(N(Rs(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRZåscCs|jj|jjƒS(N(Rrtis_doneRsR(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pytdoneéscCsLy|jj|jjƒSWn+tk rG|jjƒ|jƒ‚nXdS(N(Rrtpoll_for_resultRsRRJt_connecttcancel(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pytresultìs    cCs |jj|jjtƒƒdS(N(Rrtnotify_exceptionRsRR(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRxs (R$R%R#tpropertyRZRuRyRx(((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR\×s    R[cBsDeZdZd„Zed„ƒZed„ƒZed„ƒZRS(s2Holds metadata about the ProcessPoolTransferFuturecCs||_||_i|_dS(N(t _transfer_idt _call_argst _user_context(R"RRC((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR# s  cCs|jS(N(R}(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRCscCs|jS(N(R|(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRscCs|jS(N(R~(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyt user_contexts(R$R%t__doc__R#R{RCRR(((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR[s  R(cBseZdd„Zd„ZRS(cCs(||_|jdkr$i|_ndS(sèCreates S3 clients for processes Botocore sessions and clients are not pickleable so they cannot be inherited across Process boundaries. Instead, they must be instantiated once a process is running. N(t_client_kwargsR'(R"R9((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR#s cCstjjƒjd|jS(sCreate a botocore S3 clientts3(tbotocoretsessiontSessiont create_clientR(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR†'sN(R$R%R'R#R†(((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR(s R_cBsbeZd„Zd„Zd„Zd„Zd„Zd„Zd„Zd„Z d„Z d „Z RS( cCs%i|_d|_tjƒ|_dS(sAMonitors transfers for cross-proccess communication Notifications can be sent to the monitor and information can be retrieved from the monitor for a particular transfer. This abstraction is ran in a ``multiprocessing.managers.BaseManager`` in order to be shared across processes. iN(t_transfer_statest _id_countR2R3t _init_lock(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR#.s  cCs@|j1|j}tƒ|j|<|jd7_|SWdQXdS(Ni(R‰Rˆt TransferStateR‡(R"R((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR=>s   cCs|j|jS(s¦Determine a particular transfer is complete :param transfer_id: Unique identifier for the transfer :return: True, if done. False, otherwise. (R‡Ru(R"R((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRtEscCs|j|jƒdS(sqNotify a particular transfer is complete :param transfer_id: Unique identifier for the transfer N(R‡tset_done(R"R((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyt notify_doneMscCs4|j|jƒ|j|j}|r0|‚ndS(sPoll for the result of a transfer :param transfer_id: Unique identifier for the transfer :return: If the transfer succeeded, it will return the result. If the transfer failed, it will raise the exception associated to the failure. N(R‡twait_till_donet exceptionR'(R"RRŽ((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRvTs  cCs||j|_dS(sÁNotify an exception was encountered for a transfer :param transfer_id: Unique identifier for the transfer :param exception: The exception encountered for that transfer N(R‡RŽ(R"RRŽ((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRzbs cCs6x/|jjƒD]}|jstƒ|_qqWdS(N(R‡tvaluesRuRRŽ(R"ttransfer_state((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRKns cCs|j|jS(sûRetrieve the exception encountered for the transfer :param transfer_id: Unique identifier for the transfer :return: The exception encountered for that transfer. Otherwise if there were no exceptions, returns None. (R‡RŽ(R"R((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyt get_exceptionsscCs||j|_dS(s¿Notify the amount of jobs expected for a transfer :param transfer_id: Unique identifier for the transfer :param num_jobs: The number of jobs to complete the transfer N(R‡tjobs_to_complete(R"Rtnum_jobs((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyt notify_expected_jobs_to_complete|scCs|j|jƒS(sÄNotify that a single job is completed for a transfer :param transfer_id: Unique identifier for the transfer :return: The number of jobs remaining to complete the transfer (R‡tdecrement_jobs_to_complete(R"R((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pytnotify_job_complete„s( R$R%R#R=RtRŒRvRzRKR‘R”R–(((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR_-s       RŠcBsƒeZdZd„Zed„ƒZd„Zd„Zed„ƒZej d„ƒZed„ƒZ e j d„ƒZ d „Z RS( s6Represents the current state of an individual transfercCs4d|_tjƒ|_tjƒ|_d|_dS(Ni(R't _exceptionR2tEventt _done_eventR3t _job_lockt_jobs_to_complete(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR#–s cCs |jjƒS(N(R™tis_set(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRuœscCs|jjƒdS(N(R™tset(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR‹ scCs|jjtƒdS(N(R™twaitR(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR£scCs|jS(N(R—(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRŽ¦scCs ||_dS(N(R—(R"tval((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRŽªscCs|jS(N(R›(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR’®scCs ||_dS(N(R›(R"RŸ((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR’²scCs*|j|jd8_|jSWdQXdS(Ni(RšR›(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR•¶s ( R$R%R€R#R{RuR‹RRŽtsetterR’R•(((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRŠs   R]cBseZRS((R$R%(((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR]¼stBaseS3TransferProcesscBs#eZd„Zd„Zd„ZRS(cCs)tt|ƒjƒ||_d|_dS(N(tsuperR¡R#R)R't_client(R"Ra((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR#Äs cCs0|jjƒ|_tƒ|jƒWdQXdS(N(R)R†R£Rt_do_run(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pytrunÉs cCstdƒ‚dS(Ns _do_run()(tNotImplementedError(R"((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR¤Ús(R$R%R#R¥R¤(((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR¡Ãs  RfcBsYeZd„Zd„Zd„Zd„Zd„Zd„Zd„Zd„Z d„Z RS( cCsGtt|ƒj|ƒ||_||_||_||_||_dS(sTSubmit GetObjectJobs to fulfill a download file request :param transfer_config: Configuration for transfers. :param client_factory: ClientFactory for creating S3 clients. :param transfer_monitor: Monitor for notifying and retrieving state of transfer. :param osutil: OSUtils object to use for os-related behavior when performing the transfer. :param download_request_queue: Queue to retrieve download file requests. :param worker_queue: Queue to submit GetObjectJobs for workers to perform. N(R¢RfR#R*R6R/R-R.(R"R`RaRbRcRdRe((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR#ßs     cCs¦xŸtr¡|jjƒ}|tkr5tjdƒdSy|j|ƒWqtk r}tjd||dtƒ|jj |j |ƒ|jj |j ƒqXqWdS(Ns#Submitter shutdown signal received.sFException caught when submitting jobs for download file request %s: %stexc_info( RTR-tgetRqR>R?t_submit_get_object_jobst ExceptionR6RzRRŒ(R"RBte((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR¤ös      cCs]|j|ƒ}|j||ƒ}||jjkrF|j||ƒn|j|||ƒdS(N(t _get_sizet_allocate_temp_fileR*Rt_submit_single_get_object_jobt_submit_ranged_get_object_jobs(R"RBtsizeR((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR©s cCsG|j}|dkrC|jjd|jd|j|jd}n|S(NtBuckettKeyt ContentLength(RR'R£t head_objectRRR(R"RBR((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR¬s    cCs,|jj|jƒ}|jj||ƒ|S(N(R/tget_temp_filenameRtallocate(R"RBR°R((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR­s  cCsZ|j|jdƒ|jd|jd|jd|jd|ddd|jd |jƒdS( NiRRRRRiRR(t_notify_jobs_to_completeRt_submit_get_object_jobRRRR(R"RBR((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR®"s      c CsÂ|jj}t||ƒ}|j|j|ƒxt|ƒD]}||}t|||ƒ}i|d6} | j|jƒ|j d|jd|j d|j d|d|d| d|j ƒq;WdS( NtRangeRRRRRRR( R*R R R·RRhR tupdateRR¸RRR( R"RBRR°t part_sizet num_partstiRtrange_parametertget_object_kwargs((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR¯0s$        cKs|jjt|ƒdS(N(R.R@R(R"tget_object_job_kwargs((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR¸FscCs*tjd||ƒ|jj||ƒdS(Ns3Notifying %s job(s) to complete for transfer_id %s.(R>R?R6R”(R"RR’((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR·Is   ( R$R%R#R¤R©R¬R­R®R¯R¸R·(((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRfÞs      RicBsWeZdZdeZd„Zd„Zd„Zd„Zd„Z d„Z d„Z RS( iicCs>tt|ƒj|ƒ||_||_||_||_dS(süFulfills GetObjectJobs Downloads the S3 object, writes it to the specified file, and renames the file to its final location if it completes the final job for a particular transfer. :param queue: Queue for retrieving GetObjectJob's :param client_factory: ClientFactory for creating S3 clients :param transfer_monitor: Monitor for notifying :param osutil: OSUtils object to use for os-related behavior when performing the transfer. N(R¢RiR#t_queueR)R6R/(R"RgRaRbRc((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR#Xs    cCsÂx»tr½|jjƒ}|tkr5tjdƒdS|jj|jƒsZ|j |ƒntjd|ƒ|jj |jƒ}tjd||jƒ|s|j |j|j |j ƒqqWdS(Ns Worker shutdown signal received.sBSkipping get object job %s because there was a previous exception.s%%s jobs remaining for transfer_id %s.(RTRÁR¨RqR>R?R6R‘Rt_run_get_object_jobR–t_finalize_downloadRR(R"tjobt remaining((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR¤ks&     c Cs„y;|jd|jd|jd|jd|jd|jƒWnBtk r}tjd||dt ƒ|j j |j |ƒnXdS(NRRRRRsBException caught when downloading object for get object job %s: %sR§( t_do_get_objectRRRRRRªR>R?RTR6RzR(R"RÄR«((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyR‚s  c Cs¬d}x“t|jƒD]‚}y=|jjd|d||}|j|||dƒdSWqtk r—} tjd| |d|jdt ƒ| }qXqWt |ƒ‚dS(NR±R²tBodysCRetrying exception caught (%s), retrying request, (attempt %s / %s)iR§( R'Rht _MAX_ATTEMPTSR£t get_objectt_write_to_fileRR>R?RTR( R"RRRRRtlast_exceptionR½tresponseR«((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRÆs   csbt|dƒM}|j|ƒt‡‡fd†dƒ}x|D]}|j|ƒqAWWdQXdS(Nsrb+csˆjˆjƒS(N(treadt _IO_CHUNKSIZE((tbodyR"(s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyt¡st(topentseektitertwrite(R"RRRÏtftchunkstchunk((RÏR"s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRÊžs   cCsL|jj|ƒr%|jj|ƒn|j|||ƒ|jj|ƒdS(N(R6R‘R/t remove_filet_do_file_renameRŒ(R"RRR((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRÃ¥scCsTy|jj||ƒWn6tk rO}|jj||ƒ|jj|ƒnXdS(N(R/t rename_fileRªR6RzRÙ(R"RRRR«((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRÚ¬s ( R$R%RÈRRÎR#R¤RÂRÆRÊRÃRÚ(((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pyRiRs      (3R€t collectionst contextlibtloggingR+R2Rtbotocore.sessionRƒts3transfer.constantsRRts3transfer.compatRRts3transfer.exceptionsRRts3transfer.futuresRRts3transfer.utilsRR R R R t getLoggerR$R>Rqt namedtupleRRtcontextmanagerRRtobjectRR&R\R[R(R_RŠR]tregistertProcessR¡RfRi(((s</tmp/pip-install-usGedi/s3transfer/s3transfer/processpool.pytÂsj          ¸0`/t