Skip to content

Commit 0c563da

Browse files
author
chenjing.cjcj
committed
v2.6.10
1 parent 75ae51f commit 0c563da

File tree

7 files changed

+126
-19
lines changed

7 files changed

+126
-19
lines changed

CHANGELOG.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
TOS SDK for Python 版本记录
22
===========================
3+
Version 2.6.10
4+
-------------
5+
- 增加:get_fetch_task接口
6+
37
Version 2.6.9
48
-------------
59
- 增加:软链接相关接口

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ You can put your file as an object into your own bucket.
5151
```python
5252
# call put_object to upload you data to the TOS
5353
client.put_object(bucket_name, object_key, content="123")
54-
assert resp.status == 200
54+
assert resp.status_code == 200
5555
```
5656
## Get Object
5757
You can download objects in the TOS bucket through our SDK.

tests/test_v2_bucket.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ def test_bucket_mirror(self):
231231
redirect=Redirect(
232232
redirect_type=RedirectType.Mirror,
233233
fetch_source_on_redirect=True,
234-
public_source=PublicSource(SourceEndpoint(primary=['http://tosv.byted.org/obj/tostest/'])),
234+
public_source=PublicSource(SourceEndpoint(primary=['http://test.com/obj/tostest/'])),
235235
pass_query=True,
236236
follow_redirect=True,
237237
mirror_header=MirrorHeader(pass_all=True, pass_headers=['aaa', 'bbb'], remove=['xxx', 'xxx']),
@@ -253,7 +253,7 @@ def test_bucket_mirror(self):
253253
self.assertEqual(get_out.rules[0].redirect.mirror_header.pass_headers, ['aaa', 'bbb'])
254254
self.assertEqual(get_out.rules[0].redirect.mirror_header.remove, ['xxx', 'xxx'])
255255
self.assertEqual(get_out.rules[0].redirect.public_source.source_endpoint.primary,
256-
['http://tosv.byted.org/obj/tostest/'])
256+
['http://test.com/obj/tostest/'])
257257
self.assertEqual(get_out.rules[0].redirect.public_source.fixed_endpoint, None)
258258
self.assertEqual(get_out.rules[0].redirect.transform.with_key_prefix, 'prefix')
259259
self.assertEqual(get_out.rules[0].redirect.transform.with_key_suffix, 'suffix')

tests/test_v2_object.py

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,18 @@ def test_with_stream(self):
324324
key = self.random_key('.js')
325325
self.client.create_bucket(bucket_name)
326326
self.bucket_delete.append(bucket_name)
327-
conn = http.client.HTTPConnection('www.volcengine.com', 80)
328-
conn.request('GET', '/')
327+
key2 = self.random_key('.js')
328+
self.client.put_object(bucket_name, key2, content=random_bytes(20), acl=ACLType.ACL_Public_Read_Write)
329+
330+
endpoint = self.endpoint
331+
if self.endpoint.startswith('http://'):
332+
endpoint = self.endpoint[7:]
333+
elif self.endpoint.startswith('https://'):
334+
endpoint = self.endpoint[:8]
335+
bucket_endpoint = '{}.{}'.format(bucket_name, endpoint)
336+
object_endpoint = bucket_endpoint + '/' + key2
337+
conn = http.client.HTTPConnection(bucket_endpoint)
338+
conn.request('GET', '/'+key2)
329339
content = conn.getresponse()
330340

331341
def generator():
@@ -351,18 +361,20 @@ def generator():
351361

352362
self.client.put_object(bucket_name, key, content=content)
353363
out = self.client.get_object(bucket_name, key)
354-
conn = http.client.HTTPConnection('www.volcengine.com', 80)
355-
conn.request('GET', '/')
364+
conn = http.client.HTTPConnection(bucket_endpoint)
365+
conn.request('GET', '/' + key2)
356366
content = conn.getresponse()
357367
buf = b''
358368
for chuck in content:
359369
buf += chuck
360370
self.assertEqual(len(buf), len(out.read()))
361371

362-
input = requests.get('https://www.volcengine.com')
372+
if not object_endpoint.startswith('http://') or not object_endpoint.startswith('https://'):
373+
object_endpoint = 'http://' + object_endpoint
374+
input = requests.get(object_endpoint)
363375
self.client.put_object(bucket_name, key, content=input)
364376
out = self.client.get_object(bucket_name, key)
365-
self.assertEqual(len(out.read()), len(requests.get('https://www.volcengine.com').text))
377+
self.assertEqual(len(out.read()), len(requests.get(object_endpoint).text))
366378
conn.close()
367379

368380
def test_object_with_iterm(self):
@@ -1096,11 +1108,26 @@ def test_fetch_task_object(self):
10961108

