Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Rename 'Dataset.access_grants' -> 'Dataaset.access_entries'.
  • Loading branch information
tseaver committed Aug 13, 2017
commit 709ba64ebce51e110d3e0cbd8d0d6c426f1cf53e
60 changes: 30 additions & 30 deletions bigquery/google/cloud/bigquery/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,22 +104,22 @@ class Dataset(object):
:param client: A client which holds credentials and project configuration
for the dataset (which requires a project).

:type access_grants: list of :class:`AccessEntry`
:param access_grants: roles granted to entities for this dataset
:type access_entries: list of :class:`AccessEntry`
:param access_entries: roles granted to entities for this dataset

:type project: str
:param project: (Optional) project ID for the dataset (defaults to
the project of the client).
"""

_access_grants = None
_access_entries = None

def __init__(self, name, client, access_grants=(), project=None):
def __init__(self, name, client, access_entries=(), project=None):
self.name = name
self._client = client
self._properties = {}
# Let the @property do validation.
self.access_grants = access_grants
self.access_entries = access_entries
self._project = project or client.project

@property
Expand All @@ -141,17 +141,17 @@ def path(self):
return '/projects/%s/datasets/%s' % (self.project, self.name)

@property
def access_grants(self):
"""Dataset's access grants.
def access_entries(self):
"""Dataset's access entries.

:rtype: list of :class:`AccessEntry`
:returns: roles granted to entities for this dataset
"""
return list(self._access_grants)
return list(self._access_entries)

@access_grants.setter
def access_grants(self, value):
"""Update dataset's access grants
@access_entries.setter
def access_entries(self, value):
"""Update dataset's access entries

:type value: list of :class:`AccessEntry`
:param value: roles granted to entities for this dataset
Expand All @@ -161,7 +161,7 @@ def access_grants(self, value):
"""
if not all(isinstance(field, AccessEntry) for field in value):
raise ValueError('Values must be AccessEntry instances')
self._access_grants = tuple(value)
self._access_entries = tuple(value)

@property
def created(self):
Expand Down Expand Up @@ -341,27 +341,27 @@ def _require_client(self, client):
return client

@staticmethod
def _parse_access_grants(access):
"""Parse a resource fragment into a set of access grants.
def _parse_access_entries(access):
"""Parse a resource fragment into a set of access entries.

``role`` augments the entity type and present **unless** the entity
type is ``view``.

:type access: list of mappings
:param access: each mapping represents a single access grant.
:param access: each mapping represents a single access entry.

:rtype: list of :class:`AccessEntry`
:returns: a list of parsed grants.
:raises: :class:`ValueError` if a grant in ``access`` has more keys
:returns: a list of parsed entries.
:raises: :class:`ValueError` if a entry in ``access`` has more keys
than ``role`` and one additional key.
"""
result = []
for grant in access:
grant = grant.copy()
role = grant.pop('role', None)
entity_type, entity_id = grant.popitem()
if len(grant) != 0:
raise ValueError('Grant has unexpected keys remaining.', grant)
for entry in access:
entry = entry.copy()
role = entry.pop('role', None)
entity_type, entity_id = entry.popitem()
if len(entry) != 0:
raise ValueError('Entry has unexpected keys remaining.', entry)
result.append(
AccessEntry(role, entity_type, entity_id))
return result
Expand All @@ -375,7 +375,7 @@ def _set_properties(self, api_response):
self._properties.clear()
cleaned = api_response.copy()
access = cleaned.pop('access', ())
self.access_grants = self._parse_access_grants(access)
self.access_entries = self._parse_access_entries(access)
if 'creationTime' in cleaned:
cleaned['creationTime'] = float(cleaned['creationTime'])
if 'lastModifiedTime' in cleaned:
Expand All @@ -386,12 +386,12 @@ def _set_properties(self, api_response):
self._properties.update(cleaned)

def _build_access_resource(self):
"""Generate a resource fragment for dataset's access grants."""
"""Generate a resource fragment for dataset's access entries."""
result = []
for grant in self.access_grants:
info = {grant.entity_type: grant.entity_id}
if grant.role is not None:
info['role'] = grant.role
for entry in self.access_entries:
info = {entry.entity_type: entry.entity_id}
if entry.role is not None:
info['role'] = entry.role
result.append(info)
return result

Expand All @@ -414,7 +414,7 @@ def _build_resource(self):
if self.location is not None:
resource['location'] = self.location

if len(self.access_grants) > 0:
if len(self.access_entries) > 0:
resource['access'] = self._build_access_resource()

return resource
Expand Down
103 changes: 52 additions & 51 deletions bigquery/tests/unit/test_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ def _make_one(self, *args, **kw):
return self._get_target_class()(*args, **kw)

