Repository: googleapis/google-cloud-python

Issue:
`_PropertyMixin.reload` should clear `_changes`



Discussion:
Because `_changes` is only a set of changed keys (rather than a COW dict of changed values).


Resolving patch:
diff --git a/gcloud/storage/_helpers.py b/gcloud/storage/_helpers.py
--- a/gcloud/storage/_helpers.py
+++ b/gcloud/storage/_helpers.py
@@ -56,6 +56,8 @@ def reload(self):
         query_params = {'projection': 'noAcl'}
         self._properties = self.connection.api_request(
             method='GET', path=self.path, query_params=query_params)
+        # If the api_request succeeded, we reset changes.
+        self._changes = set()
 
     def _patch_properties(self, properties):
         """Update particular fields of this object's properties.
@@ -84,6 +86,8 @@ def patch(self):
         self._properties = self.connection.api_request(
             method='PATCH', path=self.path, data=update_properties,
             query_params={'projection': 'full'})
+        # If the api_request succeeded, we reset changes.
+        self._changes = set()
 
 
 def _scalar_property(fieldname):


Test patch:
diff --git a/gcloud/storage/test__helpers.py b/gcloud/storage/test__helpers.py
--- a/gcloud/storage/test__helpers.py
+++ b/gcloud/storage/test__helpers.py
@@ -49,6 +49,8 @@ def test_path_is_abstract(self):
     def test_reload(self):
         connection = _Connection({'foo': 'Foo'})
         derived = self._derivedClass(connection, '/path')()
+        # Make sure changes is not a set, so we can observe a change.
+        derived._changes = object()
         derived.reload()
         self.assertEqual(derived._properties, {'foo': 'Foo'})
         kw = connection._requested
@@ -56,6 +58,8 @@ def test_reload(self):
         self.assertEqual(kw[0]['method'], 'GET')
         self.assertEqual(kw[0]['path'], '/path')
         self.assertEqual(kw[0]['query_params'], {'projection': 'noAcl'})
+        # Make sure changes get reset by reload.
+        self.assertEqual(derived._changes, set())
 
     def test__patch_properties(self):
         connection = _Connection({'foo': 'Foo'})
@@ -69,6 +73,26 @@ def test__patch_properties(self):
         self.assertEqual(kw[0]['data'], {'foo': 'Foo'})
         self.assertEqual(kw[0]['query_params'], {'projection': 'full'})
 
+    def test_patch(self):
+        connection = _Connection({'foo': 'Foo'})
+        derived = self._derivedClass(connection, '/path')()
+        # Make sure changes is non-empty, so we can observe a change.
+        BAR = object()
+        BAZ = object()
+        derived._properties = {'bar': BAR, 'baz': BAZ}
+        derived._changes = set(['bar'])  # Ignore baz.
+        derived.patch()
+        self.assertEqual(derived._properties, {'foo': 'Foo'})
+        kw = connection._requested
+        self.assertEqual(len(kw), 1)
+        self.assertEqual(kw[0]['method'], 'PATCH')
+        self.assertEqual(kw[0]['path'], '/path')
+        self.assertEqual(kw[0]['query_params'], {'projection': 'full'})
+        # Since changes does not include `baz`, we don't see it sent.
+        self.assertEqual(kw[0]['data'], {'bar': BAR})
+        # Make sure changes get reset by patch().
+        self.assertEqual(derived._changes, set())
+
 
 class Test__scalar_property(unittest2.TestCase):