@@ -44,7 +44,7 @@ def __init__(self, Appid=None, Region=None, SecretId=None, SecretKey=None, Token
44
44
Access_id = None , Access_key = None , Secret_id = None , Secret_key = None , Endpoint = None , IP = None , Port = None ,
45
45
Anonymous = None , UA = None , Proxies = None , Domain = None , ServiceDomain = None , KeepAlive = True , PoolConnections = 10 ,
46
46
PoolMaxSize = 10 , AllowRedirects = False , SignHost = True , EndpointCi = None , EndpointPic = None , EnableOldDomain = True , EnableInternalDomain = True , SignParams = True ,
47
- AutoSwitchDomainOnRetry = True ):
47
+ AutoSwitchDomainOnRetry = False ):
48
48
"""初始化,保存用户的信息
49
49
50
50
:param Appid(string): 用户APPID.
@@ -359,6 +359,7 @@ def send_request(self, method, url, bucket, timeout=30, cos_request=True, ci_req
359
359
kwargs ['verify' ] = False
360
360
if self ._conf ._allow_redirects is not None :
361
361
kwargs ['allow_redirects' ] = self ._conf ._allow_redirects
362
+ exception_logbuf = list () # 记录每次重试的错误日志
362
363
for j in range (self ._retry + 1 ):
363
364
try :
364
365
if j != 0 :
@@ -397,13 +398,16 @@ def send_request(self, method, url, bucket, timeout=30, cos_request=True, ci_req
397
398
else :
398
399
break
399
400
except Exception as e : # 捕获requests抛出的如timeout等客户端错误,转化为客户端错误
400
- logger .exception ('url:%s, retry_time:%d exception:%s' % (url , j , str (e )))
401
+ # 记录每次请求的exception
402
+ exception_log = 'url:%s, retry_time:%d exception:%s' % (url , j , str (e ))
403
+ exception_logbuf .append (exception_log )
401
404
if j < self ._retry and (isinstance (e , ConnectionError ) or isinstance (e , Timeout )): # 只重试网络错误
402
405
if client_can_retry (file_position , ** kwargs ):
403
406
if not domain_switched and self ._conf ._auto_switch_domain_on_retry and self ._conf ._ip is None :
404
407
url = switch_hostname_for_url (url )
405
408
domain_switched = True
406
409
continue
410
+ logger .exception (exception_logbuf ) # 最终重试失败, 输出前几次重试失败的exception
407
411
raise CosClientError (str (e ))
408
412
409
413
if not cos_request :
@@ -419,12 +423,16 @@ def send_request(self, method, url, bucket, timeout=30, cos_request=True, ci_req
419
423
if 'x-cos-trace-id' in res .headers :
420
424
info ['traceid' ] = res .headers ['x-cos-trace-id' ]
421
425
logger .warn (info )
426
+ if len (exception_logbuf ) > 0 :
427
+ logger .exception (exception_logbuf ) # 最终重试失败, 输出前几次重试失败的exception
422
428
raise CosServiceError (method , info , res .status_code )
423
429
else :
424
430
msg = res .text
425
431
if msg == u'' : # 服务器没有返回Error Body时 给出头部的信息
426
432
msg = res .headers
427
433
logger .error (msg )
434
+ if len (exception_logbuf ) > 0 :
435
+ logger .exception (exception_logbuf ) # 最终重试失败, 输出前几次重试失败的exception
428
436
raise CosServiceError (method , msg , res .status_code )
429
437
430
438
return None
@@ -1613,7 +1621,7 @@ def head_bucket(self, Bucket, **kwargs):
1613
1621
1614
1622
:param Bucket(string): 存储桶名称.
1615
1623
:param kwargs(dict): 设置请求headers.
1616
- :return: None .
1624
+ :return: HEAD Bucket响应头域 .
1617
1625
1618
1626
.. code-block:: python
1619
1627
@@ -1635,7 +1643,7 @@ def head_bucket(self, Bucket, **kwargs):
1635
1643
bucket = Bucket ,
1636
1644
auth = CosS3Auth (self ._conf ),
1637
1645
headers = headers )
1638
- return None
1646
+ return rt . headers
1639
1647
1640
1648
def put_bucket_acl (self , Bucket , AccessControlPolicy = {}, ** kwargs ):
1641
1649
"""设置bucket ACL
@@ -2926,7 +2934,7 @@ def get_bucket_inventory(self, Bucket, Id, **kwargs):
2926
2934
return data
2927
2935
2928
2936
def delete_bucket_inventory (self , Bucket , Id , ** kwargs ):
2929
- """删除bucket 回源配置
2937
+ """删除bucket清单规则
2930
2938
2931
2939
:param Bucket(string): 存储桶名称.
2932
2940
:param Id(string): 清单规则名称.
@@ -2957,6 +2965,52 @@ def delete_bucket_inventory(self, Bucket, Id, **kwargs):
2957
2965
params = params )
2958
2966
return None
2959
2967
2968
+ def list_bucket_inventory_configurations (self , Bucket , ContinuationToken = None , ** kwargs ):
2969
+ """列举存储桶清单规则
2970
+
2971
+ :param Bucket(string): 存储桶名称
2972
+ :param ContinuationToken(string): 分页参数, 用以获取下一页信息
2973
+ :param kwargs(dict): 设置请求headers.
2974
+ :return(dict): 存储桶清单规则列表
2975
+
2976
+ .. code-block:: python
2977
+
2978
+ config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象
2979
+ client = CosS3Client(config)
2980
+ # 分页列举bucket清单规则
2981
+ continuation_token = ''
2982
+ while True:
2983
+ resp = client.list_bucket_inventory_configurations(
2984
+ Bucket=bucket,
2985
+ ContinuationToken=continuation_token,
2986
+ )
2987
+ if 'InventoryConfiguration' in resp:
2988
+ for conf in resp['InventoryConfiguration']:
2989
+ print(conf)
2990
+ if resp['IsTruncated'] == 'true':
2991
+ continuation_token = resp['NextContinuationToken']
2992
+ else:
2993
+ break
2994
+ """
2995
+ headers = mapped (kwargs )
2996
+ params = {'inventory' : '' }
2997
+ if ContinuationToken is not None :
2998
+ params ['continuation-token' ] = ContinuationToken
2999
+ url = self ._conf .uri (bucket = Bucket )
3000
+ logger .info ("list bucket inventory configurations, url={url}, headers={headers}" .format (
3001
+ url = url ,
3002
+ headers = headers ,
3003
+ ))
3004
+ rt = self .send_request (
3005
+ method = 'GET' ,
3006
+ url = url ,
3007
+ bucket = Bucket ,
3008
+ auth = CosS3Auth (self ._conf , params = params ),
3009
+ headers = headers ,
3010
+ params = params )
3011
+ data = xml_to_dict (rt .content )
3012
+ return data
3013
+
2960
3014
def put_object_tagging (self , Bucket , Key , Tagging = {}, ** kwargs ):
2961
3015
"""设置object的标签
2962
3016
@@ -3560,7 +3614,7 @@ def _check_all_upload_parts(self, bucket, key, uploadid, local_path, parts_num,
3560
3614
already_exist_parts [part_num ] = part ['ETag' ]
3561
3615
return True
3562
3616
3563
- def download_file (self , Bucket , Key , DestFilePath , PartSize = 20 , MAXThread = 5 , EnableCRC = False , progress_callback = None , ** Kwargs ):
3617
+ def download_file (self , Bucket , Key , DestFilePath , PartSize = 20 , MAXThread = 5 , EnableCRC = False , progress_callback = None , DumpRecordDir = None , ** Kwargs ):
3564
3618
"""小于等于20MB的文件简单下载,大于20MB的文件使用续传下载
3565
3619
3566
3620
:param Bucket(string): 存储桶名称.
@@ -3596,7 +3650,7 @@ def download_file(self, Bucket, Key, DestFilePath, PartSize=20, MAXThread=5, Ena
3596
3650
callback = ProgressCallback (file_size , progress_callback )
3597
3651
3598
3652
downloader = ResumableDownLoader (self , Bucket , Key , DestFilePath , object_info , PartSize , MAXThread , EnableCRC ,
3599
- callback , ** Kwargs )
3653
+ callback , DumpRecordDir , ** Kwargs )
3600
3654
downloader .start ()
3601
3655
3602
3656
def upload_file (self , Bucket , Key , LocalFilePath , PartSize = 1 , MAXThread = 5 , EnableMD5 = False , progress_callback = None ,
0 commit comments