Skip to content

Commit 89e31be

Browse files
committed
Add accessors for read-only properties of a server-side object.
Addresses part of #313.
1 parent 0e6c5bd commit 89e31be

File tree

2 files changed

+250
-0
lines changed

2 files changed

+250
-0
lines changed

gcloud/storage/key.py

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@ class Key(_PropertyMixin):
1515

1616
CUSTOM_PROPERTY_ACCESSORS = {
1717
'acl': 'get_acl()',
18+
'componentCount': 'component_count',
19+
'etag': 'etag',
20+
'generation': 'generation',
21+
'id': 'id',
22+
'mediaLink': 'media_link',
23+
'metageneration': 'metageneration',
24+
'name': 'name',
25+
'owner': 'owner',
26+
'selfLink': 'self_link',
27+
'size': 'size',
28+
'storageClass': 'storage_class',
29+
'timeDeleted': 'time_deleted',
30+
'updated': 'updated',
1831
}
1932
"""Map field name -> accessor for fields w/ custom accessors."""
2033

@@ -359,6 +372,133 @@ def make_public(self):
359372
self.acl.save()
360373
return self
361374

375+
@property
376+
def component_count(self):
377+
"""Number of underlying components that make up this object.
378+
379+
See: https://cloud.google.com/storage/docs/json_api/v1/objects
380+
381+
:rtype: integer
382+
"""
383+
return self.properties['componentCount']
384+
385+
@property
386+
def etag(self):
387+
"""Retrieve the ETag for the object.
388+
389+
See: http://tools.ietf.org/html/rfc2616#section-3.11 and
390+
https://cloud.google.com/storage/docs/json_api/v1/objects
391+
392+
:rtype: string
393+
"""
394+
return self.properties['etag']
395+
396+
@property
397+
def generation(self):
398+
"""Retrieve the generation for the object.
399+
400+
See: https://cloud.google.com/storage/docs/json_api/v1/objects
401+
402+
:rtype: integer
403+
"""
404+
return self.properties['generation']
405+
406+
@property
407+
def id(self):
408+
"""Retrieve the ID for the object.
409+
410+
See: https://cloud.google.com/storage/docs/json_api/v1/objects
411+
412+
:rtype: string
413+
"""
414+
return self.properties['id']
415+
416+
@property
417+
def media_link(self):
418+
"""Retrieve the media download URI for the object.
419+
420+
See: https://cloud.google.com/storage/docs/json_api/v1/objects
421+
422+
:rtype: string
423+
"""
424+
return self.properties['selfLink']
425+
426+
@property
427+
def metageneration(self):
428+
"""Retrieve the metageneration for the object.
429+
430+
See: https://cloud.google.com/storage/docs/json_api/v1/objects
431+
432+
:rtype: integer
433+
"""
434+
return self.properties['metageneration']
435+
436+
@property
437+
def owner(self):
438+
"""Retrieve info about the owner of the object.
439+
440+
See: https://cloud.google.com/storage/docs/json_api/v1/objects
441+
442+
:rtype: dict
443+
:returns: mapping of owner's role/ID.
444+
"""
445+
return self.properties['owner'].copy()
446+
447+
@property
448+
def self_link(self):
449+
"""Retrieve the URI for the object.
450+
451+
See: https://cloud.google.com/storage/docs/json_api/v1/objects
452+
453+
:rtype: string
454+
"""
455+
return self.properties['selfLink']
456+
457+
@property
458+
def size(self):
459+
"""Size of the object, in bytes.
460+
461+
See: https://cloud.google.com/storage/docs/json_api/v1/objects
462+
463+
:rtype: integer
464+
"""
465+
return self.properties['size']
466+
467+
@property
468+
def storage_class(self):
469+
"""Retrieve the storage class for the object.
470+
471+
See: https://cloud.google.com/storage/docs/json_api/v1/objects and
472+
https://cloud.google.com/storage/docs/durable-reduced-availability#_DRA_Bucket
473+
474+
:rtype: string
475+
:returns: Currently one of "STANDARD", "DURABLE_REDUCED_AVAILABILITY"
476+
"""
477+
return self.properties['storageClass']
478+
479+
@property
480+
def time_deleted(self):
481+
"""Retrieve the timestamp at which the object was deleted.
482+
483+
See: https://cloud.google.com/storage/docs/json_api/v1/objects
484+
485+
:rtype: string or None
486+
:returns: timestamp in RFC 3339 format, or None if the object
487+
has a "live" version.
488+
"""
489+
return self.properties.get('timeDeleted')
490+
491+
@property
492+
def updated(self):
493+
"""Retrieve the timestamp at which the object was updated.
494+
495+
See: https://cloud.google.com/storage/docs/json_api/v1/objects
496+
497+
:rtype: string
498+
:returns: timestamp in RFC 3339 format.
499+
"""
500+
return self.properties['updated']
501+
362502

