From 008ef288bd1a05f4cd5abc3d52e9f78bfe3781b9 Mon Sep 17 00:00:00 2001 From: HemangChothani Date: Fri, 10 Jul 2020 18:01:19 +0530 Subject: [PATCH 1/3] feat(bigquery): add __eq__ method for class PartitionRange and RangePartitioning --- google/cloud/bigquery/table.py | 22 +++++++ tests/unit/test_table.py | 107 +++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) diff --git a/google/cloud/bigquery/table.py b/google/cloud/bigquery/table.py index 5f557d28a..1e40dd619 100644 --- a/google/cloud/bigquery/table.py +++ b/google/cloud/bigquery/table.py @@ -1894,10 +1894,21 @@ def interval(self, value): def _key(self): return tuple(sorted(self._properties.items())) + def __eq__(self, other): + if not isinstance(other, PartitionRange): + return NotImplemented + return self._key() == other._key() + + def __ne__(self, other): + return not self == other + def __repr__(self): key_vals = ["{}={}".format(key, val) for key, val in self._key()] return "PartitionRange({})".format(", ".join(key_vals)) + def __hash__(self): + return hash(self._key()) + class RangePartitioning(object): """Range-based partitioning configuration for a table. @@ -1964,10 +1975,21 @@ def field(self, value): def _key(self): return (("field", self.field), ("range_", self.range_)) + def __eq__(self, other): + if not isinstance(other, RangePartitioning): + return NotImplemented + return self._key() == other._key() + + def __ne__(self, other): + return not self == other + def __repr__(self): key_vals = ["{}={}".format(key, repr(val)) for key, val in self._key()] return "RangePartitioning({})".format(", ".join(key_vals)) + def __hash__(self): + return hash(self._key()) + class TimePartitioningType(object): """Specifies the type of time partitioning to perform.""" diff --git a/tests/unit/test_table.py b/tests/unit/test_table.py index 94a326617..1e190ce51 100644 --- a/tests/unit/test_table.py +++ b/tests/unit/test_table.py @@ -3525,6 +3525,45 @@ def test_constructor_w_resource(self): assert object_under_test.end == 1234567890 assert object_under_test.interval == 1000000 + def test___eq___start_mismatch(self): + object_under_test = self._make_one(start=1, end=10, interval=2) + other = self._make_one(start=2, end=10, interval=2) + self.assertNotEqual(object_under_test, other) + + def test___eq___end__mismatch(self): + object_under_test = self._make_one(start=1, end=10, interval=2) + other = self._make_one(start=1, end=11, interval=2) + self.assertNotEqual(object_under_test, other) + + def test___eq___interval__mismatch(self): + object_under_test = self._make_one(start=1, end=10, interval=2) + other = self._make_one(start=1, end=11, interval=3) + self.assertNotEqual(object_under_test, other) + + def test___eq___hit(self): + object_under_test = self._make_one(start=1, end=10, interval=2) + other = self._make_one(start=1, end=10, interval=2) + self.assertEqual(object_under_test, other) + + def test__eq___type_mismatch(self): + object_under_test = self._make_one(start=1, end=10, interval=2) + self.assertNotEqual(object_under_test, object()) + self.assertEqual(object_under_test, mock.ANY) + + def test___hash__set_equality(self): + object_under_test1 = self._make_one(start=1, end=10, interval=2) + object_under_test2 = self._make_one(start=1, end=10, interval=3) + set_one = {object_under_test1, object_under_test2} + set_two = {object_under_test1, object_under_test2} + self.assertEqual(set_one, set_two) + + def test___hash__not_equals(self): + object_under_test1 = self._make_one(start=1, end=10, interval=2) + object_under_test2 = self._make_one(start=1, end=10, interval=3) + set_one = {object_under_test1} + set_two = {object_under_test2} + self.assertNotEqual(set_one, set_two) + def test_repr(self): object_under_test = self._make_one(start=1, end=10, interval=2) assert repr(object_under_test) == "PartitionRange(end=10, interval=2, start=1)" @@ -3574,6 +3613,74 @@ def test_range_w_wrong_type(self): with pytest.raises(ValueError, match="PartitionRange"): object_under_test.range_ = object() + def test___eq___field_mismatch(self): + from google.cloud.bigquery.table import PartitionRange + + object_under_test = self._make_one( + range_=PartitionRange(start=1, end=10, interval=2), field="integer_col" + ) + other = self._make_one( + range_=PartitionRange(start=1, end=10, interval=2), field="float_col" + ) + self.assertNotEqual(object_under_test, other) + + def test___eq___range__mismatch(self): + from google.cloud.bigquery.table import PartitionRange + + object_under_test = self._make_one( + range_=PartitionRange(start=1, end=10, interval=2), field="integer_col" + ) + other = self._make_one( + range_=PartitionRange(start=2, end=20, interval=2), field="float_col" + ) + self.assertNotEqual(object_under_test, other) + + def test___eq___hit(self): + from google.cloud.bigquery.table import PartitionRange + + object_under_test = self._make_one( + range_=PartitionRange(start=1, end=10, interval=2), field="integer_col" + ) + other = self._make_one( + range_=PartitionRange(start=1, end=10, interval=2), field="integer_col" + ) + self.assertEqual(object_under_test, other) + + def test__eq___type_mismatch(self): + from google.cloud.bigquery.table import PartitionRange + + object_under_test = self._make_one( + range_=PartitionRange(start=1, end=10, interval=2), field="integer_col" + ) + self.assertNotEqual(object_under_test, object()) + self.assertEqual(object_under_test, mock.ANY) + + def test___hash__set_equality(self): + from google.cloud.bigquery.table import PartitionRange + + object_under_test1 = self._make_one( + range_=PartitionRange(start=1, end=10, interval=2), field="integer_col" + ) + object_under_test2 = self._make_one( + range_=PartitionRange(start=1, end=10, interval=2), field="float_col" + ) + set_one = {object_under_test1, object_under_test2} + set_two = {object_under_test1, object_under_test2} + self.assertEqual(set_one, set_two) + + def test___hash__not_equals(self): + from google.cloud.bigquery.table import PartitionRange + + object_under_test1 = self._make_one( + range_=PartitionRange(start=1, end=10, interval=2), field="integer_col" + ) + object_under_test2 = self._make_one( + range_=PartitionRange(start=1, end=10, interval=2), field="float_col" + ) + set_one = {object_under_test1} + set_two = {object_under_test2} + self.assertNotEqual(set_one, set_two) + def test_repr(self): from google.cloud.bigquery.table import PartitionRange From 6b332c0dd1922b66870b866b0eb4909de7bf4440 Mon Sep 17 00:00:00 2001 From: HemangChothani Date: Mon, 13 Jul 2020 15:51:57 +0530 Subject: [PATCH 2/3] feat(bigquery): change class object to unhashable --- google/cloud/bigquery/table.py | 6 ++---- tests/unit/test_table.py | 35 ++++------------------------------ 2 files changed, 6 insertions(+), 35 deletions(-) diff --git a/google/cloud/bigquery/table.py b/google/cloud/bigquery/table.py index 0b4ed1ba9..f1575ffb2 100644 --- a/google/cloud/bigquery/table.py +++ b/google/cloud/bigquery/table.py @@ -1903,8 +1903,7 @@ def __repr__(self): key_vals = ["{}={}".format(key, val) for key, val in self._key()] return "PartitionRange({})".format(", ".join(key_vals)) - def __hash__(self): - return hash(self._key()) + __hash__ = None class RangePartitioning(object): @@ -1984,8 +1983,7 @@ def __repr__(self): key_vals = ["{}={}".format(key, repr(val)) for key, val in self._key()] return "RangePartitioning({})".format(", ".join(key_vals)) - def __hash__(self): - return hash(self._key()) + __hash__ = None class TimePartitioningType(object): diff --git a/tests/unit/test_table.py b/tests/unit/test_table.py index 1e190ce51..05830d872 100644 --- a/tests/unit/test_table.py +++ b/tests/unit/test_table.py @@ -3550,19 +3550,10 @@ def test__eq___type_mismatch(self): self.assertNotEqual(object_under_test, object()) self.assertEqual(object_under_test, mock.ANY) - def test___hash__set_equality(self): + def test_unhashable_object(self): object_under_test1 = self._make_one(start=1, end=10, interval=2) - object_under_test2 = self._make_one(start=1, end=10, interval=3) - set_one = {object_under_test1, object_under_test2} - set_two = {object_under_test1, object_under_test2} - self.assertEqual(set_one, set_two) - def test___hash__not_equals(self): - object_under_test1 = self._make_one(start=1, end=10, interval=2) - object_under_test2 = self._make_one(start=1, end=10, interval=3) - set_one = {object_under_test1} - set_two = {object_under_test2} - self.assertNotEqual(set_one, set_two) + self.assertIsNone(object_under_test1.__hash__) def test_repr(self): object_under_test = self._make_one(start=1, end=10, interval=2) @@ -3655,31 +3646,13 @@ def test__eq___type_mismatch(self): self.assertNotEqual(object_under_test, object()) self.assertEqual(object_under_test, mock.ANY) - def test___hash__set_equality(self): + def test_unhashable_object(self): from google.cloud.bigquery.table import PartitionRange object_under_test1 = self._make_one( range_=PartitionRange(start=1, end=10, interval=2), field="integer_col" ) - object_under_test2 = self._make_one( - range_=PartitionRange(start=1, end=10, interval=2), field="float_col" - ) - set_one = {object_under_test1, object_under_test2} - set_two = {object_under_test1, object_under_test2} - self.assertEqual(set_one, set_two) - - def test___hash__not_equals(self): - from google.cloud.bigquery.table import PartitionRange - - object_under_test1 = self._make_one( - range_=PartitionRange(start=1, end=10, interval=2), field="integer_col" - ) - object_under_test2 = self._make_one( - range_=PartitionRange(start=1, end=10, interval=2), field="float_col" - ) - set_one = {object_under_test1} - set_two = {object_under_test2} - self.assertNotEqual(set_one, set_two) + self.assertIsNone(object_under_test1.__hash__) def test_repr(self): from google.cloud.bigquery.table import PartitionRange From aa7d5e9e3abcefb8e6166cc97b7940ab565e74d3 Mon Sep 17 00:00:00 2001 From: HemangChothani Date: Mon, 13 Jul 2020 17:42:56 +0530 Subject: [PATCH 3/3] feat(bigquery): change the assertion --- tests/unit/test_table.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_table.py b/tests/unit/test_table.py index 05830d872..3aabebb77 100644 --- a/tests/unit/test_table.py +++ b/tests/unit/test_table.py @@ -3553,7 +3553,8 @@ def test__eq___type_mismatch(self): def test_unhashable_object(self): object_under_test1 = self._make_one(start=1, end=10, interval=2) - self.assertIsNone(object_under_test1.__hash__) + with six.assertRaisesRegex(self, TypeError, r".*unhashable type.*"): + hash(object_under_test1) def test_repr(self): object_under_test = self._make_one(start=1, end=10, interval=2) @@ -3652,7 +3653,8 @@ def test_unhashable_object(self): object_under_test1 = self._make_one( range_=PartitionRange(start=1, end=10, interval=2), field="integer_col" ) - self.assertIsNone(object_under_test1.__hash__) + with six.assertRaisesRegex(self, TypeError, r".*unhashable type.*"): + hash(object_under_test1) def test_repr(self): from google.cloud.bigquery.table import PartitionRange