o
    iG                     @   s  d Z ddlZddlmZ ddlmZ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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mZmZmZmZ ddlmZ ddlT ddlZddlZddlZddlZddlZeeZ							d;ddZ 							d;ddZ!dZ"	d<ddZ#dd Z$dd Z%d=ddZ&d=dd Z'd=d!d"Z(G d#d$ d$e)Z*G d%d& d&e)Z+G d'd( d(e*Z,G d)d* d*e*Z-d+Z.d,Z/G d-d. d.e)Z0d/d0 Z1G d1d2 d2e0Z2G d3d4 d4e0Z3d=d5d6Z4d=d7d8Z5G d9d: d:e)Z6dS )>uW   
oss2.resumable
~~~~~~~~~~~~~~

该模块包含了断点续传相关的函数和类。
    N   )utils)b64encode_as_stringb64decode_from_string)	iterators)
exceptions)defaults)http)models)CryptoBucket)Bucket)PartIterator)PartInfo)json	stringify
to_unicode	to_string)	TaskQueue)*c
                 C   s   t d| jt|||||| tj|}
t	|tj
}t d|
| |
|kr?t| |||
||||||	d
}| }|S tt|d}| j||||d}W d   |S 1 s[w   Y  |S )u  断点上传本地文件。

    实现中采用分片上传方式上传本地文件，缺省的并发数是 `oss2.defaults.multipart_num_threads` ，并且在
    本地磁盘保存已经上传的分片信息。如果因为某种原因上传被中断，下次上传同样的文件，即源文件和目标文件路径都
    一样，就只会上传缺失的分片。

    缺省条件下，该函数会在用户 `HOME` 目录下保存断点续传的信息。当待上传的本地文件没有发生变化，
    且目标文件名没有变化时，会根据本地保存的信息，从断点开始上传。

    使用该函数应注意如下细节：
        #. 如果使用CryptoBucket，函数会退化为普通上传

    :param bucket: :class:`Bucket <oss2.Bucket>` 或者 ：:class:`CryptoBucket <oss2.CryptoBucket>` 对象
    :param key: 上传到用户空间的文件名
    :param filename: 待上传本地文件名
    :param store: 用来保存断点信息的持久存储，参见 :class:`ResumableStore` 的接口。如不指定，则使用 `ResumableStore` 。

    :param headers: HTTP头部
        # 调用外部函数put_object 或 init_multipart_upload传递完整headers
        # 调用外部函数uplpad_part目前只传递OSS_REQUEST_PAYER, OSS_TRAFFIC_LIMIT
        # 调用外部函数complete_multipart_upload目前只传递OSS_REQUEST_PAYER, OSS_OBJECT_ACL
    :type headers: 可以是dict，建议是oss2.CaseInsensitiveDict

    :param multipart_threshold: 文件长度大于该值时，则用分片上传。
    :param part_size: 指定分片上传的每个分片的大小。如不指定，则自动计算。
    :param progress_callback: 上传进度回调函数。参见 :ref:`progress_callback` 。
    :param num_threads: 并发上传的线程数，如不指定则使用 `oss2.defaults.multipart_num_threads` 。

    :param params: HTTP请求参数
        # 只有'sequential'这个参数才会被传递到外部函数init_multipart_upload中。
        # 其他参数视为无效参数不会往外部函数传递。
    :type params: dict
    zStart to resumable upload, bucket: {0}, key: {1}, filename: {2}, headers: {3}, multipart_threshold: {4}, part_size: {5}, num_threads: {6}z<The size of file to upload is: {0}, multipart_threshold: {1})	part_sizeheadersprogress_callbacknum_threadsparamsrb)r   r   N)loggerdebugformatbucket_namer   ospathgetsizer   getmultipart_threshold_ResumableUploaderuploadopenr   
put_object)bucketkeyfilenamestorer   r#   r   r   r   r   sizeuploaderresultf r0   B/home/ubuntu/.local/lib/python3.10/site-packages/oss2/resumable.pyresumable_upload&   s2   )
r2   c
                 C   s   t d| jt||||| t|tj}t|	t	t
