Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1. add random test bucket name 2. add delete test file after finish 3… #173

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion oss2/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = '2.6.1'
__version__ = '2.6.2'

from . import models, exceptions

Expand Down
45 changes: 45 additions & 0 deletions oss2/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ class Bucket(_Base):
STAT = 'stat'
BUCKET_INFO = 'bucketInfo'
PROCESS = 'x-oss-process'
TAGGING = 'tagging'

def __init__(self, auth, endpoint, bucket_name,
is_cname=False,
Expand Down Expand Up @@ -1595,6 +1596,50 @@ def process_object(self, key, process):
resp = self.__do_object('POST', key, params={Bucket.PROCESS: ''}, data=process_data)
logger.debug("Process object done, req_id: {0}, status_code: {1}".format(resp.request_id, resp.status))
return ProcessObjectResult(resp)

def put_object_tagging(self, key, tagging, headers=None):
"""

:param str key: 上传tagging的对象名称,不能为空。

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1、注释最好用英文
2、参数input最好能换一个有意义的,比如 tagBody

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

注释这里 沿用的之前的风格,参数名称我换下

:param tagging: tag 标签内容
:type tagging: :class:`ObjectTagging <oss2.models.ObjectTagging>` 对象

:return: :class:`RequestResult <oss2.models.RequestResult>`
"""
logger.debug("Start to put object tagging, bucket: {0}, key: {1}, tagging: {2}".format(
self.bucket_name, to_string(key), tagging))

if headers is not None:
headers = http.CaseInsensitiveDict(headers)

data = self.__convert_data(ObjectTagging, xml_utils.to_put_object_tagging, tagging)
resp = self.__do_object('PUT', key, data=data, params={Bucket.TAGGING: ''}, headers=headers)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1、需要对key是否为空进行合法性检查
2、需要对data进行合法性检查,是否是一个ObjectTagging对象

Copy link
Collaborator Author

@coderall coderall Apr 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1、key为空,现在所有接口都没有判断
2、参数类型也不用,如果不是这个类型,后面访问类中变量或方法时会报异常


return RequestResult(resp)

def get_object_tagging(self, key):

"""
:param str key: 要获取tagging的对象名称
:return: :class:`ObjectTagging <oss2.models.ObjectTagging>`
"""
logger.debug("Start to get object tagging, bucket: {0}, key: {1}".format(
self.bucket_name, to_string(key)))
resp = self.__do_object('GET', key, params={Bucket.TAGGING: ''})

return self._parse_result(resp, xml_utils.parse_get_object_tagging, GetObjectTaggingResult)

def delete_object_tagging(self, key):
"""
:param str key: 要删除tagging的对象名称
:return: :class:`RequestResult <oss2.models.RequestResult>`
"""
logger.debug("Start to delete object tagging, bucket: {0}, key: {1}".format(
self.bucket_name, to_string(key)))
resp = self.__do_object('DELETE', key, params={Bucket.TAGGING: ''})
logger.debug("Delete object tagging done, req_id: {0}, status_code: {1}".format(resp.request_id, resp.status))
return RequestResult(resp)

def _get_bucket_config(self, config):
"""获得Bucket某项配置,具体哪种配置由 `config` 指定。该接口直接返回 `RequestResult` 对象。
Expand Down
2 changes: 1 addition & 1 deletion oss2/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class Auth(AuthBase):
'response-expires', 'response-content-disposition', 'cors', 'lifecycle',
'restore', 'qos', 'referer', 'stat', 'bucketInfo', 'append', 'position', 'security-token',
'live', 'comp', 'status', 'vod', 'startTime', 'endTime', 'x-oss-process',
'symlink', 'callback', 'callback-var']
'symlink', 'callback', 'callback-var', 'tagging']
)

def _sign_request(self, req, bucket_name, key):
Expand Down
3 changes: 3 additions & 0 deletions oss2/headers.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
OSS_SERVER_SIDE_ENCRYPTION = "x-oss-server-side-encryption"
OSS_SERVER_SIDE_ENCRYPTION_KEY_ID = "x-oss-server-side-encryption-key-id"

OSS_OBJECT_TAGGING = "x-oss-tagging"
OSS_OBJECT_TAGGING_COPY_DIRECTIVE = "x-oss-tagging-directive"


class RequestHeader(dict):
def __init__(self, *arg, **kw):
Expand Down
76 changes: 74 additions & 2 deletions oss2/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from .utils import http_to_unixtime, make_progress_adapter, make_crc_adapter
from .exceptions import ClientError, InconsistentError
from .compat import urlunquote, to_string
from .compat import urlunquote, to_string, urlquote
from .select_response import SelectResponseAdapter
from .headers import *
import json
Expand Down Expand Up @@ -552,6 +552,10 @@ class LifecycleRule(object):
:param expiration: 过期删除操作。
:type expiration: :class:`LifecycleExpiration`
:param status: 启用还是禁止该规则。可选值为 `LifecycleRule.ENABLED` 或 `LifecycleRule.DISABLED`
:param storage_transitions: 存储类型转换规则
:type storage_transitions: :class:`StorageTransition`
:param tagging: object tagging 规则
:type tagging: :class:`ObjectTagging`
"""

ENABLED = 'Enabled'
Expand All @@ -560,13 +564,14 @@ class LifecycleRule(object):
def __init__(self, id, prefix,
status=ENABLED, expiration=None,
abort_multipart_upload=None,
storage_transitions=None):
storage_transitions=None, tagging=None):
self.id = id
self.prefix = prefix
self.status = status
self.expiration = expiration
self.abort_multipart_upload = abort_multipart_upload
self.storage_transitions = storage_transitions
self.tagging = tagging


