Repository: googleapis/google-cloud-python

Issue:
Storage: assigning 'Bucket.retention_policy' to None fails in systests
See the [non-flaky-looking failures today](https://source.cloud.google.com/results/invocations/18371668-bb86-4350-9d2f-56c750351b9d/targets/cloud-devrel%2Fclient-libraries%2Fgoogle-cloud-python%2Fpresubmit%2Fstorage/log):

```python
__________ TestRetentionPolicy.test_bucket_w_retention_period ______________

 = <tests.system.TestRetentionPolicy testMethod=test_bucket_w_retention_period>

def test_bucket_w_retention_period(self):
    import datetime
    from google.api_core import exceptions

    period_secs = 10

    new_bucket_name = 'w-retention-period' + unique_resource_id('-')
    bucket = Config.CLIENT.create_bucket(new_bucket_name)
    self.case_buckets_to_delete.append(new_bucket_name)

    bucket.retention_period = period_secs
    bucket.default_event_based_hold = False
    bucket.patch()

    self.assertEqual(bucket.retention_period, period_secs)
    self.assertIsInstance(
        bucket.retention_policy_effective_time, datetime.datetime)
    self.assertFalse(bucket.default_event_based_hold)
    self.assertFalse(bucket.retention_policy_locked)

    blob_name = 'test-blob'
    payload = b'DEADBEEF'
    blob = bucket.blob(blob_name)
    blob.upload_from_string(payload)

    other = bucket.get_blob(blob_name)

    self.assertFalse(other.event_based_hold)
    self.assertFalse(other.temporary_hold)
    self.assertIsInstance(
        other.retention_expiration_time, datetime.datetime)

    with self.assertRaises(exceptions.Forbidden):
        other.delete()

    bucket.retention_period = None
    bucket.patch()
...

        BadRequest: 400 PATCH https://www.googleapis.com/storage/v1/b/w-retention-period-1541108415593?projection=full: Retention policy must have a retention period greater than 0 and less than 100 years.
```

@frankyn Has something changed on the back-end about this case?  These tests have been passing.


Discussion:
This is strange, I'm researching, from a brief inspection it is as if it no longer accepts the `None` value in Python. 
I think it changed based on it no longer accepts `None` when a Retention policy is defined. It used to accept it. I will follow-up on such subtle changes in the backend. 

As for the fix, I missed this during the review, because I have learned more!
From https://github.com/googleapis/google-cloud-python/blob/master/storage/google/cloud/storage/bucket.py#L1348-L1352
Change to:
```python
    @retention_period.setter
    def retention_period(self, value):
        """Set the retention period for items in the bucket.
        :type value: int
        :param value:
            number of seconds to retain items after upload or release from
            event-based lock.
        :raises ValueError: if the bucket's retention policy is locked.
        """
        policy = self._properties.setdefault('retentionPolicy', {})
        if value is not None:
            policy['retentionPeriod'] = str(value)
        else:
            policy = None
        self._patch_property('retentionPolicy', policy)
```
 
Internal tracking bug: 115765214

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
@@ -1347,8 +1347,9 @@ def retention_period(self, value):
         """
         policy = self._properties.setdefault('retentionPolicy', {})
         if value is not None:
-            value = str(value)
-        policy['retentionPeriod'] = value
+            policy['retentionPeriod'] = str(value)
+        else:
+            policy = None
         self._patch_property('retentionPolicy', policy)
 
     @property


Test patch:
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
@@ -1573,13 +1573,14 @@ def test_retention_period_getter(self):
     def test_retention_period_setter_w_none(self):
         period = 86400 * 100  # 100 days
         bucket = self._make_one()
-        policy = bucket._properties['retentionPolicy'] = {}
-        policy['retentionPeriod'] = period
+        bucket._properties['retentionPolicy'] = {
+            'retentionPeriod': period,
+        }
 
         bucket.retention_period = None
 
         self.assertIsNone(
-            bucket._properties['retentionPolicy']['retentionPeriod'])
+            bucket._properties['retentionPolicy'])
 
     def test_retention_period_setter_w_int(self):
         period = 86400 * 100  # 100 days