g}
| j|||
d}t d|j| |j|krNt| ||t|||||||
d
}||j dS | j|||||
d dS )uZ
  断点下载。

    实现的方法是：
        #. 在本地创建一个临时文件，文件名由原始文件名加上一个随机的后缀组成；
        #. 通过指定请求的 `Range` 头按照范围并发读取OSS文件，并写入到临时文件里对应的位置；
        #. 全部完成之后，把临时文件重命名为目标文件 （即 `filename` ）

    在上述过程中，断点信息，即已经完成的范围，会保存在磁盘上。因为某种原因下载中断，后续如果下载
    同样的文件，也就是源文件和目标文件一样，就会先读取断点信息，然后只下载缺失的部分。

    缺省设置下，断点信息保存在 `HOME` 目录的一个子目录下。可以通过 `store` 参数更改保存位置。

    使用该函数应注意如下细节：
        #. 对同样的源文件、目标文件，避免多个程序（线程）同时调用该函数。因为断点信息会在磁盘上互相覆盖，或临时文件名会冲突。
        #. 避免使用太小的范围（分片），即 `part_size` 不宜过小，建议大于或等于 `oss2.defaults.multiget_part_size` 。
        #. 如果目标文件已经存在，那么该函数会覆盖此文件。
        #. 如果使用CryptoBucket，函数会退化为普通下载


    :param bucket: :class:`Bucket <oss2.Bucket>` 或者 ：:class:`CryptoBucket <oss2.CryptoBucket>` 对象
    :param str key: 待下载的远程文件名。
    :param str filename: 本地的目标文件名。
    :param int multiget_threshold: 文件长度大于该值时，则使用断点下载。
    :param int part_size: 指定期望的分片大小，即每个请求获得的字节数，实际的分片大小可能有所不同。
    :param progress_callback: 下载进度回调函数。参见 :ref:`progress_callback` 。
    :param num_threads: 并发下载的线程数，如不指定则使用 `oss2.defaults.multiget_num_threads` 。

    :param store: 用来保存断点信息的持久存储，可以指定断点信息所在的目录。
    :type store: `ResumableDownloadStore`

    :param dict params: 指定下载参数，可以传入versionId下载指定版本文件

    :param headers: HTTP头部,
        # 调用外部函数head_object目前只传递OSS_REQUEST_PAYER
        # 调用外部函数get_object_to_file, get_object目前需要向下传递的值有OSS_REQUEST_PAYER, OSS_TRAFFIC_LIMIT
    :type headers: 可以是dict，建议是oss2.CaseInsensitiveDict

    :raises: 如果OSS文件不存在，则抛出 :class:`NotFound <oss2.exceptions.NotFound>` ；也有可能抛出其他因下载文件而产生的异常。
    z|Start to resumable download, bucket: {0}, key: {1}, filename: {2}, multiget_threshold: {3}, part_size: {4}, num_threads: {5})r   r   z?The size of object to download is: {0}, multiget_threshold: {1})r   r   r   r+   r   r   )r   r   r   N)r   r   r   r   r   r   r"   multiget_threshold_populate_valid_headersOSS_REQUEST_PAYEROSS_TRAFFIC_LIMIThead_objectcontent_length_ResumableDownloader_ObjectInfomakedownload
server_crcget_object_to_file)r(   r)   r*   r3   r   r   r   r+   r   r   valid_headersr.   
downloaderr0   r0   r1   resumable_downloadf   s(   /

rA   i c                 C   s   |st j}t| |t jS )u   确定分片上传是分片的大小。

    :param int total_size: 总共需要上传的长度
    :param int preferred_size: 用户期望的分片大小。如果不指定则采用defaults.part_size

    :return: 分片大小
    )r   r   _determine_part_size_internalmax_part_count)