class BucketLifecycle(object):
Expand Down Expand Up @@ -878,3 +883,70 @@ def __init__(self, resp):
self.object = result['object']
if 'status' in result:
self.process_status = result['status']

_MAX_OBJECT_TAGGING_KEY_LENGTH=128
_MAX_OBJECT_TAGGING_VALUE_LENGTH=256

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这些常量定义有统一地方放吗?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

写的时候也在想这个事,但是好像没有统一定义的地方

class ObjectTagging(object):

def __init__(self, tagging_rules=None):

self.tag_set = tagging_rules or ObjectTaggingRule()

def __str__(self):

tag_str = ""

tagging_rule = self.tag_set.tagging_rule

for key in tagging_rule:
tag_str += key
tag_str += ":" + tagging_rule[key] + " "

return tag_str

class ObjectTaggingRule(object):

def __init__(self):
self.tagging_rule = dict()

def add(self, key, value):

if key is None or key == '':
raise ClientError("ObjectTagging key should not be empty")

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value为空是否需要校验一下?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

后端接受value为空的情况

if len(key) > _MAX_OBJECT_TAGGING_KEY_LENGTH:
raise ClientError("ObjectTagging key is too long")

if len(value) > _MAX_OBJECT_TAGGING_VALUE_LENGTH:
raise ClientError("ObjectTagging value is too long")

self.tagging_rule[key] = value

def delete(self, key):
del self.tagging_rule[key]

def len(self):
return len(self.tagging_rule)

def to_query_string(self):
query_string = ''

for key in self.tagging_rule:
query_string += urlquote(key)
query_string += '='
query_string += urlquote(self.tagging_rule[key])
query_string += '&'

if len(query_string) == 0:
return ''
else:
query_string = query_string[:-1]

return query_string

class GetObjectTaggingResult(RequestResult, ObjectTagging):

def __init__(self, resp):
RequestResult.__init__(self, resp)
ObjectTagging.__init__(self)
57 changes: 55 additions & 2 deletions oss2/xml_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
Owner,
AccessControlList,
AbortMultipartUpload,
StorageTransition)
StorageTransition,
ObjectTagging,
ObjectTaggingRule)

from .compat import urlunquote, to_unicode, to_string
from .utils import iso8601_to_unixtime, date_to_iso8601, iso8601_to_date
Expand Down Expand Up @@ -422,21 +424,36 @@ def parse_lifecycle_storage_transitions(storage_transition_nodes):

return storage_transitions

def parse_lifecycle_object_taggings(lifecycle_tagging_nodes):

if lifecycle_tagging_nodes is None:
return ObjectTagging()

tagging_rule = ObjectTaggingRule()
for tag_node in lifecycle_tagging_nodes:
key = _find_tag(tag_node, 'Key')
value = _find_tag(tag_node, 'Value')
tagging_rule.add(key, value)

return ObjectTagging(tagging_rule)

def parse_get_bucket_lifecycle(result, body):
root = ElementTree.fromstring(body)
url_encoded = _is_url_encoding(root)

