in gslib/boto_translation.py [0:0]
def _BotoKeyToObject(self, key, fields=None):
"""Constructs an apitools Object from a boto key.
Args:
key: Boto key to construct Object from.
fields: If present, construct the apitools Object with only this set of
metadata fields.
Returns:
apitools Object corresponding to key.
"""
custom_metadata = None
if not fields or 'metadata' in fields or len(
[field for field in fields if field.startswith('metadata/')]) >= 1:
custom_metadata = self._TranslateBotoKeyCustomMetadata(key)
cache_control = None
if not fields or 'cacheControl' in fields:
cache_control = getattr(key, 'cache_control', None)
component_count = None
if not fields or 'componentCount' in fields:
component_count = getattr(key, 'component_count', None)
content_disposition = None
if not fields or 'contentDisposition' in fields:
content_disposition = getattr(key, 'content_disposition', None)
# Other fields like updated and ACL depend on the generation
# of the object, so populate that regardless of whether it was requested.
generation = self._TranslateBotoKeyGeneration(key)
metageneration = None
if not fields or 'metageneration' in fields:
metageneration = self._TranslateBotoKeyMetageneration(key)
time_created = None
if not fields or 'timeCreated' in fields:
# Translation code to avoid a dependency on dateutil.
time_created = self._TranslateBotoKeyTimestamp(key)
etag = None
if not fields or 'etag' in fields:
etag = getattr(key, 'etag', None)
if etag:
etag = etag.strip('"\'')
crc32c = None
if not fields or 'crc32c' in fields:
if hasattr(key, 'cloud_hashes') and 'crc32c' in key.cloud_hashes:
crc32c = base64.b64encode(key.cloud_hashes['crc32c']).rstrip(b'\n')
md5_hash = None
if not fields or 'md5Hash' in fields:
if hasattr(key, 'cloud_hashes') and 'md5' in key.cloud_hashes:
md5_hash = base64.b64encode(key.cloud_hashes['md5']).rstrip(b'\n')
elif self._GetMD5FromETag(getattr(key, 'etag', None)):
md5_hash = Base64EncodeHash(self._GetMD5FromETag(key.etag))
elif self.provider == 's3':
# S3 etags are MD5s for non-multi-part objects, but multi-part objects
# (which include all objects >= 5 GB) have a custom checksum
# implementation that is not currently supported by gsutil.
self.logger.warn(
'Non-MD5 etag (%s) present for key %s, data integrity checks are '
'not possible.', key.etag, key)
# Serialize the boto key in the media link if it is requested. This
# way we can later access the key without adding an HTTP call.
media_link = None
if not fields or 'mediaLink' in fields:
media_link = binascii.b2a_base64(
pickle.dumps(key, pickle.HIGHEST_PROTOCOL))
size = None
if not fields or 'size' in fields:
size = key.size or 0
storage_class = None
if not fields or 'storageClass' in fields:
# TODO: Scrub all callers requesting the storageClass field and then
# revert this to storage_class; the base storage_class
# attribute calls GET on the bucket if the storage class is not already
# populated in the key, which can fail if the user does not have
# permission on the bucket.
storage_class = getattr(key, '_storage_class', None)
if six.PY3:
if crc32c and isinstance(crc32c, bytes):
crc32c = crc32c.decode('ascii')
if md5_hash and isinstance(md5_hash, bytes):
md5_hash = md5_hash.decode('ascii')
cloud_api_object = apitools_messages.Object(
bucket=key.bucket.name,
name=key.name,
size=size,
contentEncoding=key.content_encoding,
contentLanguage=key.content_language,
contentType=key.content_type,
cacheControl=cache_control,
contentDisposition=content_disposition,
etag=etag,
crc32c=crc32c,
md5Hash=md5_hash,
generation=generation,
metageneration=metageneration,
componentCount=component_count,
timeCreated=time_created,
metadata=custom_metadata,
mediaLink=media_link,
storageClass=storage_class)
# Remaining functions amend cloud_api_object.
self._TranslateDeleteMarker(key, cloud_api_object)
if not fields or 'acl' in fields:
generation_str = GenerationFromUrlAndString(
StorageUrlFromString(self.provider), generation)
self._TranslateBotoKeyAcl(key,
cloud_api_object,
generation=generation_str)
return cloud_api_object