diff --git a/minio/api.py b/minio/api.py index 3748fa68e..1cf267c32 100644 --- a/minio/api.py +++ b/minio/api.py @@ -1156,7 +1156,8 @@ def copy_object(self, bucket_name, object_name, object_source, object_name, response.getheader("x-amz-version-id"), etag, - last_modified, + response.getheaders(), + last_modified=last_modified, ) def _abort_multipart_upload(self, bucket_name, object_name, upload_id): @@ -1215,9 +1216,12 @@ def _put_object(self, bucket_name, object_name, data, headers, headers=headers, query_params=query_params, ) - return ( - response.getheader("etag").replace('"', ""), + return ObjectWriteResult( + bucket_name, + object_name, response.getheader("x-amz-version-id"), + response.getheader("etag").replace('"', ""), + response.getheaders(), ) def _upload_part(self, bucket_name, object_name, data, headers, @@ -1227,10 +1231,10 @@ def _upload_part(self, bucket_name, object_name, data, headers, "partNumber": str(part_number), "uploadId": upload_id, } - etag, _ = self._put_object( + result = self._put_object( bucket_name, object_name, data, headers, query_params=query_params, ) - return etag + return result.etag def _upload_part_task(self, args): """Upload_part task for ThreadPool.""" @@ -1355,7 +1359,14 @@ def put_object( # pylint: disable=too-many-branches,too-many-statements result = self._complete_multipart_upload( bucket_name, object_name, upload_id, parts, ) - return result.etag, result.version_id + return ObjectWriteResult( + result.bucket_name, + result.object_name, + result.version_id, + result.etag, + result.http_headers(), + location=result.location, + ) except Exception as exc: if upload_id: self._abort_multipart_upload( diff --git a/minio/definitions.py b/minio/definitions.py index ace25ff13..9c32d32a2 100644 --- a/minio/definitions.py +++ b/minio/definitions.py @@ -353,13 +353,16 @@ class ObjectWriteResult: """Result class of any APIs doing object creation.""" def __init__( - self, bucket_name, object_name, version_id, etag, last_modified, + self, bucket_name, object_name, version_id, etag, http_headers, + last_modified=None, location=None, ): self._bucket_name = bucket_name self._object_name = object_name self._version_id = version_id self._etag = etag + self._http_headers = http_headers self._last_modified = last_modified + self._location = location @property def bucket_name(self): @@ -381,7 +384,17 @@ def etag(self): """Get etag.""" return self._etag + @property + def http_headers(self): + """Get HTTP headers.""" + return self._http_headers + @property def last_modified(self): """Get last-modified time.""" return self._last_modified + + @property + def location(self): + """Get location.""" + return self._location diff --git a/tests/functional/tests.py b/tests/functional/tests.py index ebba8f39a..40c76b484 100644 --- a/tests/functional/tests.py +++ b/tests/functional/tests.py @@ -798,9 +798,10 @@ def _test_stat_object(log_entry, sse=None, version_check=False): ) # Put/Upload a streaming object of 1 MiB reader = LimitedRandomReader(length) - _, version_id1 = _CLIENT.put_object( + result = _CLIENT.put_object( bucket_name, object_name, reader, length, sse=sse, ) + version_id1 = result.version_id _CLIENT.stat_object( bucket_name, object_name, sse=sse, version_id=version_id1, ) @@ -814,10 +815,11 @@ def _test_stat_object(log_entry, sse=None, version_check=False): log_entry["args"]["content_type"] = content_type = ( "application/octet-stream") log_entry["args"]["object_name"] = object_name + "-metadata" - _, version_id2 = _CLIENT.put_object( + result = _CLIENT.put_object( bucket_name, object_name + "-metadata", reader, length, content_type, metadata, sse=sse, ) + version_id2 = result.version_id # Stat on the uploaded object to check if it exists # Fetch saved stat metadata on a previously uploaded object with # metadata. @@ -866,10 +868,12 @@ def _test_remove_object(log_entry, version_check=False): _CLIENT.set_bucket_versioning( bucket_name, VersioningConfig(ENABLED), ) - _, version_id = _CLIENT.put_object( + result = _CLIENT.put_object( bucket_name, object_name, LimitedRandomReader(length), length, ) - _CLIENT.remove_object(bucket_name, object_name, version_id=version_id) + _CLIENT.remove_object( + bucket_name, object_name, version_id=result.version_id, + ) finally: _CLIENT.remove_bucket(bucket_name) @@ -907,10 +911,11 @@ def _test_get_object(log_entry, sse=None, version_check=False): _CLIENT.set_bucket_versioning( bucket_name, VersioningConfig(ENABLED), ) - _, version_id = _CLIENT.put_object( + result = _CLIENT.put_object( bucket_name, object_name, LimitedRandomReader(length), length, sse=sse, ) + version_id = result.version_id # Get/Download a full object, iterate on response to save to disk object_data = _CLIENT.get_object( bucket_name, object_name, sse=sse, version_id=version_id, @@ -960,10 +965,11 @@ def _test_fget_object(log_entry, sse=None, version_check=False): _CLIENT.set_bucket_versioning( bucket_name, VersioningConfig(ENABLED), ) - _, version_id = _CLIENT.put_object( + result = _CLIENT.put_object( bucket_name, object_name, LimitedRandomReader(length), length, sse=sse, ) + version_id = result.version_id # Get/Download a full object and save locally at path _CLIENT.fget_object( bucket_name, object_name, tmpfile, sse=sse, version_id=version_id, @@ -1088,12 +1094,14 @@ def _test_list_objects(log_entry, use_api_v1=False, version_check=False): bucket_name, VersioningConfig(ENABLED), ) size = 1 * KB - _, version_id1 = _CLIENT.put_object( + result = _CLIENT.put_object( bucket_name, object_name + "-1", LimitedRandomReader(size), size, ) - _, version_id2 = _CLIENT.put_object( + version_id1 = result.version_id + result = _CLIENT.put_object( bucket_name, object_name + "-2", LimitedRandomReader(size), size, ) + version_id2 = result.version_id # List all object paths in bucket. objects = _CLIENT.list_objects( bucket_name, '', is_recursive, include_version=version_check, @@ -1467,9 +1475,10 @@ def test_presigned_get_object_version( # pylint: disable=invalid-name try: _CLIENT.set_bucket_versioning(bucket_name, VersioningConfig(ENABLED)) size = 1 * KB - _, version_id = _CLIENT.put_object( + result = _CLIENT.put_object( bucket_name, object_name, LimitedRandomReader(size), size, ) + version_id = result.version_id presigned_get_object_url = _CLIENT.presigned_get_object( bucket_name, object_name, version_id=version_id, ) @@ -1841,11 +1850,12 @@ def _test_remove_objects(log_entry, version_check=False): # Upload some new objects to prepare for multi-object delete test. for i in range(10): object_name = "prefix-{0}".format(i) - _, version_id = _CLIENT.put_object( + result = _CLIENT.put_object( bucket_name, object_name, LimitedRandomReader(size), size, ) object_names.append( - (object_name, version_id) if version_check else object_name, + (object_name, result.version_id) if version_check + else object_name, ) log_entry["args"]["delete_object_list"] = object_names