for rule_node in root.findall('Rule'):
expiration = parse_lifecycle_expiration(rule_node.find('Expiration'))
abort_multipart_upload = parse_lifecycle_abort_multipart_upload(rule_node.find('AbortMultipartUpload'))
storage_transitions = parse_lifecycle_storage_transitions(rule_node.findall('Transition'))
tagging = parse_lifecycle_object_taggings(rule_node.findall('Tag'))
rule = LifecycleRule(
_find_tag(rule_node, 'ID'),
_find_tag(rule_node, 'Prefix'),
status=_find_tag(rule_node, 'Status'),
expiration=expiration,
abort_multipart_upload=abort_multipart_upload,
storage_transitions=storage_transitions
storage_transitions=storage_transitions,
tagging=tagging
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

两个变量名怎么是一样的?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

diff 结果应该符合预期吧

)
result.rules.append(rule)

Expand Down Expand Up @@ -567,6 +584,13 @@ def to_put_bucket_lifecycle(bucket_lifecycle):
_add_text_child(storage_transition_node, 'CreatedBeforeDate',
date_to_iso8601(storage_transition.created_before_date))

tagging = rule.tagging
if tagging:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tagging是bool类型吗?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

python的语法习惯,这里tagging是ObjectTagging类型

tagging_rule = tagging.tag_set.tagging_rule
for key in tagging.tag_set.tagging_rule:
tag_node = ElementTree.SubElement(rule_node, 'Tag')
_add_text_child(tag_node, 'Key', key)
_add_text_child(tag_node, 'Value', tagging_rule[key])
return _node_to_string(root)


Expand Down Expand Up @@ -741,3 +765,32 @@ def to_get_select_json_object_meta(json_meta_param):
raise SelectOperationClientError("The json_meta_param contains unsupported key " + key, "")

return _node_to_string(root)

def to_put_object_tagging(object_tagging):
root = ElementTree.Element("Tagging")
tag_set = ElementTree.SubElement(root, "TagSet")

for item in object_tagging.tag_set.tagging_rule:
tag_xml = ElementTree.SubElement(tag_set, "Tag")
_add_text_child(tag_xml, 'Key', item)
_add_text_child(tag_xml, 'Value', object_tagging.tag_set.tagging_rule[item])

return _node_to_string(root)

def parse_get_object_tagging(result, body):
root = ElementTree.fromstring(body)
url_encoded = _is_url_encoding(root)
tagset_node = root.find('TagSet')

if tagset_node is None:
return result

tagging_rules = ObjectTaggingRule()
for tag_node in tagset_node.findall('Tag'):
key = _find_object(tag_node, 'Key', url_encoded)
value = _find_object(tag_node, 'Value', url_encoded)
tagging_rules.add(key, value)

result.tag_set = tagging_rules
return result

Empty file added tests/__init__.py
Empty file.
10 changes: 7 additions & 3 deletions tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
OSS_ID = os.getenv("OSS_TEST_ACCESS_KEY_ID")
OSS_SECRET = os.getenv("OSS_TEST_ACCESS_KEY_SECRET")
OSS_ENDPOINT = os.getenv("OSS_TEST_ENDPOINT")
OSS_BUCKET = os.getenv("OSS_TEST_BUCKET")
OSS_TEST_BUCKET = os.getenv("OSS_TEST_BUCKET")
OSS_CNAME = os.getenv("OSS_TEST_CNAME")
OSS_CMK = os.getenv("OSS_TEST_CMK")
OSS_REGION = os.getenv("OSS_TEST_REGION", "cn-hangzhou")
Expand All @@ -30,7 +30,11 @@
def random_string(n):
return ''.join(random.choice(string.ascii_lowercase) for i in range(n))


OSS_BUCKET = ''
if OSS_TEST_BUCKET is None:
OSS_BUCKET = 'aliyun-oss-python-sdk-'+random_string(10)
else:
OSS_BUCKET = OSS_TEST_BUCKET + random_string(10)

def random_bytes(n):
return oss2.to_bytes(random_string(n))
Expand Down Expand Up @@ -82,7 +86,7 @@ def setUp(self):

global OSS_AUTH_VERSION
OSS_AUTH_VERSION = os.getenv('OSS_TEST_AUTH_VERSION')

self.bucket = oss2.Bucket(oss2.make_auth(OSS_ID, OSS_SECRET, OSS_AUTH_VERSION), OSS_ENDPOINT, OSS_BUCKET)

try:
Expand Down
Loading