total_sizepreferred_sizer0   r0   r1   determine_part_size   s   	rF   c                 C   sD   | |k r| S || | k s|t jk r |d }|| | k s|t jk s|S )N   )r   min_part_size)rD   rE   	max_countr0   r0   r1   rB      s   rB   c                 C   sb   g }t | |}t|D ]"}||d kr|| }| }n|| }|| }|t|d || q|S )Nr   )r   how_manyrangeappend_PartToProcess)rD   r   parts	num_partsistartendr0   r0   r1   _split_to_parts   s   rS   c                 C   s^   | du s|du r
dS t | } t  }|D ]}| |dur$| | ||< qt|dkr-d}|S )u8  构建只包含有效keys的http header

    :param headers: 需要过滤的header
    :type headers: 可以是dict，建议是oss2.CaseInsensitiveDict

    :param valid_keys: 有效的关键key列表
    :type valid_keys: list

    :return: 只包含有效keys的http header, type: oss2.CaseInsensitiveDict
    Nr   )r	   CaseInsensitiveDictr"   len)r   
valid_keysr?   r)   r0   r0   r1   r4      s   
r4   c                 C   s\   | du s|du r
dS t | } |  }|D ]}||dur#|| qt|dkr,d}|S )u9  过滤无效keys的http header

    :param headers: 需要过滤的header
    :type headers: 可以是dict，建议是oss2.CaseInsensitiveDict

    :param invalid_keys: 无效的关键key列表
    :type invalid_keys: list

    :return: 过滤无效header之后的http headers, type: oss2.CaseInsensitiveDict
    Nr   )r	   rT   copyr"   poprU   )r   invalid_keysr?   r)   r0   r0   r1   _filter_invalid_headers   s   

rZ   c                 C   sR   | du s|du r
dS t  }|D ]}| |dur| | ||< qt|dkr'd}|S )u   构建只包含有效keys的params

    :param params: 需要过滤的params
    :type params: dict

    :param valid_keys: 有效的关键key列表
    :type valid_keys: list

    :return: 只包含有效keys的params
    Nr   )dictr"   rU   )r   rV   valid_paramsr)   r0   r0   r1   _populate_valid_params	  s   r]   c                   @   s8   e Zd Z	dddZdd Zdd Zdd	 Zd
d ZdS )_ResumableOperationNc                 C   s   || _ t|| _|| _|| _tj|| _|| _	|d u r)| j	
|j| j| j| _n| j	
|j| j| j|| _td| j t | _|| _d S )Nz)Init _ResumableOperation, record_key: {0})r(   r   r)   r*   r,   r   r    abspath_abspath_ResumableOperation__storemake_store_keyr   _ResumableOperation__record_keyr   r   r   	threadingLock_ResumableOperation__plock&_ResumableOperation__progress_callback)selfr(   r)   r*   r,   r+   r   	versionidr0   r0   r1   __init__#  s   


z_ResumableOperation.__init__c                 C   s   | j | j d S N)ra   deleterc   rh   r0   r0   r1   _del_record9  s   z_ResumableOperation._del_recordc                 C   s   | j | j| d S rk   )ra   putrc   rh   recordr0   r0   r1   _put_record<     z_ResumableOperation._put_recordc                 C   s   | j | jS rk   )ra   r"   rc   rm   r0   r0   r1   _get_record?  s   z_ResumableOperation._get_recordc                 C   sD   | j r | j |  || j W d    d S 1 sw   Y  d S d S rk   )rg   rf   r,   )rh   consumed_sizer0   r0   r1   _report_progressB  s
   "z$_ResumableOperation._report_progressNN)__name__
__module____qualname__rj   rn   rr   rt   rv   r0   r0   r0   r1   r^   "  s    
r^   c                   @   s    e Zd Zdd Zedd ZdS )r:   c                 C   s   d | _ d | _d | _d S rk   )r,   etagmtimerm   r0   r0   r1   rj   I  s   
z_ObjectInfo.__init__c                 C   s"   t  }| j|_| j|_| j|_|S rk   )r:   r8   r,   r{   last_modifiedr|   )head_object_result
objectInfor0   r0   r1   r;   N  s
   z_ObjectInfo.makeN)rx   ry   rz   rj   staticmethodr;   r0   r0   r0   r1   r:   H  s    r:   c                       s~   e Zd Z						d fdd	ZdddZd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  ZS )r9   Nc              	      s   d }|	d ur|	 dd ur|	 d}tt| j||||j|p t ||d || _d| _t |tj	| _
