Skip to content

Commit 51e286f

Browse files
committed
Merge pull request #682 from tseaver/652-handle_empty_acls
#652: Harden ACL 'save'/'reload' against missing element in server response.
2 parents f0a1157 + 770f328 commit 51e286f

File tree

2 files changed

+75
-12
lines changed

2 files changed

+75
-12
lines changed

gcloud/storage/acl.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ def reload(self):
406406
url_path = '%s/%s' % (self.bucket.path, self._URL_PATH_ELEM)
407407
found = self.bucket.connection.api_request(method='GET', path=url_path)
408408
self.loaded = True
409-
for entry in found['items']:
409+
for entry in found.get('items', ()):
410410
self.add_entity(self.entity_from_dict(entry))
411411

412412
return self
@@ -450,7 +450,7 @@ def save(self, acl=None):
450450
data={self._URL_PATH_ELEM: list(acl)},
451451
query_params={'projection': 'full'})
452452
self.entities.clear()
453-
for entry in result[self._URL_PATH_ELEM]:
453+
for entry in result.get(self._URL_PATH_ELEM, ()):
454454
self.add_entity(self.entity_from_dict(entry))
455455
self.loaded = True
456456

@@ -512,7 +512,7 @@ def reload(self):
512512
url_path = '%s/acl' % self.blob.path
513513
found = self.blob.connection.api_request(method='GET', path=url_path)
514514
self.loaded = True
515-
for entry in found['items']:
515+
for entry in found.get('items', ()):
516516
self.add_entity(self.entity_from_dict(entry))
517517

518518
return self
@@ -535,7 +535,7 @@ def save(self, acl=None):
535535
method='PATCH', path=self.blob.path, data={'acl': list(acl)},
536536
query_params={'projection': 'full'})
537537
self.entities.clear()
538-
for entry in result['acl']:
538+
for entry in result.get('acl', ()):
539539
self.add_entity(self.entity_from_dict(entry))
540540
self.loaded = True
541541

gcloud/storage/test_acl.py

Lines changed: 71 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,22 @@ def test_ctor(self):
536536
self.assertFalse(acl.loaded)
537537
self.assertTrue(acl.bucket is bucket)
538538

539+
def test_reload_eager_missing(self):
540+
# https://github.com/GoogleCloudPlatform/gcloud-python/issues/652
541+
NAME = 'name'
542+
ROLE = 'role'
543+
connection = _Connection({})
544+
bucket = _Bucket(connection, NAME)
545+
acl = self._makeOne(bucket)
546+
acl.loaded = True
547+
acl.entity('allUsers', ROLE)
548+
self.assertTrue(acl.reload() is acl)
549+
self.assertEqual(list(acl), [])
550+
kw = connection._requested
551+
self.assertEqual(len(kw), 1)
552+
self.assertEqual(kw[0]['method'], 'GET')
553+
self.assertEqual(kw[0]['path'], '/b/%s/acl' % NAME)
554+
539555
def test_reload_eager_empty(self):
540556
NAME = 'name'
541557
ROLE = 'role'
@@ -589,6 +605,21 @@ def test_save_none_set_none_passed(self):
589605
kw = connection._requested
590606
self.assertEqual(len(kw), 0)
591607

608+
def test_save_existing_missing_none_passed(self):
609+
NAME = 'name'
610+
connection = _Connection({})
611+
bucket = _Bucket(connection, NAME)
612+
acl = self._makeOne(bucket)
613+
acl.loaded = True
614+
self.assertTrue(acl.save() is acl)
615+
self.assertEqual(list(acl), [])
616+
kw = connection._requested
617+
self.assertEqual(len(kw), 1)
618+
self.assertEqual(kw[0]['method'], 'PATCH')
619+
self.assertEqual(kw[0]['path'], '/b/%s' % NAME)
620+
self.assertEqual(kw[0]['data'], {'acl': []})
621+
self.assertEqual(kw[0]['query_params'], {'projection': 'full'})
622+
592623
def test_save_no_arg(self):
593624
NAME = 'name'
594625
ROLE = 'role'
@@ -665,24 +696,22 @@ def test_ctor(self):
665696
self.assertFalse(acl.loaded)
666697
self.assertTrue(acl.blob is blob)
667698

