Skip to content

Commit 23a173b

Browse files
spennymacplamut
andauthored
feat: make AccessEntry objects hashable (#93)
* feat: add a __hash__ implementation to AccessEntry * use internal * feat: unit tests for hashable AccessEntry * fix: black lint issue Co-authored-by: Peter Lamut <[email protected]>
1 parent 0dd90b9 commit 23a173b

File tree

2 files changed

+51
-14
lines changed

2 files changed

+51
-14
lines changed

google/cloud/bigquery/dataset.py

+37-14
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import copy
2121

2222
import google.cloud._helpers
23+
2324
from google.cloud.bigquery import _helpers
2425
from google.cloud.bigquery.model import ModelReference
2526
from google.cloud.bigquery.routine import RoutineReference
@@ -145,38 +146,60 @@ def __init__(self, role, entity_type, entity_id):
145146
"Role must be set for entity " "type %r" % (entity_type,)
146147
)
147148

148-
self.role = role
149-
self.entity_type = entity_type
150-
self.entity_id = entity_id
149+
self._role = role
150+
self._entity_type = entity_type
151+
self._entity_id = entity_id
152+
153+
@property
154+
def role(self):
155+
"""str: The role of the entry."""
156+
return self._role
157+
158+
@property
159+
def entity_type(self):
160+
"""str: The entity_type of the entry."""
161+
return self._entity_type
162+
163+
@property
164+
def entity_id(self):
165+
"""str: The entity_id of the entry."""
166+
return self._entity_id
151167

152168
def __eq__(self, other):
153169
if not isinstance(other, AccessEntry):
154170
return NotImplemented
155-
return (
156-
self.role == other.role
157-
and self.entity_type == other.entity_type
158-
and self.entity_id == other.entity_id
159-
)
171+
return self._key() == other._key()
160172

161173
def __ne__(self, other):
162174
return not self == other
163175

164176
def __repr__(self):
165177
return "<AccessEntry: role=%s, %s=%s>" % (
166-
self.role,
167-
self.entity_type,
168-
self.entity_id,
178+
self._role,
179+
self._entity_type,
180+
self._entity_id,
169181
)
170182

183+
def _key(self):
184+
""" A tuple key that uniquely describes this field.
185+
Used to compute this instance's hashcode and evaluate equality.
186+
Returns:
187+
Tuple: The contents of this :class:`~google.cloud.bigquery.dataset.AccessEntry`.
188+
"""
189+
return (self._role, self._entity_type, self._entity_id)
190+
191+
def __hash__(self):
192+
return hash(self._key())
193+
171194
def to_api_repr(self):
172195
"""Construct the API resource representation of this access entry
173196
174197
Returns:
175198
Dict[str, object]: Access entry represented as an API resource
176199
"""
177-
resource = {self.entity_type: self.entity_id}
178-
if self.role is not None:
179-
resource["role"] = self.role
200+
resource = {self._entity_type: self._entity_id}
201+
if self._role is not None:
202+
resource["role"] = self._role
180203
return resource
181204

182205
@classmethod

tests/unit/test_dataset.py

+14
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,20 @@ def test__eq___type_mismatch(self):
8484
self.assertNotEqual(entry, object())
8585
self.assertEqual(entry, mock.ANY)
8686

87+
def test___hash__set_equality(self):
88+
entry1 = self._make_one("OWNER", "userByEmail", "[email protected]")
89+
entry2 = self._make_one("OWNER", "userByEmail", "[email protected]")
90+
set_one = {entry1, entry2}
91+
set_two = {entry1, entry2}
92+
self.assertEqual(set_one, set_two)
93+
94+
def test___hash__not_equals(self):
95+
entry1 = self._make_one("OWNER", "userByEmail", "[email protected]")
96+
entry2 = self._make_one("OWNER", "userByEmail", "[email protected]")
97+
set_one = {entry1}
98+
set_two = {entry2}
99+
self.assertNotEqual(set_one, set_two)
100+
87101
def test_to_api_repr(self):
88102
entry = self._make_one("OWNER", "userByEmail", "[email protected]")
89103
resource = entry.to_api_repr()

0 commit comments

Comments
 (0)