10971109
self.client.create_bucket(bucket=bucket_fetch)
10981110
self.client.put_object(bucket=bucket_fetch, key=key, acl=ACLType.ACL_Public_Read_Write)
1099-
url = 'http://{}.{}'.format(bucket_fetch, self.endpoint) + '/' + key
1111+
endpoint = self.endpoint
1112+
if self.endpoint.startswith('http://'):
1113+
endpoint = self.endpoint[7:]
1114+
elif self.endpoint.startswith('https://'):
1115+
endpoint = self.endpoint[:8]
1116+
1117+
url = 'http://{}.{}'.format(bucket_fetch, endpoint) + '/' + key
11001118
self.client.create_bucket(bucket=bucket_name)
1101-
out = self.client.put_fetch_task(bucket=bucket_name, key=key, url=url)
1119+
raw = "!@#$%^&*()_+-=[]{}|;':\",./<>?中文测试编码%20%%%^&abcd /\\"
1120+
meta = {'name': ' %张/三%', 'age': '12', 'special': raw, raw: raw}
1121+
out = self.client.put_fetch_task(bucket=bucket_name, key=key, url=url, meta=meta,
1122+
acl=ACLType.ACL_Public_Read_Write,
1123+
storage_class=StorageClassType.Storage_Class_Ia)
11021124
self.assertIsNotNone(out.task_id)
1103-
time.sleep(10)
1125+
get_out = self.client.get_fetch_task(bucket=bucket_name, task_id=out.task_id)
1126+
self.assertEqual(get_out.task.meta['name'], meta['name'])
1127+
self.assertEqual(get_out.task.meta['special'], meta['special'])
1128+
self.assertEqual(get_out.task.meta[raw], meta[raw])
1129+
self.assertEqual(get_out.task.acl, ACLType.ACL_Public_Read_Write)
1130+
self.assertEqual(get_out.task.storage_class, StorageClassType.Storage_Class_Ia)
11041131

11051132
def test_post_object(self):
11061133
bucket_name = self.bucket_name + '-post-object'
@@ -1429,7 +1456,7 @@ def test_symlink(self):
14291456
self.client2.create_bucket(bucket_name2)
14301457
self.bucket_delete.append(bucket_name2)
14311458

1432-
dst_key = 'dst_key'
1459+
dst_key = 'abc中文测试%1 ? # */~'
14331460
symlink_key = 'symlink_key'
14341461
content = random_bytes(100)
14351462
self.client2.put_object(bucket_name, dst_key, content=content)

tos/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = 'v2.6.9'
1+
__version__ = 'v2.6.10'