363503
class _KeyIterator(Iterator):
364504
"""An iterator listing keys.

gcloud/storage/test_key.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,116 @@ def test_make_public(self):
344344
self.assertEqual(kw[0]['data'], {'acl': permissive})
345345
self.assertEqual(kw[0]['query_params'], {'projection': 'full'})
346346

347+
def test_component_count(self):
348+
KEY = 'key'
349+
connection = _Connection()
350+
bucket = _Bucket(connection)
351+
COMPONENT_COUNT = 42
352+
properties = {'componentCount': COMPONENT_COUNT}
353+
key = self._makeOne(bucket, KEY, properties)
354+
self.assertEqual(key.component_count, COMPONENT_COUNT)
355+
356+
def test_etag(self):
357+
KEY = 'key'
358+
connection = _Connection()
359+
bucket = _Bucket(connection)
360+
ETAG = 'ETAG'
361+
properties = {'etag': ETAG}
362+
key = self._makeOne(bucket, KEY, properties)
363+
self.assertEqual(key.etag, ETAG)
364+
365+
def test_generation(self):
366+
KEY = 'key'
367+
connection = _Connection()
368+
bucket = _Bucket(connection)
369+
GENERATION = 42
370+
properties = {'generation': GENERATION}
371+
key = self._makeOne(bucket, KEY, properties)
372+
self.assertEqual(key.generation, GENERATION)
373+
374+
def test_id(self):
375+
KEY = 'key'
376+
connection = _Connection()
377+
bucket = _Bucket(connection)
378+
ID = 'ID'
379+
properties = {'id': ID}
380+
key = self._makeOne(bucket, KEY, properties)
381+
self.assertEqual(key.id, ID)
382+
383+
def test_media_link(self):
384+
KEY = 'key'
385+
connection = _Connection()
386+
bucket = _Bucket(connection)
387+
MEDIA_LINK = 'http://example.com/media/'
388+
properties = {'selfLink': MEDIA_LINK}
389+
key = self._makeOne(bucket, KEY, properties)
390+
self.assertEqual(key.media_link, MEDIA_LINK)
391+
392+
def test_metageneration(self):
393+
KEY = 'key'
394+
connection = _Connection()
395+
bucket = _Bucket(connection)
396+
METAGENERATION = 42
397+
properties = {'metageneration': METAGENERATION}
398+
key = self._makeOne(bucket, KEY, properties)
399+
self.assertEqual(key.metageneration, METAGENERATION)
400+
401+
def test_owner(self):
402+
KEY = 'key'
403+
connection = _Connection()
404+
bucket = _Bucket(connection)
405+
OWNER = {'entity': 'project-owner-12345', 'entityId': '23456'}
406+
properties = {'owner': OWNER}
407+
key = self._makeOne(bucket, KEY, properties)
408+
owner = key.owner
409+
self.assertEqual(owner['entity'], 'project-owner-12345')
410+
self.assertEqual(owner['entityId'], '23456')
411+
412+
def test_self_link(self):
413+
KEY = 'key'
414+
connection = _Connection()
415+
bucket = _Bucket(connection)
416+
SELF_LINK = 'http://example.com/self/'
417+
properties = {'selfLink': SELF_LINK}
418+
key = self._makeOne(bucket, KEY, properties)
419+
self.assertEqual(key.self_link, SELF_LINK)
420+
421+
def test_size(self):
422+
KEY = 'key'
423+
connection = _Connection()
424+
bucket = _Bucket(connection)
425+
SIZE = 42
426+
properties = {'size': SIZE}
427+
key = self._makeOne(bucket, KEY, properties)
428+
self.assertEqual(key.size, SIZE)
429+
430+
def test_storage_class(self):
431+
KEY = 'key'
432+
connection = _Connection()
433+
bucket = _Bucket(connection)
434+
STORAGE_CLASS = 'http://example.com/self/'
435+
properties = {'storageClass': STORAGE_CLASS}
436+
key = self._makeOne(bucket, KEY, properties)
437+
self.assertEqual(key.storage_class, STORAGE_CLASS)
438+
439+
def test_time_deleted(self):
440+
KEY = 'key'
441+
connection = _Connection()
442+
bucket = _Bucket(connection)
443+
TIME_DELETED = '2014-11-05T20:34:37Z'
444+
properties = {'timeDeleted': TIME_DELETED}
445+
key = self._makeOne(bucket, KEY, properties)
446+
self.assertEqual(key.time_deleted, TIME_DELETED)
447+
448+
def test_updated(self):
449+
KEY = 'key'
450+
connection = _Connection()
451+
bucket = _Bucket(connection)
452+
UPDATED = '2014-11-05T20:34:37Z'
453+
properties = {'updated': UPDATED}
454+
key = self._makeOne(bucket, KEY, properties)
455+
self.assertEqual(key.updated, UPDATED)
456+
347457

348458
class Test__KeyIterator(unittest2.TestCase):
349459

0 commit comments

Comments
 (0)