diff --git a/gcloud/storage/bucket.py b/gcloud/storage/bucket.py index 4d4ce3ac1962..00c8424c9567 100644 --- a/gcloud/storage/bucket.py +++ b/gcloud/storage/bucket.py @@ -19,15 +19,27 @@ class Bucket(object): :type name: string :param name: The name of the bucket. """ + # ACL rules are lazily retrieved. + _acl = _default_object_acl = None def __init__(self, connection=None, name=None, metadata=None): self.connection = connection self.name = name self.metadata = metadata - # ACL rules are lazily retrieved. - self.acl = None - self.default_object_acl = None + @property + def acl(self): + """Create our ACL on demand.""" + if self._acl is None: + self._acl = BucketACL(self) + return self._acl + + @property + def default_object_acl(self): + """Create our defaultObjectACL on demand.""" + if self._default_object_acl is None: + self._default_object_acl = DefaultObjectACL(self) + return self._default_object_acl @classmethod def from_dict(cls, bucket_dict, connection=None): @@ -431,11 +443,15 @@ def reload_acl(self): :rtype: :class:`Bucket` :returns: The current bucket. """ - self.acl = BucketACL(bucket=self) + self.acl.clear() - for entry in self.get_metadata('acl', []): - entity = self.acl.entity_from_dict(entry) - self.acl.add_entity(entity) + url_path = '%s/acl' % self.path + found = self.connection.api_request(method='GET', path=url_path) + for entry in found['items']: + self.acl.add_entity(self.acl.entity_from_dict(entry)) + + # Even if we fetch no entries, the ACL is still loaded. + self.acl.loaded = True return self @@ -445,7 +461,7 @@ def get_acl(self): :rtype: :class:`gcloud.storage.acl.BucketACL` :returns: An ACL object for the current bucket. """ - if not self.acl: + if not self.acl.loaded: self.reload_acl() return self.acl @@ -487,12 +503,17 @@ def save_acl(self, acl=None): # both evaluate to False, but mean very different things. if acl is None: acl = self.acl + dirty = acl.loaded + else: + dirty = True - if acl is None: - return self + if dirty: + result = self.connection.api_request( + method='PATCH', path=self.path, data={'acl': list(acl)}) + self.acl.clear() + for entry in result['acl']: + self.acl.entity(self.acl.entity_from_dict(entry)) - self.patch_metadata({'acl': list(acl)}) - self.reload_acl() return self def clear_acl(self): @@ -522,7 +543,11 @@ def clear_acl(self): At this point all the custom rules you created have been removed. """ - return self.save_acl(acl=[]) + self.connection.api_request( + method='PATCH', path=self.path, data={'acl': []}) + self.acl.clear() + self.acl.loaded = True + return self def reload_default_object_acl(self): """Reload the Default Object ACL rules for this bucket. @@ -530,11 +555,16 @@ def reload_default_object_acl(self): :rtype: :class:`Bucket` :returns: The current bucket. """ - self.default_object_acl = DefaultObjectACL(bucket=self) + doa = self.default_object_acl + doa.clear() + + url_path = '%s/defaultObjectAcl' % self.path + found = self.connection.api_request(method='GET', path=url_path) + for entry in found['items']: + doa.add_entity(doa.entity_from_dict(entry)) - for entry in self.get_metadata('defaultObjectAcl', []): - entity = self.default_object_acl.entity_from_dict(entry) - self.default_object_acl.add_entity(entity) + # Even if we fetch no entries, the ACL is still loaded. + doa.loaded = True return self @@ -547,7 +577,7 @@ def get_default_object_acl(self): :rtype: :class:`gcloud.storage.acl.DefaultObjectACL` :returns: A DefaultObjectACL object for this bucket. """ - if not self.default_object_acl: + if not self.default_object_acl.loaded: self.reload_default_object_acl() return self.default_object_acl @@ -562,18 +592,29 @@ def save_default_object_acl(self, acl=None): """ if acl is None: acl = self.default_object_acl + dirty = acl.loaded + else: + dirty = True - if acl is None: - return self + if dirty: + result = self.connection.api_request( + method='PATCH', path=self.path, + data={'defaultObjectAcl': list(acl)}) + doa = self.default_object_acl + doa.clear() + for entry in result['defaultObjectAcl']: + doa.entity(doa.entity_from_dict(entry)) - self.patch_metadata({'defaultObjectAcl': list(acl)}) - self.reload_default_object_acl() return self def clear_default_object_acl(self): """Remove the Default Object ACL from this bucket.""" - return self.save_default_object_acl(acl=[]) + self.connection.api_request( + method='PATCH', path=self.path, data={'defaultObjectAcl': []}) + self.default_object_acl.clear() + self.default_object_acl.loaded = True + return self def make_public(self, recursive=False, future=False): """Make a bucket public. diff --git a/gcloud/storage/test_bucket.py b/gcloud/storage/test_bucket.py index e7869ce0cab3..92d27cdaf9ef 100644 --- a/gcloud/storage/test_bucket.py +++ b/gcloud/storage/test_bucket.py @@ -17,8 +17,8 @@ def test_ctor_defaults(self): self.assertEqual(bucket.connection, None) self.assertEqual(bucket.name, None) self.assertEqual(bucket.metadata, None) - self.assertEqual(bucket.acl, None) - self.assertEqual(bucket.default_object_acl, None) + self.assertTrue(bucket._acl is None) + self.assertTrue(bucket._default_object_acl is None) def test_ctor_explicit(self): NAME = 'name' @@ -28,8 +28,8 @@ def test_ctor_explicit(self): self.assertTrue(bucket.connection is connection) self.assertEqual(bucket.name, NAME) self.assertEqual(bucket.metadata, metadata) - self.assertEqual(bucket.acl, None) - self.assertEqual(bucket.default_object_acl, None) + self.assertTrue(bucket._acl is None) + self.assertTrue(bucket._default_object_acl is None) def test_from_dict_defaults(self): NAME = 'name' @@ -39,8 +39,8 @@ def test_from_dict_defaults(self): self.assertEqual(bucket.connection, None) self.assertEqual(bucket.name, NAME) self.assertEqual(bucket.metadata, metadata) - self.assertEqual(bucket.acl, None) - self.assertEqual(bucket.default_object_acl, None) + self.assertTrue(bucket._acl is None) + self.assertTrue(bucket._default_object_acl is None) def test_from_dict_explicit(self): NAME = 'name' @@ -51,8 +51,22 @@ def test_from_dict_explicit(self): self.assertTrue(bucket.connection is connection) self.assertEqual(bucket.name, NAME) self.assertEqual(bucket.metadata, metadata) - self.assertEqual(bucket.acl, None) - self.assertEqual(bucket.default_object_acl, None) + self.assertTrue(bucket._acl is None) + self.assertTrue(bucket._default_object_acl is None) + + def test_acl_property(self): + from gcloud.storage.acl import BucketACL + bucket = self._makeOne() + acl = bucket.acl + self.assertTrue(isinstance(acl, BucketACL)) + self.assertTrue(acl is bucket._acl) + + def test_default_object_acl_property(self): + from gcloud.storage.acl import DefaultObjectACL + bucket = self._makeOne() + acl = bucket.default_object_acl + self.assertTrue(isinstance(acl, DefaultObjectACL)) + self.assertTrue(acl is bucket._default_object_acl) def test___iter___empty(self): NAME = 'name' @@ -551,28 +565,42 @@ def test_disable_website(self): def test_reload_acl_eager_empty(self): from gcloud.storage.acl import BucketACL - metadata = {'acl': []} - bucket = self._makeOne(metadata=metadata) + NAME = 'name' + ROLE = 'role' + connection = _Connection({'items': []}) + bucket = self._makeOne(connection, NAME) + bucket.acl.entity('allUsers', ROLE) self.assertTrue(bucket.reload_acl() is bucket) self.assertTrue(isinstance(bucket.acl, BucketACL)) self.assertEqual(list(bucket.acl), []) + kw = connection._requested + self.assertEqual(len(kw), 1) + self.assertEqual(kw[0]['method'], 'GET') + self.assertEqual(kw[0]['path'], '/b/%s/acl' % NAME) def test_reload_acl_eager_nonempty(self): from gcloud.storage.acl import BucketACL + NAME = 'name' ROLE = 'role' - metadata = {'acl': [{'entity': 'allUsers', 'role': ROLE}]} - bucket = self._makeOne(metadata=metadata) + connection = _Connection( + {'items': [{'entity': 'allUsers', 'role': ROLE}]}) + bucket = self._makeOne(connection, NAME) + bucket.acl.loaded = True self.assertTrue(bucket.reload_acl() is bucket) self.assertTrue(isinstance(bucket.acl, BucketACL)) self.assertEqual(list(bucket.acl), [{'entity': 'allUsers', 'role': ROLE}]) + kw = connection._requested + self.assertEqual(len(kw), 1) + self.assertEqual(kw[0]['method'], 'GET') + self.assertEqual(kw[0]['path'], '/b/%s/acl' % NAME) def test_reload_acl_lazy(self): from gcloud.storage.acl import BucketACL NAME = 'name' ROLE = 'role' - after = {'acl': [{'entity': 'allUsers', 'role': ROLE}]} - connection = _Connection(after) + connection = _Connection( + {'items': [{'entity': 'allUsers', 'role': ROLE}]}) bucket = self._makeOne(connection, NAME) self.assertTrue(bucket.reload_acl() is bucket) self.assertTrue(isinstance(bucket.acl, BucketACL)) @@ -581,26 +609,27 @@ def test_reload_acl_lazy(self): kw = connection._requested self.assertEqual(len(kw), 1) self.assertEqual(kw[0]['method'], 'GET') - self.assertEqual(kw[0]['path'], '/b/%s' % NAME) - self.assertEqual(kw[0]['query_params'], {'projection': 'full'}) + self.assertEqual(kw[0]['path'], '/b/%s/acl' % NAME) def test_get_acl_lazy(self): from gcloud.storage.acl import BucketACL - metadata = {'acl': []} - connection = _Connection() - bucket = self._makeOne(metadata=metadata) + NAME = 'name' + connection = _Connection({'items': []}) + bucket = self._makeOne(connection, NAME) acl = bucket.get_acl() self.assertTrue(acl is bucket.acl) self.assertTrue(isinstance(acl, BucketACL)) self.assertEqual(list(bucket.acl), []) kw = connection._requested - self.assertEqual(len(kw), 0) + self.assertEqual(len(kw), 1) + self.assertEqual(kw[0]['method'], 'GET') + self.assertEqual(kw[0]['path'], '/b/%s/acl' % NAME) def test_get_acl_eager(self): - from gcloud.storage.acl import BucketACL connection = _Connection() bucket = self._makeOne() - preset = bucket.acl = BucketACL(bucket) + preset = bucket.acl # Ensure it is assigned + preset.loaded = True acl = bucket.get_acl() self.assertTrue(acl is preset) kw = connection._requested @@ -616,25 +645,22 @@ def test_save_acl_none_set_none_passed(self): def test_save_acl_existing_set_none_passed(self): NAME = 'name' connection = _Connection({'foo': 'Foo', 'acl': []}) - metadata = {'acl': []} - bucket = self._makeOne(connection, NAME, metadata) - bucket.reload_acl() + bucket = self._makeOne(connection, NAME) + bucket.acl.loaded = True self.assertTrue(bucket.save_acl() is bucket) kw = connection._requested self.assertEqual(len(kw), 1) self.assertEqual(kw[0]['method'], 'PATCH') self.assertEqual(kw[0]['path'], '/b/%s' % NAME) - self.assertEqual(kw[0]['data'], metadata) - self.assertEqual(kw[0]['query_params'], {'projection': 'full'}) + self.assertEqual(kw[0]['data'], {'acl': []}) def test_save_acl_existing_set_new_passed(self): NAME = 'name' ROLE = 'role' new_acl = [{'entity': 'allUsers', 'role': ROLE}] connection = _Connection({'foo': 'Foo', 'acl': new_acl}) - metadata = {'acl': []} - bucket = self._makeOne(connection, NAME, metadata) - bucket.reload_acl() + bucket = self._makeOne(connection, NAME) + bucket.acl.loaded = True self.assertTrue(bucket.save_acl(new_acl) is bucket) self.assertEqual(list(bucket.acl), new_acl) kw = connection._requested @@ -642,16 +668,15 @@ def test_save_acl_existing_set_new_passed(self): self.assertEqual(kw[0]['method'], 'PATCH') self.assertEqual(kw[0]['path'], '/b/%s' % NAME) self.assertEqual(kw[0]['data'], {'acl': new_acl}) - self.assertEqual(kw[0]['query_params'], {'projection': 'full'}) def test_clear_acl(self): NAME = 'name' ROLE = 'role' - old_acl = [{'entity': 'allUsers', 'role': ROLE}] - connection = _Connection({'foo': 'Foo', 'acl': []}) - metadata = {'acl': old_acl} - bucket = self._makeOne(connection, NAME, metadata) - bucket.reload_acl() + connection = _Connection( + {'foo': 'Foo', 'acl': []}, + ) + bucket = self._makeOne(connection, NAME) + bucket.acl.entity('allUsers', ROLE) self.assertTrue(bucket.clear_acl() is bucket) self.assertEqual(list(bucket.acl), []) kw = connection._requested @@ -659,60 +684,69 @@ def test_clear_acl(self): self.assertEqual(kw[0]['method'], 'PATCH') self.assertEqual(kw[0]['path'], '/b/%s' % NAME) self.assertEqual(kw[0]['data'], {'acl': []}) - self.assertEqual(kw[0]['query_params'], {'projection': 'full'}) def test_reload_default_object_acl_eager_empty(self): - from gcloud.storage.acl import BucketACL - metadata = {'defaultObjectAcl': []} - bucket = self._makeOne(metadata=metadata) + from gcloud.storage.acl import DefaultObjectACL + NAME = 'name' + after = {'items': []} + connection = _Connection(after) + bucket = self._makeOne(connection, NAME) + bucket.default_object_acl.loaded = True self.assertTrue(bucket.reload_default_object_acl() is bucket) - self.assertTrue(isinstance(bucket.default_object_acl, BucketACL)) + self.assertTrue( + isinstance(bucket.default_object_acl, DefaultObjectACL)) self.assertEqual(list(bucket.default_object_acl), []) def test_reload_default_object_acl_eager_nonempty(self): - from gcloud.storage.acl import BucketACL + from gcloud.storage.acl import DefaultObjectACL + NAME = 'name' ROLE = 'role' - metadata = {'defaultObjectAcl': [{'entity': 'allUsers', 'role': ROLE}]} - bucket = self._makeOne(metadata=metadata) + after = {'items': [{'entity': 'allUsers', 'role': ROLE}]} + connection = _Connection(after) + bucket = self._makeOne(connection, NAME) + bucket.default_object_acl.entity('allUsers', 'OTHERROLE') self.assertTrue(bucket.reload_default_object_acl() is bucket) - self.assertTrue(isinstance(bucket.default_object_acl, BucketACL)) + self.assertTrue( + isinstance(bucket.default_object_acl, DefaultObjectACL)) self.assertEqual(list(bucket.default_object_acl), [{'entity': 'allUsers', 'role': ROLE}]) def test_reload_default_object_acl_lazy(self): - from gcloud.storage.acl import BucketACL + from gcloud.storage.acl import DefaultObjectACL NAME = 'name' ROLE = 'role' - after = {'defaultObjectAcl': [{'entity': 'allUsers', 'role': ROLE}]} + after = {'items': [{'entity': 'allUsers', 'role': ROLE}]} connection = _Connection(after) bucket = self._makeOne(connection, NAME) self.assertTrue(bucket.reload_default_object_acl() is bucket) - self.assertTrue(isinstance(bucket.default_object_acl, BucketACL)) + self.assertTrue( + isinstance(bucket.default_object_acl, DefaultObjectACL)) self.assertEqual(list(bucket.default_object_acl), [{'entity': 'allUsers', 'role': ROLE}]) kw = connection._requested self.assertEqual(len(kw), 1) self.assertEqual(kw[0]['method'], 'GET') - self.assertEqual(kw[0]['path'], '/b/%s' % NAME) - self.assertEqual(kw[0]['query_params'], {'projection': 'full'}) + self.assertEqual(kw[0]['path'], '/b/%s/defaultObjectAcl' % NAME) def test_get_default_object_acl_lazy(self): from gcloud.storage.acl import BucketACL - metadata = {'defaultObjectAcl': []} - connection = _Connection() - bucket = self._makeOne(metadata=metadata) + NAME = 'name' + connection = _Connection({'items': []}) + bucket = self._makeOne(connection, NAME) acl = bucket.get_default_object_acl() self.assertTrue(acl is bucket.default_object_acl) self.assertTrue(isinstance(acl, BucketACL)) self.assertEqual(list(bucket.default_object_acl), []) kw = connection._requested - self.assertEqual(len(kw), 0) + self.assertEqual(len(kw), 1) + self.assertEqual(kw[0]['method'], 'GET') + self.assertEqual(kw[0]['path'], '/b/%s/defaultObjectAcl' % NAME) def test_get_default_object_acl_eager(self): - from gcloud.storage.acl import BucketACL connection = _Connection() bucket = self._makeOne() - preset = bucket.default_object_acl = BucketACL(bucket) + preset = bucket.default_object_acl # ensure it is assigned + preset.loaded = True acl = bucket.get_default_object_acl() self.assertTrue(acl is preset) kw = connection._requested @@ -727,115 +761,90 @@ def test_save_default_object_acl_none_set_none_passed(self): def test_save_default_object_acl_existing_set_none_passed(self): NAME = 'name' - connection = _Connection({'foo': 'Foo', 'acl': []}) connection = _Connection( - {'foo': 'Foo', 'acl': []}, {'foo': 'Foo', 'acl': [], 'defaultObjectAcl': []}, ) - metadata = {'defaultObjectAcl': []} - bucket = self._makeOne(connection, NAME, metadata) - bucket.reload_default_object_acl() + bucket = self._makeOne(connection, NAME) + bucket.default_object_acl.loaded = True self.assertTrue(bucket.save_default_object_acl() is bucket) kw = connection._requested - self.assertEqual(len(kw), 2) + self.assertEqual(len(kw), 1) self.assertEqual(kw[0]['method'], 'PATCH') self.assertEqual(kw[0]['path'], '/b/%s' % NAME) - self.assertEqual(kw[0]['data'], metadata) - self.assertEqual(kw[0]['query_params'], {'projection': 'full'}) - self.assertEqual(kw[1]['method'], 'GET') - self.assertEqual(kw[1]['path'], '/b/%s' % NAME) - self.assertEqual(kw[1]['query_params'], {'projection': 'full'}) + self.assertEqual(kw[0]['data'], {'defaultObjectAcl': []}) def test_save_default_object_acl_existing_set_new_passed(self): NAME = 'name' ROLE = 'role' new_acl = [{'entity': 'allUsers', 'role': ROLE}] connection = _Connection( - {'foo': 'Foo', 'acl': new_acl}, {'foo': 'Foo', 'acl': new_acl, 'defaultObjectAcl': new_acl}, ) metadata = {'defaultObjectAcl': []} bucket = self._makeOne(connection, NAME, metadata) - bucket.reload_default_object_acl() + bucket.default_object_acl.loaded = True self.assertTrue(bucket.save_default_object_acl(new_acl) is bucket) self.assertEqual(list(bucket.default_object_acl), new_acl) kw = connection._requested - self.assertEqual(len(kw), 2) + self.assertEqual(len(kw), 1) self.assertEqual(kw[0]['method'], 'PATCH') self.assertEqual(kw[0]['path'], '/b/%s' % NAME) self.assertEqual(kw[0]['data'], {'defaultObjectAcl': new_acl}) - self.assertEqual(kw[0]['query_params'], {'projection': 'full'}) - self.assertEqual(kw[1]['method'], 'GET') - self.assertEqual(kw[1]['path'], '/b/%s' % NAME) - self.assertEqual(kw[1]['query_params'], {'projection': 'full'}) def test_clear_default_object_acl(self): NAME = 'name' ROLE = 'role' - old_acl = [{'entity': 'allUsers', 'role': ROLE}] connection = _Connection( - {'foo': 'Foo', 'acl': []}, {'foo': 'Foo', 'acl': [], 'defaultObjectAcl': []}, ) - metadata = {'defaultObjectAcl': old_acl} - bucket = self._makeOne(connection, NAME, metadata) - bucket.reload_default_object_acl() + bucket = self._makeOne(connection, NAME) + bucket.default_object_acl.entity('allUsers', ROLE) self.assertTrue(bucket.clear_default_object_acl() is bucket) self.assertEqual(list(bucket.default_object_acl), []) kw = connection._requested - self.assertEqual(len(kw), 2) + self.assertEqual(len(kw), 1) self.assertEqual(kw[0]['method'], 'PATCH') self.assertEqual(kw[0]['path'], '/b/%s' % NAME) self.assertEqual(kw[0]['data'], {'defaultObjectAcl': []}) - self.assertEqual(kw[0]['query_params'], {'projection': 'full'}) - self.assertEqual(kw[1]['method'], 'GET') - self.assertEqual(kw[1]['path'], '/b/%s' % NAME) - self.assertEqual(kw[1]['query_params'], {'projection': 'full'}) def test_make_public_defaults(self): from gcloud.storage.acl import _ACLEntity NAME = 'name' - before = {'acl': [], 'defaultObjectAcl': []} permissive = [{'entity': 'allUsers', 'role': _ACLEntity.READER_ROLE}] after = {'acl': permissive, 'defaultObjectAcl': []} connection = _Connection(after) - bucket = self._makeOne(connection, NAME, before) + bucket = self._makeOne(connection, NAME) + bucket.acl.loaded = True bucket.make_public() - self.assertEqual(bucket.metadata, after) - self.assertEqual(list(bucket.acl), after['acl']) - self.assertEqual(bucket.default_object_acl, None) + self.assertEqual(list(bucket.acl), permissive) + self.assertEqual(list(bucket.default_object_acl), []) kw = connection._requested self.assertEqual(len(kw), 1) self.assertEqual(kw[0]['method'], 'PATCH') self.assertEqual(kw[0]['path'], '/b/%s' % NAME) self.assertEqual(kw[0]['data'], {'acl': after['acl']}) - self.assertEqual(kw[0]['query_params'], {'projection': 'full'}) def test_make_public_w_future(self): from gcloud.storage.acl import _ACLEntity NAME = 'name' - before = {'acl': [], 'defaultObjectAcl': []} permissive = [{'entity': 'allUsers', 'role': _ACLEntity.READER_ROLE}] after1 = {'acl': permissive, 'defaultObjectAcl': []} after2 = {'acl': permissive, 'defaultObjectAcl': permissive} connection = _Connection(after1, after2) - bucket = self._makeOne(connection, NAME, before) + bucket = self._makeOne(connection, NAME) + bucket.acl.loaded = True + bucket.default_object_acl.loaded = True bucket.make_public(future=True) - self.assertEqual(bucket.metadata, after2) - self.assertEqual(list(bucket.acl), after2['acl']) - self.assertEqual(list(bucket.default_object_acl), - after2['defaultObjectAcl']) + self.assertEqual(list(bucket.acl), permissive) + self.assertEqual(list(bucket.default_object_acl), permissive) kw = connection._requested self.assertEqual(len(kw), 2) self.assertEqual(kw[0]['method'], 'PATCH') self.assertEqual(kw[0]['path'], '/b/%s' % NAME) - self.assertEqual(kw[0]['data'], {'acl': after1['acl']}) - self.assertEqual(kw[0]['query_params'], {'projection': 'full'}) + self.assertEqual(kw[0]['data'], {'acl': permissive}) self.assertEqual(kw[1]['method'], 'PATCH') self.assertEqual(kw[1]['path'], '/b/%s' % NAME) - self.assertEqual(kw[1]['data'], {'defaultObjectAcl': - after2['defaultObjectAcl']}) - self.assertEqual(kw[1]['query_params'], {'projection': 'full'}) + self.assertEqual(kw[1]['data'], {'defaultObjectAcl': permissive}) def test_make_public_recursive(self): from gcloud.storage.acl import _ACLEntity @@ -870,23 +879,21 @@ def get_items_from_response(self, response): NAME = 'name' KEY = 'key' - before = {'acl': [], 'defaultObjectAcl': []} permissive = [{'entity': 'allUsers', 'role': _ACLEntity.READER_ROLE}] after = {'acl': permissive, 'defaultObjectAcl': []} connection = _Connection(after, {'items': [{'name': KEY}]}) - bucket = self._makeOne(connection, NAME, before) + bucket = self._makeOne(connection, NAME) + bucket.acl.loaded = True with _Monkey(MUT, _KeyIterator=_KeyIterator): bucket.make_public(recursive=True) - self.assertEqual(bucket.metadata, after) - self.assertEqual(list(bucket.acl), after['acl']) - self.assertEqual(bucket.default_object_acl, None) + self.assertEqual(list(bucket.acl), permissive) + self.assertEqual(list(bucket.default_object_acl), []) self.assertEqual(_saved, [(bucket, KEY, True)]) kw = connection._requested self.assertEqual(len(kw), 2) self.assertEqual(kw[0]['method'], 'PATCH') self.assertEqual(kw[0]['path'], '/b/%s' % NAME) - self.assertEqual(kw[0]['data'], {'acl': after['acl']}) - self.assertEqual(kw[0]['query_params'], {'projection': 'full'}) + self.assertEqual(kw[0]['data'], {'acl': permissive}) self.assertEqual(kw[1]['method'], 'GET') self.assertEqual(kw[1]['path'], '/b/%s/o' % NAME) self.assertEqual(kw[1]['query_params'], None)