diff --git a/README.md b/README.md index ff92b8c..4301a60 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,10 @@ +Version 3.24.3 + +New Features: + +1. Added APIs related to accessLabel, including ObsClient.setAccesslabel,ObsClient.getAccessLabel and ObsClient.deleteAccessLabel. + +------------------------------------------------------------------------------------------------- Version 3.23.12 Resolved Issues: diff --git a/README_CN.md b/README_CN.md index a983f0c..b2cd284 100644 --- a/README_CN.md +++ b/README_CN.md @@ -1,6 +1,13 @@ -Version 3.23.12 +Version 3.24.3 -修复问题 +新特性: + +1. 新增accessLabel相关接口(ObsClient.setAccesslabel/ObsClient.getAccessLabel/ObsClient.deleteAccessLabel) + +------------------------------------------------------------------------------------------------- +Version 3.23.12 + +修复问题: 1. 修复putFile上传文件夹时可能导致contentType不一致问题。 diff --git a/src/__init__.py b/src/__init__.py index 7529392..dab93a7 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1,3 +1,4 @@ +#!/usr/bin/python # -*- coding:utf-8 -*- # Copyright 2019 Huawei Technologies Co.,Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); you may not use diff --git a/src/obs/client.py b/src/obs/client.py index 9867502..4242879 100644 --- a/src/obs/client.py +++ b/src/obs/client.py @@ -670,8 +670,12 @@ def _get_server_connection_use_http1x(self, is_secure, server, port, proxy_host, except Exception: conn = httplib.HTTPSConnection(server, port=port, timeout=self.timeout) else: - conn = httplib.HTTPSConnection(server, port=port, timeout=self.timeout, context=self.context, - check_hostname=None) + try: + conn = httplib.HTTPSConnection(server, port=port, timeout=self.timeout, context=self.context, + check_hostname=None) + except Exception: + conn = httplib.HTTPSConnection(server, port=port, timeout=self.timeout, context=self.context) + else: conn = httplib.HTTPConnection(server, port=port, timeout=self.timeout) @@ -1567,6 +1571,23 @@ def setObjectMetadata(self, bucketName, objectKey, metadata=None, headers=None, **self.convertor.trans_set_object_metadata(metadata=metadata, headers=headers, versionId=versionId)) + @funcCache + def setAccessLabel(self, bucketName, objectKey, accesslabel, extensionHeaders=None): + return self._make_put_request(bucketName, objectKey, pathArgs={'x-obs-accesslabel': None}, + entity={'accesslabel': accesslabel}, + extensionHeaders=extensionHeaders) + + @funcCache + def getAccessLabel(self, bucketName, objectKey, extensionHeaders=None): + return self._make_get_request(bucketName, objectKey, pathArgs={'x-obs-accesslabel': None}, + methodName='getAccessLabel', + extensionHeaders=extensionHeaders) + + @funcCache + def deleteAccessLabel(self, bucketName, objectKey, extensionHeaders=None): + return self._make_delete_request(bucketName, objectKey, pathArgs={'x-obs-accesslabel': None}, + extensionHeaders=extensionHeaders) + @funcCache def getObject(self, bucketName, objectKey, downloadPath=None, getObjectRequest=None, headers=None, loadStreamInMemory=False, progressCallback=None, extensionHeaders=None, notifier=None): diff --git a/src/obs/const.py b/src/obs/const.py index 012ce77..4ea2ef9 100644 --- a/src/obs/const.py +++ b/src/obs/const.py @@ -21,7 +21,7 @@ CONTENT_LENGTH_HEADER = 'Content-Length' CONTENT_TYPE_HEADER = 'Content-Type' CONTENT_MD5_HEADER = 'Content-MD5' -CACHE_CONTROL_HEADER = 'Cache-Control' +CACHE_CONTROL_HEADER = 'Cache-Control' # type: str CONTENT_DISPOSITION_HEADER = 'Content-Disposition' CONTENT_ENCODING_HEADER = 'Content-Encoding' CONTENT_LANGUAGE_HEADER = 'Content-Language' @@ -96,7 +96,7 @@ DEFAULT_TASK_NUM = 8 DEFAULT_TASK_QUEUE_SIZE = 20000 -OBS_SDK_VERSION = '3.23.12' +OBS_SDK_VERSION = '3.24.3' V2_META_HEADER_PREFIX = 'x-amz-meta-' V2_HEADER_PREFIX = 'x-amz-' diff --git a/src/obs/convertor.py b/src/obs/convertor.py index 8948569..9cb332b 100644 --- a/src/obs/convertor.py +++ b/src/obs/convertor.py @@ -1919,6 +1919,10 @@ def parseSetObjectMetadata(self, headers): option.nextPosition = util.to_long(headers.get(self.ha.next_position_header())) return option + def parseGetAccessLabel(self, jsons, headers=None): + result = json.loads(jsons) + return result + def parseGetObject(self, headers, option): self._parseGetObjectCommonHeader(headers, option) option.deleteMarker = headers.get(self.ha.delete_marker_header()) diff --git a/src/setup.py b/src/setup.py index 57ea472..aa22801 100644 --- a/src/setup.py +++ b/src/setup.py @@ -1,3 +1,4 @@ +#!/usr/bin/python # -*- coding:utf-8 -*- # Copyright 2019 Huawei Technologies Co.,Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); you may not use @@ -21,7 +22,7 @@ setup( name='esdk-obs-python', - version='3.23.12', + version='3.24.3', packages=find_packages(exclude=['tests']), zip_safe=False, description='OBS Python SDK', diff --git a/src/tests/test_obs_client.py b/src/tests/test_obs_client.py index 9861441..4218cf6 100644 --- a/src/tests/test_obs_client.py +++ b/src/tests/test_obs_client.py @@ -22,8 +22,8 @@ import conftest from obs import CreateBucketHeader, GetObjectHeader, ObsClient, UploadFileHeader, \ -Expiration, NoncurrentVersionExpiration, AbortIncompleteMultipartUpload, DateTime, \ -Rule, Lifecycle + Expiration, NoncurrentVersionExpiration, AbortIncompleteMultipartUpload, DateTime, \ + Rule, Lifecycle from conftest import test_config @@ -62,8 +62,8 @@ def test_create_PFS_bucket(self, delete_bucket_after_test): def test_delete_posix_folder(self): client_type, uploadClient, deleteClient = self.get_client() bucket_name = test_config["bucketName"] - file1 =test_config["path_prefix"] + "file-001" - file2 =test_config["path_prefix"] + "file-002" + file1 = test_config["path_prefix"] + "file-001" + file2 = test_config["path_prefix"] + "file-002" upload_result1 = uploadClient.putContent(bucket_name, file1, content='Hello OBS') assert upload_result1.status == 200 upload_result2 = uploadClient.putContent(bucket_name, file2, content='Hello OBS') @@ -72,7 +72,6 @@ def test_delete_posix_folder(self): assert len(delete_list) == 3 assert len(error_list) == 0 - def test_create_object_bucket(self, delete_bucket_after_test): _, uploadClient, _ = self.get_client() bucket_name = test_config["bucket_prefix"] + "create-pfs-002" @@ -421,14 +420,12 @@ def test_putFile_with_content_type(self): assert new_content_list == old_content_list - - def test_setBucketLifecycle_and_getBucketLifecycle_success(self): client_type, bucketLifecycleClient, obsClient = self.get_client() rule1 = Rule(id='rule1', prefix='prefix1', status='Enabled', expiration=Expiration(days=60), - noncurrentVersionExpiration=NoncurrentVersionExpiration(10)) + noncurrentVersionExpiration=NoncurrentVersionExpiration(10)) rule2 = Rule(id='rule2', prefix='prefix2', status='Enabled', expiration=Expiration(date=DateTime(2023, 12, 31)), - abortIncompleteMultipartUpload=AbortIncompleteMultipartUpload(10)) + abortIncompleteMultipartUpload=AbortIncompleteMultipartUpload(10)) lifecycle = Lifecycle(rule=[rule1, rule2]) set_rul_result = bucketLifecycleClient.setBucketLifecycle(test_config["bucketName"], lifecycle) assert set_rul_result.status == 200 @@ -436,6 +433,91 @@ def test_setBucketLifecycle_and_getBucketLifecycle_success(self): assert get_rul_result.status == 200 assert get_rul_result.body.lifecycleConfig.rule[1].abortIncompleteMultipartUpload.daysAfterInitiation == 10 + def test_setAccessLabel_success(self): + client_type, accessLabelClient, obsClient = self.get_client() + accessLabelList = ['role_label_01', 'role_label_02'] + obsClient.putContent('pythonsdktestbucket-posix', 'dir1/') + set_al_result = accessLabelClient.setAccessLabel('pythonsdktestbucket-posix', 'dir1', accessLabelList) + assert set_al_result.status == 204 + obsClient.deleteObject('pythonsdktestbucket-posix', 'dir1/') + + def test_setAccessLabel_fail(self): + client_type, accessLabelClient, obsClient = self.get_client() + obsClient.putContent('pythonsdktestbucket-posix', 'dir1/') + obsClient.putContent('pythonsdktestbucket-posix', 'file1', content='123') + set_al_result1 = accessLabelClient.setAccessLabel('pythonsdktestbucket-posix', 'dir1', ['role-label-01']) + assert set_al_result1.status == 400 + set_al_result2 = accessLabelClient.setAccessLabel('pythonsdktestbucket-posix', 'dir1', + ['abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ']) + assert set_al_result2.status == 400 + set_al_result3 = accessLabelClient.setAccessLabel('pythonsdktestbucket-posix', 'dir1', + ["role_label_" + str(i + 1) for i in range(513)]) + assert set_al_result3.status == 405 + set_al_result4 = accessLabelClient.setAccessLabel('pythonsdktestbucket-posix', 'file1', + ['role_label_01', 'role_label_02']) + assert set_al_result4.status == 405 + obsClient.deleteObject('pythonsdktestbucket-posix', 'dir1/') + obsClient.deleteObject('pythonsdktestbucket-posix', 'file1') + + def test_getAccessLabel_success(self): + client_type, accessLabelClient, obsClient = self.get_client() + obsClient.putContent('pythonsdktestbucket-posix', 'dir1/') + obsClient.putContent('pythonsdktestbucket-posix', 'dir2/') + obsClient.putContent('pythonsdktestbucket-posix', 'dir3/') + obsClient.putContent('pythonsdktestbucket-posix', 'dir4/') + accessLabelClient.setAccessLabel('pythonsdktestbucket-posix', 'dir1', ['role_label_01', 'role_label_02']) + get_al_result1 = accessLabelClient.getAccessLabel('pythonsdktestbucket-posix', 'dir1') + assert get_al_result1.status == 200 + assert get_al_result1.body['accesslabel'] == ['role_label_01', 'role_label_02'] + accessLabelClient.setAccessLabel('pythonsdktestbucket-posix', 'dir2', + ['abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ']) + get_al_result2 = accessLabelClient.getAccessLabel('pythonsdktestbucket-posix', 'dir2') + assert get_al_result2.status == 200 + assert get_al_result2.body['accesslabel'] == ['abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'] + accessLabelClient.setAccessLabel('pythonsdktestbucket-posix', 'dir3', + ["role_label_" + str(i + 1) for i in range(512)]) + get_al_result3 = accessLabelClient.getAccessLabel('pythonsdktestbucket-posix', 'dir3') + assert get_al_result3.status == 200 + assert get_al_result3.body['accesslabel'] == ["role_label_" + str(i + 1) for i in range(512)] + accessLabelClient.setAccessLabel('pythonsdktestbucket-posix', 'dir4', + ["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW" + str(i + 1) for i in + range(512)]) + get_al_result4 = accessLabelClient.getAccessLabel('pythonsdktestbucket-posix', 'dir4') + assert get_al_result4.status == 200 + assert get_al_result4.body['accesslabel'] == ["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW" + str(i + 1) for + i in range(512)] + obsClient.deleteObject('pythonsdktestbucket-posix', 'dir1/') + obsClient.deleteObject('pythonsdktestbucket-posix', 'dir2/') + obsClient.deleteObject('pythonsdktestbucket-posix', 'dir3/') + obsClient.deleteObject('pythonsdktestbucket-posix', 'dir4/') + + def test_getAccessLabel_fail(self): + client_type, accessLabelClient, obsClient = self.get_client() + obsClient.putContent('pythonsdktestbucket-posix', 'dir1/') + get_al_result = accessLabelClient.getAccessLabel('pythonsdktestbucket-posix', 'dir1') + assert get_al_result.status == 404 + obsClient.deleteObject('pythonsdktestbucket-posix', 'dir1/') + + def test_deleteAccessLabel_success(self): + client_type, accessLabelClient, obsClient = self.get_client() + obsClient.putContent('pythonsdktestbucket-posix', 'dir1/') + obsClient.putContent('pythonsdktestbucket-posix', 'dir2/') + accessLabelClient.setAccessLabel('pythonsdktestbucket-posix', 'dir1', ['role_label_01', 'role_label_02']) + del_al_result1 = accessLabelClient.deleteAccessLabel('pythonsdktestbucket-posix', 'dir1') + del_al_result2 = accessLabelClient.deleteAccessLabel('pythonsdktestbucket-posix', 'dir2') + del_al_result3 = accessLabelClient.deleteAccessLabel('pythonsdktestbucket-posix', 'dir3') + assert del_al_result1.status == 204 + assert del_al_result2.status == 204 + assert del_al_result3.status == 204 + obsClient.deleteObject('pythonsdktestbucket-posix', 'dir1/') + obsClient.deleteObject('pythonsdktestbucket-posix', 'dir2/') + + def test_deleteAccessLabel_fail(self): + client_type, accessLabelClient, obsClient = self.get_client() + obsClient.putContent('pythonsdktestbucket-posix', 'file1', content='123') + del_al_result1 = accessLabelClient.deleteAccessLabel('pythonsdktestbucket-posix', 'file1') + assert del_al_result1.status == 405 + obsClient.deleteObject('pythonsdktestbucket-posix', 'file1') if __name__ == "__main__": pytest.main(["-v", 'test_obs_client.py::TestOBSClient::test_uploadFile_with_metadata'])