668-
def test_reload_eager_empty(self):
699+
def test_reload_eager_missing(self):
700+
# https://github.com/GoogleCloudPlatform/gcloud-python/issues/652
669701
NAME = 'name'
670702
BLOB_NAME = 'blob-name'
671703
ROLE = 'role'
672-
after = {'items': [{'entity': 'allUsers', 'role': ROLE}]}
704+
after = {}
673705
connection = _Connection(after)
674706
bucket = _Bucket(connection, NAME)
675707
blob = _Blob(bucket, BLOB_NAME)
676708
acl = self._makeOne(blob)
677709
acl.loaded = True
710+
acl.entity('allUsers', ROLE)
678711
self.assertTrue(acl.reload() is acl)
679-
self.assertEqual(list(acl), after['items'])
680-
kw = connection._requested
681-
self.assertEqual(len(kw), 1)
682-
self.assertEqual(kw[0]['method'], 'GET')
683-
self.assertEqual(kw[0]['path'], '/b/name/o/%s/acl' % BLOB_NAME)
712+
self.assertEqual(list(acl), [])
684713

685-
def test_reload_eager_nonempty(self):
714+
def test_reload_eager_empty(self):
686715
NAME = 'name'
687716
BLOB_NAME = 'blob-name'
688717
ROLE = 'role'
@@ -696,6 +725,23 @@ def test_reload_eager_nonempty(self):
696725
self.assertTrue(acl.reload() is acl)
697726
self.assertEqual(list(acl), [])
698727

728+
def test_reload_eager_nonempty(self):
729+
NAME = 'name'
730+
BLOB_NAME = 'blob-name'
731+
ROLE = 'role'
732+
after = {'items': [{'entity': 'allUsers', 'role': ROLE}]}
733+
connection = _Connection(after)
734+
bucket = _Bucket(connection, NAME)
735+
blob = _Blob(bucket, BLOB_NAME)
736+
acl = self._makeOne(blob)
737+
acl.loaded = True
738+
self.assertTrue(acl.reload() is acl)
739+
self.assertEqual(list(acl), after['items'])
740+
kw = connection._requested
741+
self.assertEqual(len(kw), 1)
742+
self.assertEqual(kw[0]['method'], 'GET')
743+
self.assertEqual(kw[0]['path'], '/b/name/o/%s/acl' % BLOB_NAME)
744+
699745
def test_reload_lazy(self):
700746
NAME = 'name'
701747
BLOB_NAME = 'blob-name'
@@ -724,6 +770,23 @@ def test_save_none_set_none_passed(self):
724770
kw = connection._requested
725771
self.assertEqual(len(kw), 0)
726772

773+
def test_save_existing_missing_none_passed(self):
774+
# https://github.com/GoogleCloudPlatform/gcloud-python/issues/652
775+
NAME = 'name'
776+
BLOB_NAME = 'blob-name'
777+
connection = _Connection({'foo': 'Foo'})
778+
bucket = _Bucket(connection, NAME)
779+
blob = _Blob(bucket, BLOB_NAME)
780+
acl = self._makeOne(blob)
781+
acl.loaded = True
782+
self.assertTrue(acl.save() is acl)
783+
kw = connection._requested
784+
self.assertEqual(len(kw), 1)
785+
self.assertEqual(kw[0]['method'], 'PATCH')
786+
self.assertEqual(kw[0]['path'], '/b/name/o/%s' % BLOB_NAME)
787+
self.assertEqual(kw[0]['data'], {'acl': []})
788+
self.assertEqual(kw[0]['query_params'], {'projection': 'full'})
789+
727790
def test_save_existing_set_none_passed(self):
728791
NAME = 'name'
729792
BLOB_NAME = 'blob-name'

0 commit comments

Comments
 (0)