diff --git a/bigquery/google/cloud/bigquery/_helpers.py b/bigquery/google/cloud/bigquery/_helpers.py index 4da9be9f0723..deb83516b9d7 100644 --- a/bigquery/google/cloud/bigquery/_helpers.py +++ b/bigquery/google/cloud/bigquery/_helpers.py @@ -328,10 +328,15 @@ def __init__(self, udf_type, value): self.value = value def __eq__(self, other): + if not isinstance(other, UDFResource): + return NotImplemented return( self.udf_type == other.udf_type and self.value == other.value) + def __ne__(self, other): + return not self == other + class UDFResourcesProperty(object): """Custom property type, holding :class:`UDFResource` instances.""" diff --git a/bigquery/google/cloud/bigquery/dataset.py b/bigquery/google/cloud/bigquery/dataset.py index 8fb986cb848d..1304d5028873 100644 --- a/bigquery/google/cloud/bigquery/dataset.py +++ b/bigquery/google/cloud/bigquery/dataset.py @@ -76,11 +76,16 @@ def __init__(self, role, entity_type, entity_id): self.entity_id = entity_id def __eq__(self, other): + if not isinstance(other, AccessGrant): + return NotImplemented return ( self.role == other.role and self.entity_type == other.entity_type and self.entity_id == other.entity_id) + def __ne__(self, other): + return not self == other + def __repr__(self): return '' % ( self.role, self.entity_type, self.entity_id) diff --git a/bigquery/google/cloud/bigquery/schema.py b/bigquery/google/cloud/bigquery/schema.py index edd8dd68f3bd..e98d67c30fb6 100644 --- a/bigquery/google/cloud/bigquery/schema.py +++ b/bigquery/google/cloud/bigquery/schema.py @@ -101,16 +101,12 @@ def _key(self): ) def __eq__(self, other): - if isinstance(other, SchemaField): - return self._key() == other._key() - else: + if not isinstance(other, SchemaField): return NotImplemented + return self._key() == other._key() def __ne__(self, other): - if isinstance(other, SchemaField): - return self._key() != other._key() - else: - return NotImplemented + return not self == other def __hash__(self): return hash(self._key()) diff --git a/bigquery/tests/unit/test__helpers.py b/bigquery/tests/unit/test__helpers.py index 7648ed5bee18..581b4b9a42fc 100644 --- a/bigquery/tests/unit/test__helpers.py +++ b/bigquery/tests/unit/test__helpers.py @@ -14,6 +14,8 @@ import unittest +import mock + class Test_not_null(unittest.TestCase): @@ -815,6 +817,18 @@ def test_instance_getter_empty(self): instance = klass() self.assertEqual(instance.udf_resources, []) + def test_resource_equality(self): + from google.cloud.bigquery._helpers import UDFResource + + resource1a = UDFResource('resourceUri', 'gs://bucket/file.js') + resource1b = UDFResource('resourceUri', 'gs://bucket/file.js') + resource2 = UDFResource('resourceUri', 'gs://bucket/other.js') + + self.assertEqual(resource1a, resource1b) + self.assertNotEqual(resource1a, resource2) + self.assertNotEqual(resource1a, object()) + self.assertEqual(resource1a, mock.ANY) + def test_instance_getter_w_non_empty_list(self): from google.cloud.bigquery._helpers import UDFResource diff --git a/bigquery/tests/unit/test_dataset.py b/bigquery/tests/unit/test_dataset.py index 97721554f1b6..164f9ed0a2b4 100644 --- a/bigquery/tests/unit/test_dataset.py +++ b/bigquery/tests/unit/test_dataset.py @@ -14,6 +14,8 @@ import unittest +import mock + class TestAccessGrant(unittest.TestCase): @@ -77,6 +79,11 @@ def test___eq___hit(self): other = self._make_one('OWNER', 'userByEmail', 'phred@example.com') self.assertEqual(grant, other) + def test__eq___type_mismatch(self): + grant = self._make_one('OWNER', 'userByEmail', 'silly@example.com') + self.assertNotEqual(grant, object()) + self.assertEqual(grant, mock.ANY) + class TestDataset(unittest.TestCase): PROJECT = 'project' diff --git a/bigquery/tests/unit/test_schema.py b/bigquery/tests/unit/test_schema.py index bf3cf2e025d1..84f910a10d8e 100644 --- a/bigquery/tests/unit/test_schema.py +++ b/bigquery/tests/unit/test_schema.py @@ -14,6 +14,8 @@ import unittest +import mock + class TestSchemaField(unittest.TestCase): @@ -101,7 +103,7 @@ def test___eq___wrong_type(self): field = self._make_one('test', 'STRING') other = object() self.assertNotEqual(field, other) - self.assertIs(field.__eq__(other), NotImplemented) + self.assertEqual(field, mock.ANY) def test___eq___name_mismatch(self): field = self._make_one('test', 'STRING') @@ -155,7 +157,7 @@ def test___ne___wrong_type(self): field = self._make_one('toast', 'INTEGER') other = object() self.assertNotEqual(field, other) - self.assertIs(field.__ne__(other), NotImplemented) + self.assertEqual(field, mock.ANY) def test___ne___same_value(self): field1 = self._make_one('test', 'TIMESTAMP', mode='REPEATED') diff --git a/bigtable/google/cloud/bigtable/cluster.py b/bigtable/google/cloud/bigtable/cluster.py index 8d15547efae3..44af71f37caf 100644 --- a/bigtable/google/cloud/bigtable/cluster.py +++ b/bigtable/google/cloud/bigtable/cluster.py @@ -159,7 +159,7 @@ def name(self): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented # NOTE: This does not compare the configuration values, such as # the serve_nodes. Instead, it only compares # identifying values instance, cluster ID and client. This is @@ -170,7 +170,7 @@ def __eq__(self, other): other._instance == self._instance) def __ne__(self, other): - return not self.__eq__(other) + return not self == other def reload(self): """Reload the metadata for this cluster.""" diff --git a/bigtable/google/cloud/bigtable/column_family.py b/bigtable/google/cloud/bigtable/column_family.py index c34e75ed2c1f..391452880f2f 100644 --- a/bigtable/google/cloud/bigtable/column_family.py +++ b/bigtable/google/cloud/bigtable/column_family.py @@ -39,9 +39,6 @@ class GarbageCollectionRule(object): don't support that feature and instead support via native classes. """ - def __ne__(self, other): - return not self.__eq__(other) - class MaxVersionsGCRule(GarbageCollectionRule): """Garbage collection limiting the number of versions of a cell. @@ -55,9 +52,12 @@ def __init__(self, max_num_versions): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return other.max_num_versions == self.max_num_versions + def __ne__(self, other): + return not self == other + def to_pb(self): """Converts the garbage collection rule to a protobuf. @@ -79,9 +79,12 @@ def __init__(self, max_age): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return other.max_age == self.max_age + def __ne__(self, other): + return not self == other + def to_pb(self): """Converts the garbage collection rule to a protobuf. @@ -104,9 +107,12 @@ def __init__(self, rules): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return other.rules == self.rules + def __ne__(self, other): + return not self == other + def to_pb(self): """Converts the union into a single GC rule as a protobuf. @@ -130,9 +136,12 @@ def __init__(self, rules): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return other.rules == self.rules + def __ne__(self, other): + return not self == other + def to_pb(self): """Converts the intersection into a single GC rule as a protobuf. @@ -190,13 +199,13 @@ def name(self): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return (other.column_family_id == self.column_family_id and other._table == self._table and other.gc_rule == self.gc_rule) def __ne__(self, other): - return not self.__eq__(other) + return not self == other def to_pb(self): """Converts the column family to a protobuf. diff --git a/bigtable/google/cloud/bigtable/instance.py b/bigtable/google/cloud/bigtable/instance.py index 958f16602953..924a0d71e9ac 100644 --- a/bigtable/google/cloud/bigtable/instance.py +++ b/bigtable/google/cloud/bigtable/instance.py @@ -180,7 +180,7 @@ def name(self): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented # NOTE: This does not compare the configuration values, such as # the display_name. Instead, it only compares # identifying values instance ID and client. This is @@ -191,7 +191,7 @@ def __eq__(self, other): other._client == self._client) def __ne__(self, other): - return not self.__eq__(other) + return not self == other def reload(self): """Reload the metadata for this instance.""" diff --git a/bigtable/google/cloud/bigtable/row_data.py b/bigtable/google/cloud/bigtable/row_data.py index 78179db25c4e..56129f6342b8 100644 --- a/bigtable/google/cloud/bigtable/row_data.py +++ b/bigtable/google/cloud/bigtable/row_data.py @@ -58,13 +58,13 @@ def from_pb(cls, cell_pb): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return (other.value == self.value and other.timestamp == self.timestamp and other.labels == self.labels) def __ne__(self, other): - return not self.__eq__(other) + return not self == other class PartialCellData(object): @@ -126,12 +126,12 @@ def __init__(self, row_key): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return (other._row_key == self._row_key and other._cells == self._cells) def __ne__(self, other): - return not self.__eq__(other) + return not self == other def to_dict(self): """Convert the cells to a dictionary. @@ -211,11 +211,11 @@ def __init__(self, response_iterator): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return other._response_iterator == self._response_iterator def __ne__(self, other): - return not self.__eq__(other) + return not self == other @property def state(self): diff --git a/bigtable/google/cloud/bigtable/row_filters.py b/bigtable/google/cloud/bigtable/row_filters.py index e3f3006df286..a59be638365c 100644 --- a/bigtable/google/cloud/bigtable/row_filters.py +++ b/bigtable/google/cloud/bigtable/row_filters.py @@ -32,9 +32,6 @@ class RowFilter(object): This class is a do-nothing base class for all row filters. """ - def __ne__(self, other): - return not self.__eq__(other) - class _BoolFilter(RowFilter): """Row filter that uses a boolean flag. @@ -48,9 +45,12 @@ def __init__(self, flag): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return other.flag == self.flag + def __ne__(self, other): + return not self == other + class SinkFilter(_BoolFilter): """Advanced row filter to skip parent filters. @@ -124,9 +124,12 @@ def __init__(self, regex): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return other.regex == self.regex + def __ne__(self, other): + return not self == other + class RowKeyRegexFilter(_RegexFilter): """Row filter for a row key regular expression. @@ -173,9 +176,12 @@ def __init__(self, sample): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return other.sample == self.sample + def __ne__(self, other): + return not self == other + def to_pb(self): """Converts the row filter to a protobuf. @@ -257,12 +263,12 @@ def __init__(self, start=None, end=None): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return (other.start == self.start and other.end == self.end) def __ne__(self, other): - return not self.__eq__(other) + return not self == other def to_pb(self): """Converts the :class:`TimestampRange` to a protobuf. @@ -292,9 +298,12 @@ def __init__(self, range_): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return other.range_ == self.range_ + def __ne__(self, other): + return not self == other + def to_pb(self): """Converts the row filter to a protobuf. @@ -367,13 +376,16 @@ def __init__(self, column_family_id, start_column=None, end_column=None, def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return (other.column_family_id == self.column_family_id and other.start_column == self.start_column and other.end_column == self.end_column and other.inclusive_start == self.inclusive_start and other.inclusive_end == self.inclusive_end) + def __ne__(self, other): + return not self == other + def to_pb(self): """Converts the row filter to a protobuf. @@ -485,12 +497,15 @@ def __init__(self, start_value=None, end_value=None, def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return (other.start_value == self.start_value and other.end_value == self.end_value and other.inclusive_start == self.inclusive_start and other.inclusive_end == self.inclusive_end) + def __ne__(self, other): + return not self == other + def to_pb(self): """Converts the row filter to a protobuf. @@ -533,9 +548,12 @@ def __init__(self, num_cells): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return other.num_cells == self.num_cells + def __ne__(self, other): + return not self == other + class CellsRowOffsetFilter(_CellCountFilter): """Row filter to skip cells in a row. @@ -631,9 +649,12 @@ def __init__(self, label): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return other.label == self.label + def __ne__(self, other): + return not self == other + def to_pb(self): """Converts the row filter to a protobuf. @@ -661,9 +682,12 @@ def __init__(self, filters=None): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return other.filters == self.filters + def __ne__(self, other): + return not self == other + class RowFilterChain(_FilterCombination): """Chain of row filters. @@ -748,11 +772,14 @@ def __init__(self, base_filter, true_filter=None, false_filter=None): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return (other.base_filter == self.base_filter and other.true_filter == self.true_filter and other.false_filter == self.false_filter) + def __ne__(self, other): + return not self == other + def to_pb(self): """Converts the row filter to a protobuf. diff --git a/bigtable/google/cloud/bigtable/table.py b/bigtable/google/cloud/bigtable/table.py index 64fbcc93771e..921fd30fd11b 100644 --- a/bigtable/google/cloud/bigtable/table.py +++ b/bigtable/google/cloud/bigtable/table.py @@ -142,12 +142,12 @@ def row(self, row_key, filter_=None, append=False): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return (other.table_id == self.table_id and other._instance == self._instance) def __ne__(self, other): - return not self.__eq__(other) + return not self == other def create(self, initial_split_keys=None, column_families=()): """Creates this table. diff --git a/bigtable/tests/unit/test_column_family.py b/bigtable/tests/unit/test_column_family.py index 6fa408fdb07e..73b836501b47 100644 --- a/bigtable/tests/unit/test_column_family.py +++ b/bigtable/tests/unit/test_column_family.py @@ -12,9 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. - import unittest +import mock + class TestMaxVersionsGCRule(unittest.TestCase): @@ -29,8 +30,8 @@ def _make_one(self, *args, **kwargs): def test___eq__type_differ(self): gc_rule1 = self._make_one(10) - gc_rule2 = object() - self.assertNotEqual(gc_rule1, gc_rule2) + self.assertNotEqual(gc_rule1, object()) + self.assertEqual(gc_rule1, mock.ANY) def test___eq__same_value(self): gc_rule1 = self._make_one(2) diff --git a/datastore/google/cloud/datastore/entity.py b/datastore/google/cloud/datastore/entity.py index e74d5aa640ee..be30aa915172 100644 --- a/datastore/google/cloud/datastore/entity.py +++ b/datastore/google/cloud/datastore/entity.py @@ -146,7 +146,7 @@ def __eq__(self, other): :returns: True if the entities compare equal, else False. """ if not isinstance(other, Entity): - return False + return NotImplemented return (self.key == other.key and self.exclude_from_indexes == other.exclude_from_indexes and @@ -162,7 +162,7 @@ def __ne__(self, other): :rtype: bool :returns: False if the entities compare equal, else True. """ - return not self.__eq__(other) + return not self == other @property def kind(self): diff --git a/datastore/google/cloud/datastore/helpers.py b/datastore/google/cloud/datastore/helpers.py index ee4537317030..eeae9d427572 100644 --- a/datastore/google/cloud/datastore/helpers.py +++ b/datastore/google/cloud/datastore/helpers.py @@ -454,7 +454,7 @@ def __eq__(self, other): :returns: True if the points compare equal, else False. """ if not isinstance(other, GeoPoint): - return False + return NotImplemented return (self.latitude == other.latitude and self.longitude == other.longitude) @@ -465,4 +465,4 @@ def __ne__(self, other): :rtype: bool :returns: False if the points compare equal, else True. """ - return not self.__eq__(other) + return not self == other diff --git a/datastore/google/cloud/datastore/key.py b/datastore/google/cloud/datastore/key.py index f1733f8f5d8e..615cab696568 100644 --- a/datastore/google/cloud/datastore/key.py +++ b/datastore/google/cloud/datastore/key.py @@ -123,7 +123,7 @@ def __eq__(self, other): :returns: True if the keys compare equal, else False. """ if not isinstance(other, Key): - return False + return NotImplemented if self.is_partial or other.is_partial: return False @@ -143,7 +143,7 @@ def __ne__(self, other): :rtype: bool :returns: False if the keys compare equal, else True. """ - return not self.__eq__(other) + return not self == other def __hash__(self): """Hash a keys for use in a dictionary lookp. diff --git a/monitoring/google/cloud/monitoring/label.py b/monitoring/google/cloud/monitoring/label.py index 602a2eb99aa5..0ea909a0a75e 100644 --- a/monitoring/google/cloud/monitoring/label.py +++ b/monitoring/google/cloud/monitoring/label.py @@ -87,10 +87,12 @@ def _to_dict(self): return info def __eq__(self, other): + if not isinstance(other, LabelDescriptor): + return NotImplemented return self.__dict__ == other.__dict__ def __ne__(self, other): - return self.__dict__ != other.__dict__ + return not self == other def __repr__(self): return ( diff --git a/monitoring/tests/unit/test_label.py b/monitoring/tests/unit/test_label.py index 11b66f92ae71..24fb6808bf82 100644 --- a/monitoring/tests/unit/test_label.py +++ b/monitoring/tests/unit/test_label.py @@ -14,6 +14,8 @@ import unittest +import mock + class TestLabelValueType(unittest.TestCase): @@ -108,9 +110,13 @@ def test_equality(self): KEY = 'response_code' VALUE_TYPE = 'INT64' DESCRIPTION = 'HTTP status code for the request.' - descriptor1 = self._make_one(key=KEY, value_type=VALUE_TYPE, - description=DESCRIPTION) + descriptor1a = self._make_one(key=KEY, value_type=VALUE_TYPE, + description=DESCRIPTION) + descriptor1b = self._make_one(key=KEY, value_type=VALUE_TYPE, + description=DESCRIPTION) descriptor2 = self._make_one(key=KEY, value_type=VALUE_TYPE, - description=DESCRIPTION) - self.assertTrue(descriptor1 == descriptor2) - self.assertFalse(descriptor1 != descriptor2) + description=DESCRIPTION + 'foo') + self.assertEqual(descriptor1a, descriptor1b) + self.assertNotEqual(descriptor1a, descriptor2) + self.assertNotEqual(descriptor1a, object()) + self.assertEqual(descriptor1a, mock.ANY) diff --git a/spanner/google/cloud/spanner/database.py b/spanner/google/cloud/spanner/database.py index acfcefdce891..72dd926368bd 100644 --- a/spanner/google/cloud/spanner/database.py +++ b/spanner/google/cloud/spanner/database.py @@ -170,12 +170,12 @@ def spanner_api(self): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented return (other.database_id == self.database_id and other._instance == self._instance) def __ne__(self, other): - return not self.__eq__(other) + return not self == other def create(self): """Create this database within its instance diff --git a/spanner/google/cloud/spanner/instance.py b/spanner/google/cloud/spanner/instance.py index 5bd4663764f5..9d98751dde19 100644 --- a/spanner/google/cloud/spanner/instance.py +++ b/spanner/google/cloud/spanner/instance.py @@ -148,7 +148,7 @@ def name(self): def __eq__(self, other): if not isinstance(other, self.__class__): - return False + return NotImplemented # NOTE: This does not compare the configuration values, such as # the display_name. Instead, it only compares # identifying values instance ID and client. This is @@ -159,7 +159,7 @@ def __eq__(self, other): other._client == self._client) def __ne__(self, other): - return not self.__eq__(other) + return not self == other def copy(self): """Make a copy of this instance.