@@ -114,6 +114,7 @@ def __init__(self, connection=None, name=None, properties=None):
114114 name = properties .get ('name' )
115115 super (Bucket , self ).__init__ (name = name , properties = properties )
116116 self ._connection = connection
117+ self ._changes = set ()
117118
118119 def __repr__ (self ):
119120 return '<Bucket: %s>' % self .name
@@ -511,6 +512,7 @@ def update_cors(self, entries):
511512 :param entries: A sequence of mappings describing each CORS policy.
512513 """
513514 self ._patch_properties ({'cors' : entries })
515+ self .patch ()
514516
515517 def get_default_object_acl (self ):
516518 """Get the current Default Object ACL rules.
@@ -568,6 +570,7 @@ def update_lifecycle(self, rules):
568570 :param rules: A sequence of mappings describing each lifecycle rule.
569571 """
570572 self ._patch_properties ({'lifecycle' : {'rule' : rules }})
573+ self .patch ()
571574
572575 location = _scalar_property ('location' )
573576 """Retrieve location configured for this bucket.
@@ -604,13 +607,15 @@ def enable_logging(self, bucket_name, object_prefix=''):
604607 """
605608 info = {'logBucket' : bucket_name , 'logObjectPrefix' : object_prefix }
606609 self ._patch_properties ({'logging' : info })
610+ self .patch ()
607611
608612 def disable_logging (self ):
609613 """Disable access logging for this bucket.
610614
611615 See: https://cloud.google.com/storage/docs/accesslogs#disabling
612616 """
613617 self ._patch_properties ({'logging' : None })
618+ self .patch ()
614619
615620 @property
616621 def metageneration (self ):
@@ -741,7 +746,8 @@ def configure_website(self, main_page_suffix=None, not_found_page=None):
741746 'notFoundPage' : not_found_page ,
742747 },
743748 }
744- return self ._patch_properties (data )
749+ self ._patch_properties (data )
750+ return self .patch ()
745751
746752 def disable_website (self ):
747753 """Disable the website configuration for this bucket.
@@ -774,3 +780,40 @@ def make_public(self, recursive=False, future=False):
774780 for blob in self :
775781 blob .acl .all ().grant_read ()
776782 blob .save_acl ()
783+
784+ def _patch_properties (self , properties ):
785+ """Update particular fields of this object's properties.
786+
787+ This method will only update the fields provided and will not
788+ touch the other fields.
789+
790+ It **will not** reload the properties from the server as is done
791+ in :meth:`_PropertyMixin._patch_properties`. The behavior is
792+ local only and syncing occurs via :meth:`patch`.
793+
794+ :type properties: dict
795+ :param properties: The dictionary of values to update.
796+
797+ :rtype: :class:`Bucket`
798+ :returns: The current bucket.
799+ """
800+ self ._changes .update (properties .keys ())
801+ self ._properties .update (properties )
802+ return self
803+
804+ def patch (self ):
805+ """Sends all changed properties in a PATCH request.
806+
807+ Updates the ``properties`` with the response from the backend.
808+
809+ :rtype: :class:`Bucket`
810+ :returns: The current bucket.
811+ """
812+ # Pass '?projection=full' here because 'PATCH' documented not
813+ # to work properly w/ 'noAcl'.
814+ update_properties = dict ((key , self ._properties [key ])
815+ for key in self ._changes )
816+ self ._properties = self .connection .api_request (
817+ method = 'PATCH' , path = self .path , data = update_properties ,
818+ query_params = {'projection' : 'full' })
819+ return self
0 commit comments