tos/clientv2.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
PolicySignatureCondition, RestoreObjectOutput, RestoreJobParameters, RenameObjectOutput,
7070
PutBucketRenameOutput, DeleteBucketRenameOutput, GetBucketRenameOutput, PutBucketTaggingOutput,
7171
DeleteBucketTaggingOutput, GetBucketTaggingOutput, PutSymlinkOutput, GetSymlinkOutput,
72-
GenericInput)
72+
GenericInput, GetFetchTaskOutput)
7373
from .thread_ctx import consume_body
7474
from .utils import (SizeAdapter, _make_copy_source,
7575
_make_range_string, _make_upload_part_file_content,
@@ -595,7 +595,7 @@ def _get_put_acl_headers(ACL, GrantFullControl, GrantRead, GrantReadACP, GrantWr
595595

596596

597597
def _get_put_symlink_headers(TargetKey, TargetBucket, ACL, StorageClass, Metadata, ForbidOverwrite):
598-
headers = {"x-tos-symlink-target": TargetKey}
598+
headers = {"x-tos-symlink-target": urllib.parse.quote(TargetKey, '/~')}
599599
if TargetBucket:
600600
headers["x-tos-symlink-bucket"] = TargetBucket
601601
if ACL:
@@ -3351,11 +3351,26 @@ def put_fetch_task(self, bucket: str, key: str, url: str,
33513351
data = to_fetch_object(url, key, ignore_same_key, hex_md5)
33523352
data = json.dumps(data)
33533353

3354-
resp = self._req(bucket=bucket, key=key, params={'fetchTask': ''}, headers=headers,
3354+
resp = self._req(bucket=bucket, params={'fetchTask': ''}, headers=headers,
33553355
method=HttpMethodType.Http_Method_Post.value, data=data, generic_input=generic_input)
33563356

33573357
return PutFetchTaskOutput(resp)
33583358

3359+
def get_fetch_task(self, bucket: str, task_id: str,
3360+
generic_input: GenericInput = None) -> GetFetchTaskOutput:
3361+
""" 获取 fetch 任务
3362+
3363+
:param bucket: 桶名
3364+
:param task_id: 任务id
3365+
:param generic_input: 通用请求参数,比如request_date设置签名UTC时间,代表本次请求Header中指定的 X-Tos-Date 头域
3366+
:return: GetFetchTaskOutput
3367+
"""
3368+
3369+
param = {'fetchTask': '', 'taskId': task_id}
3370+
resp = self._req(bucket=bucket, params=param, method=HttpMethodType.Http_Method_Get.value,
3371+
generic_input=generic_input)
3372+
return GetFetchTaskOutput(resp)
3373+
33593374
def put_bucket_replication(self, bucket: str, role: str,
33603375
rules: list, generic_input: GenericInput = None) -> PutBucketReplicationOutput:
33613376
""" 设置桶的跨区域复制规则

tos/models2.py

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
StorageClassInheritDirectiveType, VersioningStatusType, ProtocolType, CertStatus, AzRedundancyType, \
99
convert_storage_class_type, convert_az_redundancy_type, convert_permission_type, convert_grantee_type, \
1010
convert_canned_type, convert_redirect_type, convert_status_type, convert_versioning_status_type, \
11-
convert_protocol_type, convert_cert_status, TierType, convert_tier_type
11+
convert_protocol_type, convert_cert_status, TierType, convert_tier_type, ACLType
1212
from .consts import CHUNK_SIZE
1313
from .exceptions import TosClientError, make_server_error_with_exception
1414
from .models import CommonPrefixInfo, DeleteMarkerInfo
@@ -1343,6 +1343,67 @@ def __init__(self, resp):
13431343
self.task_id = get_value(data, 'TaskId')
13441344

13451345

1346+
class FetchTask(object):
1347+
def __init__(self, bucket: str = None, key: str = None, url: str = None, ignore_same_key: bool = None,
1348+
content_md5: str = None, callback_url: str = None, callback_host: str = None,
1349+
callback_body_type: str = None, callback_body: str = None, storage_class: StorageClassType = None,
1350+
acl: ACLType = None, grant_full_control: str = None, grant_read: str = None,
1351+
grant_read_acp: str = None, grant_write_acp: str = None, ssec_algorithm: str = None,
1352+
ssec_key: str = None, ssec_key_md5: str = None, meta: dict = None):
1353+
self.bucket = bucket
1354+
self.key = key
1355+
self.url = url
1356+
self.ignore_same_key = ignore_same_key
1357+
self.content_md5 = content_md5
1358+
self.callback_url = callback_url
1359+
self.callback_host = callback_host
1360+
self.callback_body_type = callback_body_type
1361+
self.callback_body = callback_body
1362+
self.storage_class = storage_class
1363+
self.acl = acl
1364+
self.grant_full_control = grant_full_control
1365+
self.grant_read = grant_read
1366+
self.grant_read_acp = grant_read_acp
1367+
self.grant_write_acp = grant_write_acp
1368+
self.ssec_algorithm = ssec_algorithm
1369+
self.ssec_key = ssec_key
1370+
self.ssec_key_md5 = ssec_key_md5
1371+
self.meta = meta
1372+
1373+
1374+
class GetFetchTaskOutput(ResponseInfo):
1375+
def __init__(self, resp):
1376+
super(GetFetchTaskOutput, self).__init__(resp)
1377+
data = resp.json_read()
1378+
self.state = get_value(data, 'State')
1379+
self.err = get_value(data, 'Err')
1380+
task = get_value(data, 'Task')
1381+
meta = {}
1382+
for m in task.get('UserMeta', []):
1383+
meta[m['Key']] = m['Value']
1384+
meta = meta_header_decode(meta)
1385+
self.task = FetchTask(
1386+
bucket=get_value(task, 'Bucket'),
1387+
key=get_value(task, 'Key'),
1388+
url=get_value(task, 'URL'),
1389+
ignore_same_key=get_value(task, 'IgnoreSameKey', lambda x: bool(x)),
1390+
callback_url=get_value(task, 'CallBackURL'),
1391+
callback_host=get_value(task, 'CallbackHost'),
1392+
callback_body=get_value(task, 'CallBackBody'),
1393+
callback_body_type=get_value(task, 'CallBackBodyType'),
1394+
storage_class=get_value(task, 'StorageClass', lambda x: StorageClassType(x)),
1395+
acl=get_value(task, 'Acl', lambda x: ACLType(x)),
1396+
grant_full_control=get_value(task, 'GrantFullControl'),
1397+
grant_read=get_value(task, 'GrantRead'),
1398+
grant_read_acp=get_value(task, 'GrantReadAcp'),
1399+
grant_write_acp=get_value(task, 'GrantWriteAcp'),
1400+
ssec_algorithm=get_value(task, 'SSECAlgorithm'),
1401+
ssec_key=get_value(task, 'SSECKey'),
1402+
ssec_key_md5=get_value(task, 'SSECKeyMd5'),
1403+
meta=meta
1404+
)
1405+
1406+
13461407
class PutBucketReplicationOutput(ResponseInfo):
13471408
def __init__(self, resp):
13481409
super(PutBucketReplicationOutput, self).__init__(resp)
@@ -1824,7 +1885,7 @@ class GetSymlinkOutput(ResponseInfo):
18241885
def __init__(self, resp):
18251886
super(GetSymlinkOutput, self).__init__(resp)
18261887
self.version_id = get_value(resp.headers, "x-tos-version-id")
1827-
self.symlink_target_key = get_value(resp.headers, 'x-tos-symlink-target')
1888+
self.symlink_target_key = urllib.parse.unquote_plus(get_value(resp.headers, 'x-tos-symlink-target'))
18281889
self.etag = get_etag(resp.headers)
18291890
self.last_modified = get_value(resp.headers, 'last-modified')
18301891
if self.last_modified:

0 commit comments

Comments
 (0)