def test_ctor_defaults(self):
grant = self._make_one('OWNER', 'userByEmail', 'phred@example.com')
self.assertEqual(grant.role, 'OWNER')
self.assertEqual(grant.entity_type, 'userByEmail')
self.assertEqual(grant.entity_id, 'phred@example.com')
entry = self._make_one('OWNER', 'userByEmail', 'phred@example.com')
self.assertEqual(entry.role, 'OWNER')
self.assertEqual(entry.entity_type, 'userByEmail')
self.assertEqual(entry.entity_id, 'phred@example.com')

def test_ctor_bad_entity_type(self):
with self.assertRaises(ValueError):
Expand All @@ -48,10 +48,10 @@ def test_ctor_view_success(self):
role = None
entity_type = 'view'
entity_id = object()
grant = self._make_one(role, entity_type, entity_id)
self.assertEqual(grant.role, role)
self.assertEqual(grant.entity_type, entity_type)
self.assertEqual(grant.entity_id, entity_id)
entry = self._make_one(role, entity_type, entity_id)
self.assertEqual(entry.role, role)
self.assertEqual(entry.entity_type, entity_type)
self.assertEqual(entry.entity_id, entity_id)

def test_ctor_nonview_without_role(self):
role = None
Expand All @@ -60,29 +60,29 @@ def test_ctor_nonview_without_role(self):
self._make_one(role, entity_type, None)

def test___eq___role_mismatch(self):
grant = self._make_one('OWNER', 'userByEmail', 'phred@example.com')
entry = self._make_one('OWNER', 'userByEmail', 'phred@example.com')
other = self._make_one('WRITER', 'userByEmail', 'phred@example.com')
self.assertNotEqual(grant, other)
self.assertNotEqual(entry, other)

def test___eq___entity_type_mismatch(self):
grant = self._make_one('OWNER', 'userByEmail', 'phred@example.com')
entry = self._make_one('OWNER', 'userByEmail', 'phred@example.com')
other = self._make_one('OWNER', 'groupByEmail', 'phred@example.com')
self.assertNotEqual(grant, other)
self.assertNotEqual(entry, other)

def test___eq___entity_id_mismatch(self):
grant = self._make_one('OWNER', 'userByEmail', 'phred@example.com')
entry = self._make_one('OWNER', 'userByEmail', 'phred@example.com')
other = self._make_one('OWNER', 'userByEmail', 'bharney@example.com')
self.assertNotEqual(grant, other)
self.assertNotEqual(entry, other)

def test___eq___hit(self):
grant = self._make_one('OWNER', 'userByEmail', 'phred@example.com')
entry = self._make_one('OWNER', 'userByEmail', 'phred@example.com')
other = self._make_one('OWNER', 'userByEmail', 'phred@example.com')
self.assertEqual(grant, other)
self.assertEqual(entry, 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)
entry = self._make_one('OWNER', 'userByEmail', 'silly@example.com')
self.assertNotEqual(entry, object())
self.assertEqual(entry, mock.ANY)


class TestDataset(unittest.TestCase):
Expand Down Expand Up @@ -129,20 +129,21 @@ def _makeResource(self):
{'role': 'READER', 'specialGroup': 'projectReaders'}],
}

def _verify_access_entry(self, access_grants, resource):
r_grants = []
for r_grant in resource['access']:
role = r_grant.pop('role')
for entity_type, entity_id in sorted(r_grant.items()):
r_grants.append({'role': role,
'entity_type': entity_type,
'entity_id': entity_id})

self.assertEqual(len(access_grants), len(r_grants))
for a_grant, r_grant in zip(access_grants, r_grants):
self.assertEqual(a_grant.role, r_grant['role'])
self.assertEqual(a_grant.entity_type, r_grant['entity_type'])
self.assertEqual(a_grant.entity_id, r_grant['entity_id'])
def _verify_access_entry(self, access_entries, resource):
r_entries = []
for r_entry in resource['access']:
role = r_entry.pop('role')
for entity_type, entity_id in sorted(r_entry.items()):
r_entries.append({
'role': role,
'entity_type': entity_type,
'entity_id': entity_id})

self.assertEqual(len(access_entries), len(r_entries))
for a_entry, r_entry in zip(access_entries, r_entries):
self.assertEqual(a_entry.role, r_entry['role'])
self.assertEqual(a_entry.entity_type, r_entry['entity_type'])
self.assertEqual(a_entry.entity_id, r_entry['entity_id'])

def _verify_readonly_resource_properties(self, dataset, resource):

Expand Down Expand Up @@ -179,9 +180,9 @@ def _verify_resource_properties(self, dataset, resource):
self.assertEqual(dataset.location, resource.get('location'))

if 'access' in resource:
self._verify_access_entry(dataset.access_grants, resource)
self._verify_access_entry(dataset.access_entries, resource)
else:
self.assertEqual(dataset.access_grants, [])
self.assertEqual(dataset.access_entries, [])