t| j| j
t| _
d | _t |tj| _d | _d | _|	| _|
| _t | _d | _td|jt|| j
| j d S )N	versionId)r   ri   ResumableDownloadzQInit _ResumableDownloader, bucket: {0}, key: {1}, part_size: {2}, num_thread: {3})r"   superr9   rj   r,   ResumableDownloadStorer   _ResumableDownloader__opr   multiget_part_size_ResumableDownloader__part_sizerB   _MAX_MULTIGET_PART_COUNT_ResumableDownloader__tmp_filemultiget_num_threads!_ResumableDownloader__num_threads$_ResumableDownloader__finished_parts#_ResumableDownloader__finished_size_ResumableDownloader__params_ResumableDownloader__headersrd   re   _ResumableDownloader__lock_ResumableDownloader__recordr   r   r   r   r   )rh   r(   r)   r*   r   r   r+   r   r   r   r   ri   	__class__r0   r1   rj   Y  s.   


z_ResumableDownloader.__init__c                 C   s   |    |  }td| t| jd  tt	j
| j|d| jg| j }|  | jjrFt| jdd d}t|}td||d  t| j| j | | j |   d S )NzParts need to download: {0}a)parts_to_downloadc                 S      | j S rk   part_numberpr0   r0   r1   <lambda>      z/_ResumableDownloader.download.<locals>.<lambda>r)   zresume download)!_ResumableDownloader__load_record+_ResumableDownloader__get_parts_to_downloadr   r   r   r&   r   closer   	functoolspartial_ResumableDownloader__producer_ResumableDownloader__consumerr   runr(   
enable_crcsortedr   r   calc_obj_crc_from_parts	check_crcforce_renamer*   rv   r,   rn   )rh   r=   r   qrN   
object_crcr0   r0   r1   r<   y  s   
z_ResumableDownloader.downloadc                 C      |D ]}| | qd S rk   ro   )rh   r   r   partr0   r0   r1   
__producer     z_ResumableDownloader.__producerc                 C   s6   |  r| }|d u rd S | | |  sd S d S rk   )okr"   #_ResumableDownloader__download_partrh   r   r   r0   r0   r1   
__consumer  s   
z_ResumableDownloader.__consumerc                 C   s   |  | j t| jdO}||jtj t| j	t
tg}|d u r%t }| jj|t< t| jj|t< | jj| j|j|jd f|| jd}tj|||j|j |jd W d    n1 s^w   Y  |j|_td |j!|j|j | "| d S )Nzrb+r   )
byte_ranger   r   )
request_idzRdown part success, add part info to record, part_number: {0}, start: {1}, end: {2})#rv   r   r&   r   seekrQ   r   SEEK_SETr4   r   r5   r6   r	   rT   r   r{   IF_MATCHr   	http_dater|   IF_UNMODIFIED_SINCEr(   
get_objectr)   rR   r   copyfileobj_and_verifyr   
client_crcpart_crcr   r   r   r   !_ResumableDownloader__finish_partrh   r   r/   r   r.   r0   r0   r1   __download_part  s    $z$_ResumableDownloader.__download_partc                 C   sn  |   }td| |r| |std |   d }|r>tj	| j
|d  s>td| j
|d   |   d }|r^| |r^td| j t| j
|d   |   d }|s| j| jj| j| jj| jj| jj| j| j|  g d
}td| jj| j| j | | | j
|d  | _|d | _td	d
 |d D | _tdd
 | jD | _|| _d S )NLoad record return {0}3The content of record is invalid, delete the record
tmp_suffixz0Temp file: {0} does not exist, delete the recorduA   Object: {0} has been overwritten，delete the record and tmp file)
op_typer(   r)   r,   r|   r{   r   	file_pathr   rN   z5Add new record, bucket: {0}, key: {1}, part_size: {2}r   c                 s   s.    | ]}t |d  |d |d |d V  qdS )r   rQ   rR   r   N)rM   .0r   r0   r0   r1   	<genexpr>  s    
z5_ResumableDownloader.__load_record.<locals>.<genexpr>rN   c                 s       | ]}|j V  qd S rk   r,   r   r0   r0   r1   r         ) rt   r   r   r   $_ResumableDownloader__is_record_sanewarnrn   r   r    existsr*   '_ResumableDownloader__is_remote_changedr)   r   silently_remover   r(   r   r   r,   r|   r{   r   r`   $_ResumableDownloader__gen_tmp_suffixrr   r   listr   sumr   r   rp   r0   r0   r1   __load_record  sD   




