Repository: googleapis/google-cloud-python

Issue:
Should we compare Entity._meanings in __eq__
/cc @tseaver @pcostell 



Discussion:
AFAICT, two fields with identical values but different meanings should compare unequal.

OK cool. Will wait on @pcostell before implementing.

Agree here. But I think entity equality should also take into consideration exclude_from_indexes.

Borrowing from @Alfus:

In this case I would suggest that equality/comparison depend on the library implementation. 'smart' equal functions are usually problematic in the long run, so if the object holding the value also holds the meaning, I think meaning should be considered (i.e. equal should mean identical objects). If the object also holds 'exclude_from_indexes', that should also be considered (for example, comparing two entities should take this into consideration).

Thanks. Will implement and ping you on the PR.


Resolving patch:
diff --git a/gcloud/datastore/entity.py b/gcloud/datastore/entity.py
--- a/gcloud/datastore/entity.py
+++ b/gcloud/datastore/entity.py
@@ -98,6 +98,8 @@ def __eq__(self, other):
             return False
 
         return (self.key == other.key and
+                self._exclude_from_indexes == other._exclude_from_indexes and
+                self._meanings == other._meanings and
                 super(Entity, self).__eq__(other))
 
     def __ne__(self, other):


Test patch:
diff --git a/gcloud/datastore/test_entity.py b/gcloud/datastore/test_entity.py
--- a/gcloud/datastore/test_entity.py
+++ b/gcloud/datastore/test_entity.py
@@ -70,10 +70,21 @@ def test___eq_____ne___w_different_keys(self):
 
     def test___eq_____ne___w_same_keys(self):
         from gcloud.datastore.key import Key
+
+        name = 'foo'
+        value = 42
+        meaning = 9
+
         key1 = Key(_KIND, _ID, dataset_id=_DATASET_ID)
-        entity1 = self._makeOne(key=key1)
+        entity1 = self._makeOne(key=key1, exclude_from_indexes=(name,))
+        entity1[name] = value
+        entity1._meanings[name] = (meaning, value)
+
         key2 = Key(_KIND, _ID, dataset_id=_DATASET_ID)
-        entity2 = self._makeOne(key=key2)
+        entity2 = self._makeOne(key=key2, exclude_from_indexes=(name,))
+        entity2[name] = value
+        entity2._meanings[name] = (meaning, value)
+
         self.assertTrue(entity1 == entity2)
         self.assertFalse(entity1 != entity2)
 
@@ -140,6 +151,38 @@ def test___eq_____ne___w_same_keys_props_w_diff_entities_as_value(self):
         self.assertFalse(entity1 == entity2)
         self.assertTrue(entity1 != entity2)
 
+    def test__eq__same_value_different_exclude(self):
+        from gcloud.datastore.key import Key
+
+        name = 'foo'
+        value = 42
+        key = Key(_KIND, _ID, dataset_id=_DATASET_ID)
+
+        entity1 = self._makeOne(key=key, exclude_from_indexes=(name,))
+        entity1[name] = value
+
+        entity2 = self._makeOne(key=key, exclude_from_indexes=())
+        entity2[name] = value
+
+        self.assertFalse(entity1 == entity2)
+
+    def test__eq__same_value_different_meanings(self):
+        from gcloud.datastore.key import Key
+
+        name = 'foo'
+        value = 42
+        meaning = 9
+        key = Key(_KIND, _ID, dataset_id=_DATASET_ID)
+
+        entity1 = self._makeOne(key=key, exclude_from_indexes=(name,))
+        entity1[name] = value
+
+        entity2 = self._makeOne(key=key, exclude_from_indexes=(name,))
+        entity2[name] = value
+        entity2._meanings[name] = (meaning, value)
+
+        self.assertFalse(entity1 == entity2)
+
     def test___repr___no_key_empty(self):
         entity = self._makeOne()
         self.assertEqual(repr(entity), '<Entity {}>')