Repository: googleapis/google-cloud-python

Issue:
Add support for bucket labels
See: https://cloud.google.com/storage/docs/json_api/v1/buckets#labels


Discussion:

Resolving patch:
diff --git a/storage/google/cloud/storage/bucket.py b/storage/google/cloud/storage/bucket.py
--- a/storage/google/cloud/storage/bucket.py
+++ b/storage/google/cloud/storage/bucket.py
@@ -551,6 +551,36 @@ def cors(self, entries):
         """
         self._patch_property('cors', entries)
 
+    @property
+    def labels(self):
+        """Retrieve or set CORS policies configured for this bucket.
+
+        See
+        https://cloud.google.com/storage/docs/json_api/v1/buckets#labels
+
+        :setter: Set labels for this bucket.
+        :getter: Gets the labels for this bucket.
+
+        :rtype: :class:`dict`
+        :returns: Name-value pairs (string->string) labelling the bucket.
+        """
+        labels = self._properties.get('labels')
+        if labels is None:
+            return {}
+        return copy.deepcopy(labels)
+
+    @labels.setter
+    def labels(self, mapping):
+        """Set CORS policies configured for this bucket.
+
+        See
+        https://cloud.google.com/storage/docs/json_api/v1/buckets#labels
+
+        :type mapping: :class:`dict`
+        :param mapping: Name-value pairs (string->string) labelling the bucket.
+        """
+        self._patch_property('labels', copy.deepcopy(mapping))
+
     @property
     def etag(self):
         """Retrieve the ETag for the bucket.


Test patch:
diff --git a/storage/tests/unit/test_blob.py b/storage/tests/unit/test_blob.py
--- a/storage/tests/unit/test_blob.py
+++ b/storage/tests/unit/test_blob.py
@@ -19,6 +19,7 @@
 import unittest
 
 import mock
+import six
 from six.moves import http_client
 
 
@@ -55,7 +56,8 @@ def test_ctor_with_encoded_unicode(self):
         blob_name = b'wet \xe2\x9b\xb5'
         blob = self._make_one(blob_name, bucket=None)
         unicode_name = u'wet \N{sailboat}'
-        self.assertNotEqual(blob.name, blob_name)
+        self.assertNotIsInstance(blob.name, bytes)
+        self.assertIsInstance(blob.name, six.text_type)
         self.assertEqual(blob.name, unicode_name)
 
     def test_ctor_w_encryption_key(self):
diff --git a/storage/tests/unit/test_bucket.py b/storage/tests/unit/test_bucket.py
--- a/storage/tests/unit/test_bucket.py
+++ b/storage/tests/unit/test_bucket.py
@@ -167,6 +167,7 @@ def test_create_w_extra_properties(self):
             "condition": {"age": 365}
         }]
         LOCATION = 'eu'
+        LABELS = {'color': 'red', 'flavor': 'cherry'}
         STORAGE_CLASS = 'NEARLINE'
         DATA = {
             'name': BUCKET_NAME,
@@ -175,6 +176,7 @@ def test_create_w_extra_properties(self):
             'location': LOCATION,
             'storageClass': STORAGE_CLASS,
             'versioning': {'enabled': True},
+            'labels': LABELS,
         }
         connection = _Connection(DATA)
         client = _Client(connection, project=PROJECT)
@@ -184,6 +186,7 @@ def test_create_w_extra_properties(self):
         bucket.location = LOCATION
         bucket.storage_class = STORAGE_CLASS
         bucket.versioning_enabled = True
+        bucket.labels = LABELS
         bucket.create()
 
         kw, = connection._requested
@@ -663,6 +666,27 @@ def test_cors_setter(self):
         self.assertEqual(bucket.cors, [CORS_ENTRY])
         self.assertTrue('cors' in bucket._changes)
 
+    def test_labels_getter(self):
+        NAME = 'name'
+        LABELS = {'color': 'red', 'flavor': 'cherry'}
+        properties = {'labels': LABELS}
+        bucket = self._make_one(name=NAME, properties=properties)
+        labels = bucket.labels
+        self.assertEqual(labels, LABELS)
+        # Make sure it was a copy, not the same object.
+        self.assertIsNot(labels, LABELS)
+
+    def test_labels_setter(self):
+        NAME = 'name'
+        LABELS = {'color': 'red', 'flavor': 'cherry'}
+        bucket = self._make_one(name=NAME)
+
+        self.assertEqual(bucket.labels, {})
+        bucket.labels = LABELS
+        self.assertEqual(bucket.labels, LABELS)
+        self.assertIsNot(bucket._properties['labels'], LABELS)
+        self.assertIn('labels', bucket._changes)
+
     def test_get_logging_w_prefix(self):
         NAME = 'name'
         LOG_BUCKET = 'logs'