Skip to content

Commit

Permalink
feat: make AccessEntry objects hashable (#93)
Browse files Browse the repository at this point in the history
* feat: add a __hash__ implementation to AccessEntry

* use internal

* feat: unit tests for hashable AccessEntry

* fix: black lint issue

Co-authored-by: Peter Lamut <plamut@users.noreply.github.com>
  • Loading branch information
spennymac and plamut authored May 15, 2020
1 parent 0dd90b9 commit 23a173b
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 14 deletions.
51 changes: 37 additions & 14 deletions google/cloud/bigquery/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import copy

import google.cloud._helpers

from google.cloud.bigquery import _helpers
from google.cloud.bigquery.model import ModelReference
from google.cloud.bigquery.routine import RoutineReference
Expand Down Expand Up @@ -145,38 +146,60 @@ def __init__(self, role, entity_type, entity_id):
"Role must be set for entity " "type %r" % (entity_type,)
)

self.role = role
self.entity_type = entity_type
self.entity_id = entity_id
self._role = role
self._entity_type = entity_type
self._entity_id = entity_id

@property
def role(self):
"""str: The role of the entry."""
return self._role

@property
def entity_type(self):
"""str: The entity_type of the entry."""
return self._entity_type

@property
def entity_id(self):
"""str: The entity_id of the entry."""
return self._entity_id

def __eq__(self, other):
if not isinstance(other, AccessEntry):
return NotImplemented
return (
self.role == other.role
and self.entity_type == other.entity_type
and self.entity_id == other.entity_id
)
return self._key() == other._key()

def __ne__(self, other):
return not self == other

def __repr__(self):
return "<AccessEntry: role=%s, %s=%s>" % (
self.role,
self.entity_type,
self.entity_id,
self._role,
self._entity_type,
self._entity_id,
)

def _key(self):
""" A tuple key that uniquely describes this field.
Used to compute this instance's hashcode and evaluate equality.
Returns:
Tuple: The contents of this :class:`~google.cloud.bigquery.dataset.AccessEntry`.
"""
return (self._role, self._entity_type, self._entity_id)

def __hash__(self):
return hash(self._key())

def to_api_repr(self):
"""Construct the API resource representation of this access entry
Returns:
Dict[str, object]: Access entry represented as an API resource
"""
resource = {self.entity_type: self.entity_id}
if self.role is not None:
resource["role"] = self.role
resource = {self._entity_type: self._entity_id}
if self._role is not None:
resource["role"] = self._role
return resource

@classmethod
Expand Down
14 changes: 14 additions & 0 deletions tests/unit/test_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,20 @@ def test__eq___type_mismatch(self):
self.assertNotEqual(entry, object())
self.assertEqual(entry, mock.ANY)

def test___hash__set_equality(self):
entry1 = self._make_one("OWNER", "userByEmail", "silly@example.com")
entry2 = self._make_one("OWNER", "userByEmail", "phred@example.com")
set_one = {entry1, entry2}
set_two = {entry1, entry2}
self.assertEqual(set_one, set_two)

def test___hash__not_equals(self):
entry1 = self._make_one("OWNER", "userByEmail", "silly@example.com")
entry2 = self._make_one("OWNER", "userByEmail", "phred@example.com")
set_one = {entry1}
set_two = {entry2}
self.assertNotEqual(set_one, set_two)

def test_to_api_repr(self):
entry = self._make_one("OWNER", "userByEmail", "salmon@example.com")
resource = entry.to_api_repr()
Expand Down

0 comments on commit 23a173b

Please sign in to comment.