@@ -19,15 +19,27 @@ class Bucket(object):
1919 :type name: string
2020 :param name: The name of the bucket.
2121 """
22+ # ACL rules are lazily retrieved.
23+ _acl = _default_object_acl = None
2224
2325 def __init__ (self , connection = None , name = None , metadata = None ):
2426 self .connection = connection
2527 self .name = name
2628 self .metadata = metadata
2729
28- # ACL rules are lazily retrieved.
29- self .acl = None
30- self .default_object_acl = None
30+ @property
31+ def acl (self ):
32+ """Create our ACL on demand."""
33+ if self ._acl is None :
34+ self ._acl = BucketACL (self )
35+ return self ._acl
36+
37+ @property
38+ def default_object_acl (self ):
39+ """Create our defaultObjectACL on demand."""
40+ if self ._default_object_acl is None :
41+ self ._default_object_acl = DefaultObjectACL (self )
42+ return self ._default_object_acl
3143
3244 @classmethod
3345 def from_dict (cls , bucket_dict , connection = None ):
@@ -428,11 +440,15 @@ def reload_acl(self):
428440 :rtype: :class:`Bucket`
429441 :returns: The current bucket.
430442 """
431- self .acl = BucketACL ( bucket = self )
443+ self .acl . clear ( )
432444
433- for entry in self .get_metadata ('acl' , []):
434- entity = self .acl .entity_from_dict (entry )
435- self .acl .add_entity (entity )
445+ url_path = '%s/acl' % self .path
446+ found = self .connection .api_request (method = 'GET' , path = url_path )
447+ for entry in found ['items' ]:
448+ self .acl .add_entity (self .acl .entity_from_dict (entry ))
449+
450+ # Even if we fetch no entries, the ACL is still loaded.
451+ self .acl .loaded = True
436452
437453 return self
438454
@@ -442,7 +458,7 @@ def get_acl(self):
442458 :rtype: :class:`gcloud.storage.acl.BucketACL`
443459 :returns: An ACL object for the current bucket.
444460 """
445- if not self .acl :
461+ if not self .acl . loaded :
446462 self .reload_acl ()
447463 return self .acl
448464
@@ -484,12 +500,17 @@ def save_acl(self, acl=None):
484500 # both evaluate to False, but mean very different things.
485501 if acl is None :
486502 acl = self .acl
503+ dirty = acl .loaded
504+ else :
505+ dirty = True
487506
488- if acl is None :
489- return self
507+ if dirty :
508+ result = self .connection .api_request (
509+ method = 'PATCH' , path = self .path , data = {'acl' : list (acl )})
510+ self .acl .clear ()
511+ for entry in result ['acl' ]:
512+ self .acl .entity (self .acl .entity_from_dict (entry ))
490513
491- self .patch_metadata ({'acl' : list (acl )})
492- self .reload_acl ()
493514 return self
494515
495516 def clear_acl (self ):
@@ -519,19 +540,28 @@ def clear_acl(self):
519540
520541 At this point all the custom rules you created have been removed.
521542 """
522- return self .save_acl (acl = [])
543+ self .connection .api_request (
544+ method = 'PATCH' , path = self .path , data = {'acl' : []})
545+ self .acl .clear ()
546+ self .acl .loaded = True
547+ return self
523548
524549 def reload_default_object_acl (self ):
525550 """Reload the Default Object ACL rules for this bucket.
526551
527552 :rtype: :class:`Bucket`
528553 :returns: The current bucket.
529554 """
530- self .default_object_acl = DefaultObjectACL (bucket = self )
555+ doa = self .default_object_acl
556+ doa .clear ()
557+
558+ url_path = '%s/defaultObjectAcl' % self .path
559+ found = self .connection .api_request (method = 'GET' , path = url_path )
560+ for entry in found ['items' ]:
561+ doa .add_entity (doa .entity_from_dict (entry ))
531562
532- for entry in self .get_metadata ('defaultObjectAcl' , []):
533- entity = self .default_object_acl .entity_from_dict (entry )
534- self .default_object_acl .add_entity (entity )
563+ # Even if we fetch no entries, the ACL is still loaded.
564+ doa .loaded = True
535565
536566 return self
537567
@@ -544,7 +574,7 @@ def get_default_object_acl(self):
544574 :rtype: :class:`gcloud.storage.acl.DefaultObjectACL`
545575 :returns: A DefaultObjectACL object for this bucket.
546576 """
547- if not self .default_object_acl :
577+ if not self .default_object_acl . loaded :
548578 self .reload_default_object_acl ()
549579 return self .default_object_acl
550580
@@ -559,18 +589,29 @@ def save_default_object_acl(self, acl=None):
559589 """
560590 if acl is None :
561591 acl = self .default_object_acl
592+ dirty = acl .loaded
593+ else :
594+ dirty = True
562595
563- if acl is None :
564- return self
596+ if dirty :
597+ result = self .connection .api_request (
598+ method = 'PATCH' , path = self .path ,
599+ data = {'defaultObjectAcl' : list (acl )})
600+ doa = self .default_object_acl
601+ doa .clear ()
602+ for entry in result ['defaultObjectAcl' ]:
603+ doa .entity (doa .entity_from_dict (entry ))
565604
566- self .patch_metadata ({'defaultObjectAcl' : list (acl )})
567- self .reload_default_object_acl ()
568605 return self
569606
570607 def clear_default_object_acl (self ):
571608 """Remove the Default Object ACL from this bucket."""
572609
573- return self .save_default_object_acl (acl = [])
610+ self .connection .api_request (
611+ method = 'PATCH' , path = self .path , data = {'defaultObjectAcl' : []})
612+ self .default_object_acl .clear ()
613+ self .default_object_acl .loaded = True
614+ return self
574615
575616 def make_public (self , recursive = False , future = False ):
576617 """Make a bucket public.
0 commit comments