def test_ctor_defaults(self):
client = _Client(self.PROJECT)
Expand All @@ -192,7 +193,7 @@ def test_ctor_defaults(self):
self.assertEqual(
dataset.path,
'/projects/%s/datasets/%s' % (self.PROJECT, self.DS_NAME))
self.assertEqual(dataset.access_grants, [])
self.assertEqual(dataset.access_entries, [])

self.assertIsNone(dataset.created)
self.assertIsNone(dataset.dataset_id)
Expand All @@ -210,19 +211,19 @@ def test_ctor_explicit(self):

phred = AccessEntry('OWNER', 'userByEmail', 'phred@example.com')
bharney = AccessEntry('OWNER', 'userByEmail', 'bharney@example.com')
grants = [phred, bharney]
entries = [phred, bharney]
OTHER_PROJECT = 'foo-bar-123'
client = _Client(self.PROJECT)
dataset = self._make_one(self.DS_NAME, client,
access_grants=grants,
access_entries=entries,
project=OTHER_PROJECT)
self.assertEqual(dataset.name, self.DS_NAME)
self.assertIs(dataset._client, client)
self.assertEqual(dataset.project, OTHER_PROJECT)
self.assertEqual(
dataset.path,
'/projects/%s/datasets/%s' % (OTHER_PROJECT, self.DS_NAME))
self.assertEqual(dataset.access_grants, grants)
self.assertEqual(dataset.access_entries, entries)

self.assertIsNone(dataset.created)
self.assertIsNone(dataset.dataset_id)
Expand All @@ -235,30 +236,30 @@ def test_ctor_explicit(self):
self.assertIsNone(dataset.friendly_name)
self.assertIsNone(dataset.location)

def test_access_grants_setter_non_list(self):
def test_access_entries_setter_non_list(self):
client = _Client(self.PROJECT)
dataset = self._make_one(self.DS_NAME, client)
with self.assertRaises(TypeError):
dataset.access_grants = object()
dataset.access_entries = object()

def test_access_grants_setter_invalid_field(self):
def test_access_entries_setter_invalid_field(self):
from google.cloud.bigquery.dataset import AccessEntry

client = _Client(self.PROJECT)
dataset = self._make_one(self.DS_NAME, client)
phred = AccessEntry('OWNER', 'userByEmail', 'phred@example.com')
with self.assertRaises(ValueError):
dataset.access_grants = [phred, object()]
dataset.access_entries = [phred, object()]

def test_access_grants_setter(self):
def test_access_entries_setter(self):
from google.cloud.bigquery.dataset import AccessEntry

client = _Client(self.PROJECT)
dataset = self._make_one(self.DS_NAME, client)
phred = AccessEntry('OWNER', 'userByEmail', 'phred@example.com')
bharney = AccessEntry('OWNER', 'userByEmail', 'bharney@example.com')
dataset.access_grants = [phred, bharney]
self.assertEqual(dataset.access_grants, [phred, bharney])
dataset.access_entries = [phred, bharney]
self.assertEqual(dataset.access_entries, [phred, bharney])

def test_default_table_expiration_ms_setter_bad_value(self):
client = _Client(self.PROJECT)
Expand Down Expand Up @@ -339,16 +340,16 @@ def test_from_api_repr_w_properties(self):
self.assertIs(dataset._client, client)
self._verify_resource_properties(dataset, RESOURCE)

def test__parse_access_grants_w_unknown_entity_type(self):
def test__parse_access_entries_w_unknown_entity_type(self):
ACCESS = [
{'role': 'READER', 'unknown': 'UNKNOWN'},
]
client = _Client(self.PROJECT)
dataset = self._make_one(self.DS_NAME, client=client)
with self.assertRaises(ValueError):
dataset._parse_access_grants(ACCESS)
dataset._parse_access_entries(ACCESS)

def test__parse_access_grants_w_extra_keys(self):
def test__parse_access_entries_w_extra_keys(self):
USER_EMAIL = 'phred@example.com'
ACCESS = [
{
Expand All @@ -360,7 +361,7 @@ def test__parse_access_grants_w_extra_keys(self):
client = _Client(self.PROJECT)
dataset = self._make_one(self.DS_NAME, client=client)
with self.assertRaises(ValueError):
dataset._parse_access_grants(ACCESS)
dataset._parse_access_entries(ACCESS)

def test_create_w_bound_client(self):
PATH = 'projects/%s/datasets' % self.PROJECT
Expand Down Expand Up @@ -405,7 +406,7 @@ def test_create_w_alternate_client(self):
'datasetId': 'starry-skies',
'tableId': 'northern-hemisphere',
}
dataset.access_grants = [
dataset.access_entries = [
AccessEntry('OWNER', 'userByEmail', USER_EMAIL),
AccessEntry('OWNER', 'groupByEmail', GROUP_EMAIL),
AccessEntry('READER', 'domain', 'foo.com'),
Expand Down