From b4329508e9e5e860a1847dfcecb34cc9ec96861b Mon Sep 17 00:00:00 2001 From: Richard Theis Date: Fri, 25 Mar 2016 12:52:51 -0500 Subject: [PATCH] Consistent resource.prop for timestamps and booleans (object store) This patch set updates all object store objects to use consistent resource.prop for timestamps and booleans. In particular, the following changes were made: - Clarify documentation for timestamp and boolean attributes - Use 'is_' prefix and boolean type for boolean attributes - Use '_at' suffix and timestamp type for timestamp attributes This patch set also include missing documentation for the Account resource. Change-Id: Ibf204bb0ab444e7090c1102acdd3d0e1d9722829 Partial-Bug: #1544584 --- .../users/resources/object_store/index.rst | 1 + .../resources/object_store/v1/account.rst | 12 ++++++++++ openstack/object_store/v1/_proxy.py | 6 +++-- openstack/object_store/v1/account.py | 1 + openstack/object_store/v1/container.py | 12 ++++++---- openstack/object_store/v1/obj.py | 24 ++++++++++++------- .../unit/object_store/v1/test_container.py | 2 +- .../tests/unit/object_store/v1/test_obj.py | 6 ++--- 8 files changed, 44 insertions(+), 20 deletions(-) create mode 100644 doc/source/users/resources/object_store/v1/account.rst diff --git a/doc/source/users/resources/object_store/index.rst b/doc/source/users/resources/object_store/index.rst index df075e5d..e5524e34 100644 --- a/doc/source/users/resources/object_store/index.rst +++ b/doc/source/users/resources/object_store/index.rst @@ -4,5 +4,6 @@ Object Store Resources .. toctree:: :maxdepth: 1 + v1/account v1/container v1/obj diff --git a/doc/source/users/resources/object_store/v1/account.rst b/doc/source/users/resources/object_store/v1/account.rst new file mode 100644 index 00000000..5236faea --- /dev/null +++ b/doc/source/users/resources/object_store/v1/account.rst @@ -0,0 +1,12 @@ +openstack.object_store.v1.account +================================= + +.. automodule:: openstack.object_store.v1.account + +The Account Class +----------------- + +The ``Account`` class inherits from :class:`~openstack.resource.Resource`. + +.. autoclass:: openstack.object_store.v1.account.Account + :members: diff --git a/openstack/object_store/v1/_proxy.py b/openstack/object_store/v1/_proxy.py index 2040332d..759b7e62 100644 --- a/openstack/object_store/v1/_proxy.py +++ b/openstack/object_store/v1/_proxy.py @@ -111,8 +111,9 @@ class Proxy(proxy.BaseProxy): metadata are keys defined by the Object Store and values defined by the user. The system metadata keys are: + - `content_type` - - `detect_content_type` + - `is_content_type_detected` - `versions_location` - `read_ACL` - `write_ACL` @@ -282,12 +283,13 @@ class Proxy(proxy.BaseProxy): metadata are keys defined by the Object Store and values defined by the user. The system metadata keys are: + - `content_type` - `content_encoding` - `content_disposition` - - `detect_content_type` - `delete_after` - `delete_at` + - `is_content_type_detected` """ container_name = self._get_container_name(obj, container) res = self._get_resource(_obj.Object, obj, diff --git a/openstack/object_store/v1/account.py b/openstack/object_store/v1/account.py index aa59811b..a82e6e61 100644 --- a/openstack/object_store/v1/account.py +++ b/openstack/object_store/v1/account.py @@ -40,4 +40,5 @@ class Account(_base.BaseResource): #: this header is not returned by this operation. meta_temp_url_key_2 = resource.header("x-account-meta-temp-url-key-2") #: The timestamp of the transaction. + #: *Type: datetime object parsed from a UNIX epoch* timestamp = resource.header("x-timestamp", type=format.UNIXEpoch) diff --git a/openstack/object_store/v1/container.py b/openstack/object_store/v1/container.py index 0d3cb39a..58e0dae7 100644 --- a/openstack/object_store/v1/container.py +++ b/openstack/object_store/v1/container.py @@ -20,7 +20,7 @@ class Container(_base.BaseResource): _custom_metadata_prefix = "X-Container-Meta-" _system_metadata = { "content_type": "content-type", - "detect_content_type": "x-detect-content-type", + "is_content_type_detected": "x-detect-content-type", "versions_location": "x-versions-location", "read_ACL": "x-container-read", "write_ACL": "x-container-write", @@ -53,6 +53,7 @@ class Container(_base.BaseResource): #: The count of bytes used in total. bytes_used = resource.header("x-container-bytes-used", type=int) #: The timestamp of the transaction. + #: *Type: datetime object parsed from a UNIX epoch* timestamp = resource.header("x-timestamp", type=format.UNIXEpoch) # Request headers (when id=None) @@ -60,8 +61,8 @@ class Container(_base.BaseResource): #: most recent one. If you omit this header, Object Storage responds #: faster after it finds one valid replica. Because setting this #: header to True is more expensive for the back end, use it only - #: when it is absolutely needed. - newest = resource.header("x-newest", type=bool) + #: when it is absolutely needed. *Type: bool* + is_newest = resource.header("x-newest", type=bool) # Request headers (when id=name) #: The ACL that grants read access. If not set, this header is not @@ -85,8 +86,9 @@ class Container(_base.BaseResource): content_type = resource.header("content-type") #: If set to true, Object Storage guesses the content type based #: on the file extension and ignores the value sent in the - #: Content-Type header, if present. - detect_content_type = resource.header("x-detect-content-type", type=bool) + #: Content-Type header, if present. *Type: bool* + is_content_type_detected = resource.header("x-detect-content-type", + type=bool) #: In combination with Expect: 100-Continue, specify an #: "If-None-Match: \*" header to query whether the server already #: has a copy of the object before any data is sent. diff --git a/openstack/object_store/v1/obj.py b/openstack/object_store/v1/obj.py index 1a88f8a1..fea1eec3 100644 --- a/openstack/object_store/v1/obj.py +++ b/openstack/object_store/v1/obj.py @@ -25,9 +25,9 @@ class Object(_base.BaseResource): "content_disposition": "content-disposition", "content_encoding": "content-encoding", "content_type": "content-type", - "detect_content_type": "x-detect-content-type", "delete_after": "x-delete-after", - "delete_at": "x-delete-at" + "delete_at": "x-delete-at", + "is_content_type_detected": "x-detect-content-type", } base_path = "/%(container)s" @@ -59,8 +59,8 @@ class Object(_base.BaseResource): #: the most recent one. If you omit this header, Object Storage #: responds faster after it finds one valid replica. Because #: setting this header to True is more expensive for the back end, - #: use it only when it is absolutely needed. - newest = resource.header("x-newest", type=bool) + #: use it only when it is absolutely needed. *Type: bool* + is_newest = resource.header("x-newest", type=bool) #: TODO(briancurtin) there's a lot of content here... range = resource.header("range", type=dict) #: See http://www.ietf.org/rfc/rfc2616.txt. @@ -82,7 +82,8 @@ class Object(_base.BaseResource): #: Used with temporary URLs to specify the expiry time of the #: signature. For more information about temporary URLs, see #: OpenStack Object Storage API v1 Reference. - expires = resource.header("expires") + #: *Type: datetime object parsed from ISO 8601 formatted string* + expires_at = resource.header("expires", type=format.ISO8601) #: If you include the multipart-manifest=get query parameter and #: the object is a large object, the object contents are not #: returned. Instead, the manifest is returned in the @@ -113,7 +114,9 @@ class Object(_base.BaseResource): #: was corrupted, so retry the operation. etag = resource.header("etag") #: Set to True if this object is a static large object manifest object. - is_static_large_object = resource.header("x-static-large-object") + #: *Type: bool* + is_static_large_object = resource.header("x-static-large-object", + type=bool) #: If set, the value of the Content-Encoding metadata. #: If not set, this header is not returned by this operation. content_encoding = resource.header("content-encoding") @@ -130,16 +133,18 @@ class Object(_base.BaseResource): #: If set, the time when the object will be deleted by the system #: in the format of a UNIX Epoch timestamp. #: If not set, this header is not returned by this operation. + #: *Type: datetime object parsed from a UNIX epoch* delete_at = resource.header("x-delete-at", type=format.UNIXEpoch) #: If set, to this is a dynamic large object manifest object. #: The value is the container and object name prefix of the #: segment objects in the form container/prefix. object_manifest = resource.header("x-object-manifest") #: The timestamp of the transaction. + #: *Type: datetime object parsed from a UNIX epoch* timestamp = resource.header("x-timestamp", type=format.UNIXEpoch) #: The date and time that the object was created or the last #: time that the metadata was changed. - last_modified = resource.header("last_modified", alias="last-modified") + last_modified_at = resource.header("last_modified", alias="last-modified") # Headers for PUT and POST requests #: Set to chunked to enable chunked transfer encoding. If used, @@ -147,8 +152,9 @@ class Object(_base.BaseResource): transfer_encoding = resource.header("transfer-encoding") #: If set to true, Object Storage guesses the content type based #: on the file extension and ignores the value sent in the - #: Content-Type header, if present. - detect_content_type = resource.header("x-detect-content-type", type=bool) + #: Content-Type header, if present. *Type: bool* + is_content_type_detected = resource.header("x-detect-content-type", + type=bool) #: If set, this is the name of an object used to create the new #: object by copying the X-Copy-From object. The value is in form #: {container}/{object}. You must UTF-8-encode and then URL-encode diff --git a/openstack/tests/unit/object_store/v1/test_container.py b/openstack/tests/unit/object_store/v1/test_container.py index 119b098a..4d51f058 100644 --- a/openstack/tests/unit/object_store/v1/test_container.py +++ b/openstack/tests/unit/object_store/v1/test_container.py @@ -138,7 +138,7 @@ class TestContainer(testtools.TestCase): def _test_create_update(self, sot, sot_call, sess_method): sot.read_ACL = "some ACL" sot.write_ACL = "another ACL" - sot.detect_content_type = True + sot.is_content_type_detected = True headers = { "x-container-read": "some ACL", "x-container-write": "another ACL", diff --git a/openstack/tests/unit/object_store/v1/test_obj.py b/openstack/tests/unit/object_store/v1/test_obj.py index 5f98a81c..903138b6 100644 --- a/openstack/tests/unit/object_store/v1/test_obj.py +++ b/openstack/tests/unit/object_store/v1/test_obj.py @@ -96,7 +96,7 @@ class TestObject(testtools.TestCase): headers = DICT_EXAMPLE['headers'] self.assertEqual(headers['content-length'], sot.content_length) self.assertEqual(headers['accept-ranges'], sot.accept_ranges) - self.assertEqual(headers['last-modified'], sot.last_modified) + self.assertEqual(headers['last-modified'], sot.last_modified_at) self.assertEqual(headers['etag'], sot.etag) self.assertEqual(datetime(2016, 1, 21, 22, 10, 56, 281120, tzinfo=iso8601.UTC), @@ -108,7 +108,7 @@ class TestObject(testtools.TestCase): def test_get(self): sot = obj.Object.new(container=CONTAINER_NAME, name=OBJECT_NAME) - sot.newest = True + sot.is_newest = True sot.if_match = {"who": "what"} rv = sot.get(self.sess) @@ -127,7 +127,7 @@ class TestObject(testtools.TestCase): def _test_create(self, method, data, accept): sot = obj.Object.new(container=CONTAINER_NAME, name=OBJECT_NAME, data=data) - sot.newest = True + sot.is_newest = True headers = {"x-newest": True, "Accept": ""} rv = sot.create(self.sess)