z"_ResumableDownloader.__load_recordc                 C   s>   | j sJ tt| j| j}t| j}tt|| dd dS )Nc                 S   r   rk   r   r   r0   r0   r1   r     r   z>_ResumableDownloader.__get_parts_to_download.<locals>.<lambda>r   )r   setrS   r,   r   r   r   r   )rh   all_setfinished_setr0   r0   r1   __get_parts_to_download  s   

z,_ResumableDownloader.__get_parts_to_downloadc              
   C   s   zb|d | j krtd|d  W dS dD ]}t|| ts/td|||   W dS qdD ]}t|| tsJtd|||   W dS q2t|d ts`td	|||  W dS W dS  ty~ } ztd
|j	 W Y d }~dS d }~ww )Nr   1op_type invalid, op_type in record:{0} is invalidF)r{   r   r   r(   r)   z{0} is not a string: {1})r   r,   r|   z{0} is not an integer: {1}rN   z{0} is not a list: {1}Key not found: {0}T)
r   r   errorr   
isinstancestrintr   KeyErrorargsrh   rq   r)   er0   r0   r1   __is_record_sane  s0   z%_ResumableDownloader.__is_record_sanec                 C   s0   |d | j jkp|d | j jkp|d | j jkS )Nr|   r,   r{   )r   r|   r,   r{   rp   r0   r0   r1   __is_remote_changed  s
   z(_ResumableDownloader.__is_remote_changedc                 C   sv   | j . | j| |  j|j7  _| jd |j|j|j|j	d | 
| j W d    d S 1 s4w   Y  d S )NrN   r   rQ   rR   r   )r   r   rL   r   r,   r   r   rQ   rR   r   rr   )rh   r   r0   r0   r1   __finish_part  s   "z"_ResumableDownloader.__finish_partc                 C   s   dd dd tdD  S )Nz.tmp- c                 s   s    | ]	}t tjV  qd S rk   )randomchoicestringascii_lowercase)r   rP   r0   r0   r1   r     s    z8_ResumableDownloader.__gen_tmp_suffix.<locals>.<genexpr>   )joinrK   rm   r0   r0   r1   __gen_tmp_suffix     z%_ResumableDownloader.__gen_tmp_suffixNNNNNNrk   )rx   ry   rz   rj   r<   r   r   r   r   r   r   r   r   r   __classcell__r0   r0   r   r1   r9   X  s$    
 
%r9   c                       s   e Zd ZdZ						d fdd	Zdd Zd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  ZS )r$   uq  以断点续传方式上传文件。

    :param bucket: :class:`Bucket <oss2.Bucket>` 对象
    :param key: 文件名
    :param filename: 待上传的文件名
    :param size: 文件总长度
    :param store: 用来保存进度的持久化存储
    :param headers: 传给 `init_multipart_upload` 的HTTP头部
    :param part_size: 分片大小。优先使用用户提供的值。如果用户没有指定，那么对于新上传，计算出一个合理值；对于老的上传，采用第一个
        分片的大小。
    :param progress_callback: 上传进度回调函数。参见 :ref:`progress_callback` 。
    Nc                    s   t t| j|||||pt |d d| _|| _t|tj| _	t
j|| _t|	tj| _d | _|
| _t | _d | _d| _d | _d| _d| _d | _t| jtrWd| _d| _td |j!t"|| j	| j d S )N)r   ResumableUploadr   FTzOInit _ResumableUploader, bucket: {0}, key: {1}, part_size: {2}, num_thread: {3})#r   r$   rj   ResumableStore_ResumableUploader__op_ResumableUploader__headersr   r"   r   _ResumableUploader__part_sizer   r    getmtime_ResumableUploader__mtimemultipart_num_threads_ResumableUploader__num_threads_ResumableUploader__upload_id_ResumableUploader__paramsrd   re   _ResumableUploader__lock_ResumableUploader__record!_ResumableUploader__finished_size"_ResumableUploader__finished_parts_ResumableUploader__encryption)_ResumableUploader__record_upload_context"_ResumableUploader__upload_contextr   r(   r   r   r   r   r   r   )rh   r(   r)   r*   r,   r+   r   r   r   r   r   r   r0   r1   rj     s0   

z_ResumableUploader.__init__c                 C   s   |    | | j}t|dd d}td| ttj	| j
|d| jg| j }|  | | j t| jttg}| jj| j| j| j|d}|   |S )Nc                 S   r   rk   r   r   r0   r0   r1   r   E  r   z+_ResumableUploader.upload.<locals>.<lambda>r   zParts need to upload: {0})parts_to_uploadr   )_ResumableUploader__load_record'_ResumableUploader__get_parts_to_uploadr  r   r   r   r   r   r   r   _ResumableUploader__producer_ResumableUploader__consumerr   r   rv   r,   r4   r   r5   OSS_OBJECT_ACLr(   complete_multipart_uploadr)   r   rn   )rh   r  r   r   r.   r0   r0   r1   r%   A  s   z_ResumableUploader.uploadc                 C   r   rk   r   )rh   r   r  r   r0   r0   r1   r   T  r   z_ResumableUploader.__producerc                 C   s"   	 |  }|d u rd S | | qrk   )r"   _ResumableUploader__upload_partr   r0   r0   r1   r   X  s   
z_ResumableUploader.__consumerc              	   C   s   t t| jdg}| | j ||jtj t	| j
ttg}| jr8| jj| j| j|jt||j|| jd}n| jj| j| j|jt||j|d}td|j|j|j | t|j|j|j|jd W d    d S 1 srw   Y  d S )Nr   )r   upload_contextr  zTUpload part success, add part info to record, part_number: {0}, etag: {1}, size: {2})r,   r   )r&   r   r*   rv   r  r   rQ   r   r   r4   r   r5   r6   r  r(   upload_partr)   r   r   r   SizedFileAdapterr,   r  r   r   r   r{   _ResumableUploader__finish_partr   crcr   r0   r0   r1   __upload_part`  s"    "z _ResumableUploader.__upload_partc                 C   sH   | j  | j| |  j|j7  _W d    d S 1 sw   Y  d S rk   )r   r  rL   r  r,   )rh   	part_infor0   r0   r1   r   r  s   "z _ResumableUploader.__finish_partc              	   C   s  |   }td| |r| |std |   d }|r4| |r4td| j |   d }|rM| 	|d sMtd|d  |   d }|st
| jtjg}t| j| j}td| j| j| | jrt| j|}| j| j| j||j}| jr|j}|j|jt|jt|j|j d}n| j| j| j|j}| j!|| j"| j| j#| jj$| j|d}| jr||d	< td
| jj$| j|| | %| || _&| j&d | _| j&d | _'| jr9d	| j&v r1| j&d	 }|d }|d }	|	| jj(j)j*ks|| jj(jkrd}
t+,|
| t-| jj(j)|d t.|d t.|d |d }t| j| j|| _/nd}
t+,|
| d	| j&v rGd}
t+0|
| | 1 | _2t3dd | j2D | _4d S )Nr   r   z-File: {0} has been changed, delete the record	upload_idz7Multipart upload: {0} does not exist, delete the recordzMUpload File size: {0}, User-specify part_size: {1}, Calculated part_size: {2})wrap_algcek_algencrypted_keyencrypted_ivmat_desc)r   r  r   r,   r|   r(   r)   r   content_crypto_materialzEAdd new record, bucket: {0}, key: {1}, upload_id: {2}, part_size: {3}r   r  r  z@Envelope or data encryption/decryption algorithm is inconsistentr  r  r  zUIf record_upload_context flag is true, content_crypto_material must in the the recordzWcontent_crypto_material must in the the record, but record_upload_context flat is falsec                 s   r   rk   r   r   r0   r0   r1   r     r   z3_ResumableUploader.__load_record.<locals>.<genexpr>)5rt   r   r   r   "_ResumableUploader__is_record_saner   rn    _ResumableUploader__file_changedr*   !_ResumableUploader__upload_existsr]   r   r   
SEQUENTIALrF   r,   r   r  r
   MultipartUploadCryptoContextr(   init_multipart_uploadr)   r   r  r  r  r  r  r   r  r  r  r   r`   r   r   rr   r  r   crypto_providercipheralgr   InconsistentErrorContentCryptoMaterialr   r  InvalidEncryptionRequest&_ResumableUploader__get_finished_partsr  r   r  )rh   rq   r   r   r  r  materialmaterial_recordr  r  err_msgr  r0   r0   r1   r   w  s   



"
z _ResumableUploader.__load_recordc                 C   s>   g }t | jttg}t| j| j| j|dD ]}|| q|S )Nr  )	rZ   r   OSS_SERVER_SIDE_ENCRYPTIONOSS_SERVER_SIDE_DATA_ENCRYPTIONr   r(   r)   r   rL   )rh   rN   r?   r   r0   r0   r1   __get_finished_parts  s   z'_ResumableUploader.__get_finished_partsc              	   C   sL   zt | jttg}ttj| j| j|dd|d W dS  t	j
y%   Y dS w )N0r   )	max_partsr   FT)rZ   r   r.  r/  r   r   r   r(   r)   r   NoSuchUpload)rh   r  r?   r0   r0   r1   __upload_exists  s    z"_ResumableUploader.__upload_existsc                 C   s   |d | j kp|d | jkS )Nr|   r,   )r   r,   rp   r0   r0   r1   __file_changed  r   z!_ResumableUploader.__file_changedc                 C   sL   t | j| j}|s|S tdd |D }|D ]}|j|v r!||j= q| S )Nc                 s   s    | ]}|j |fV  qd S rk   r   r   r0   r0   r1   r     s    z;_ResumableUploader.__get_parts_to_upload.<locals>.<genexpr>)rS   r,   r   r[   r   values)rh   parts_uploaded	all_partsall_parts_mapuploadedr0   r0   r1   __get_parts_to_upload  s   
z(_ResumableUploader.__get_parts_to_uploadc              
   C   s  zk|d | j krtd|d  W dS dD ]}t|| ts/td|||   W dS qdD ]}t|| tsJtd|||   W dS q2t|d tsft|d tsitd	|d  W dS W dS W dS  ty } ztd
|j	 W Y d }~dS d }~ww )Nr   r   F)r  r   r(   r)   z3Type Error, {0} in record is not a string type: {1})r,   r   z5Type Error, {0} in record is not an integer type: {1}r|   zBType Error, mtime in record is not a float or an integer type: {0}r   T)
r   r   r   r   r   r   r   floatr   r   r   r0   r0   r1   r     s8   		z#_ResumableUploader.__is_record_saner   rk   )rx   ry   rz   __doc__rj   r%   r  r  r  r  r	  r*  r   r  r
  r  r   r0   r0   r   r1   r$     s(    (
Q
r$   z.py-oss-uploadz.py-oss-downloadc                   @   s4   e Zd Zdd Zdd Zdd Zdd Zd	d
 ZdS )_ResumableStoreBasec                 C   sD   t d|| tj||| _tj| jrd S t	| j d S )Nz6Init ResumableStoreBase, root path: {0}, temp dir: {1})
r   r   r   r   r    r   dirisdirr   	makedir_prh   rootr?  r0   r0   r1   rj     s
   z_ResumableStoreBase.__init__c                 C   s   |  |}td|| tj|std| d S z&tt|d}t	
|}W d    n1 s6w   Y  W t|S W t|S  tyS   t| Y d S w )Nz4ResumableStoreBase: get key: {0} from file path: {1}zfile {0} is not existr)_ResumableStoreBase__pathr   r   r   r   r    r   r&   r   r   load
ValueErrorremover   )rh   r)   pathnamer/   contentr0   r0   r1   r"     s    

z_ResumableStoreBase.getc                 C   s\   |  |}tt|d}t|| W d    n1 sw   Y  td||| d S )Nwz>ResumableStoreBase: put key: {0} to file path: {1}, value: {2})rE  r&   r   r   dumpr   r   r   )rh   r)   valuerI  r/   r0   r0   r1   ro   ,  s
   
z_ResumableStoreBase.putc                 C   s*   |  |}t| td|| d S )Nz3ResumableStoreBase: delete key: {0}, file path: {1})rE  r   rH  r   r   r   )rh   r)   rI  r0   r0   r1   rl   4  s   

z_ResumableStoreBase.deletec                 C   s   t j| j|S rk   )r   r    r   r?  )rh   r)   r0   r0   r1   __path:  s   z_ResumableStoreBase.__pathN)rx   ry   rz   rj   r"   ro   rl   rE  r0   r0   r0   r1   r>    s    	r>  c                 C   s   t jt j| S rk   )r   r    normpathnormcase)r    r0   r0   r1   _normalize_path>  rs   rQ  c                       s.   e Zd ZdZd fdd	Zedd Z  ZS )r   u   保存断点上传断点信息的类。

    每次上传的信息会保存在 `root/dir/` 下面的某个文件里。

    :param str root: 父目录，缺省为HOME
    :param str dir: 子目录，缺省为 `_UPLOAD_TEMP_DIR`
    Nc                    &   t t| |ptjd|pt d S N~)r   r   rj   r   r    
expanduser_UPLOAD_TEMP_DIRrB  r   r0   r1   rj   K     &zResumableStore.__init__c                 C   s,   t |}d| |}t|d t| S )Noss://{0}/{1}--rQ  r   r   
md5_string)r   r)   r*   filepathoss_pathnamer0   r0   r1   rb   N  s   zResumableStore.make_store_keyrw   rx   ry   rz   r=  rj   r   rb   r   r0   r0   r   r1   r   B  s
    r   c                       s0   e Zd ZdZd fdd	ZedddZ  ZS )	r   u   保存断点下载断点信息的类。

    每次下载的断点信息会保存在 `root/dir/` 下面的某个文件里。

    :param str root: 父目录，缺省为HOME
    :param str dir: 子目录，缺省为 `_DOWNLOAD_TEMP_DIR`
    Nc                    rR  rS  )r   r   rj   r   r    rU  _DOWNLOAD_TEMP_DIRrB  r   r0   r1   rj   _  rW  zResumableDownloadStore.__init__c                 C   sD   t |}|d u rd| |}nd| ||}t|d t| S )NrX  zoss://{0}/{1}?versionid={2}rY  rZ  )r   r)   r*   
version_idr\  r]  r0   r0   r1   rb   b  s
   z%ResumableDownloadStore.make_store_keyrw   rk   r^  r0   r0   r   r1   r   V  s
    r   c                 C      t | |dS NrC  r?  )r   rc  r0   r0   r1   make_upload_storem     rd  c                 C   ra  rb  )r   rc  r0   r0   r1   make_download_storeq  re  rf  c                   @   s>   e Zd ZdddZedd Zdd Zdd	 Zed
d ZdS )rM   Nc                 C   s   || _ || _|| _|| _d S rk   r   )rh   r   rQ   rR   r   r0   r0   r1   rj   v  s   
z_PartToProcess.__init__c                 C   s   | j | j S rk   )rR   rQ   rm   r0   r0   r1   r,   |  s   z_PartToProcess.sizec                 C   s
   t | jS rk   )hash_PartToProcess__keyrm   r0   r0   r1   __hash__  s   
z_PartToProcess.__hash__c                 C   s   | j |j kS rk   )rh  )rh   otherr0   r0   r1   __eq__  re  z_PartToProcess.__eq__c                 C   s   | j | j| jfS rk   )r   rQ   rR   rm   r0   r0   r1   __key  s   z_PartToProcess.__keyrk   )	rx   ry   rz   rj   propertyr,   ri  rk  rh  r0   r0   r0   r1   rM   u  s    

rM   )NNNNNNNrk   rw   )7r=  r   r   r   r   r   r   r   r   r	   r
   crypto_bucketr   r   r   r   compatr   r   r   r   
task_queuer   r   r   rd   r   r   logging	getLoggerrx   r   r2   rA   r   rF   rB   rS   r4   rZ   r]   objectr^   r:   r9   r$   rV  r_  r>  rQ  r   r   rd  rf  rM   r0   r0   r0   r1   <module>   sz   

A
B




& 4 1

