Skip to content

Commit 09c1d14

Browse files
committed
Work around hypothetical case parsing 'dataset.access_grants':
The back-end might return a grant with more than one entity_type for a given role. See: #1046 (comment)
1 parent f7fdc6f commit 09c1d14

File tree

2 files changed

+37
-11
lines changed

2 files changed

+37
-11
lines changed

gcloud/bigquery/dataset.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -290,9 +290,12 @@ def _parse_access_grants(self, access):
290290
for grant in access:
291291
grant = grant.copy()
292292
role = grant.pop('role')
293-
entity_type, entity_id = list(grant.items())[0]
294-
result.append(
295-
AccessGrant(role, entity_type, entity_id))
293+
# Hypothetical case: we don't know that the back-end will ever
294+
# return such structures, but they are logical. See:
295+
#https://github.com/GoogleCloudPlatform/gcloud-python/pull/1046#discussion_r36687769
296+
for entity_type, entity_id in grant.items():
297+
result.append(
298+
AccessGrant(role, entity_type, entity_id))
296299
return result
297300

298301
def _set_properties(self, api_response):

gcloud/bigquery/test_dataset.py

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,19 @@ def _makeResource(self):
7474
}
7575

7676
def _verifyAccessGrants(self, access_grants, resource):
77-
r_grants = resource['access']
78-
self.assertEqual(len(access_grants), len(r_grants))
77+
r_grants = []
78+
for r_grant in resource['access']:
79+
role = r_grant.pop('role')
80+
for entity_type, entity_id in r_grant.items():
81+
r_grants.append({'role': role,
82+
'entity_type': entity_type,
83+
'entity_id': entity_id})
7984

85+
self.assertEqual(len(access_grants), len(r_grants))
8086
for a_grant, r_grant in zip(access_grants, r_grants):
81-
role = r_grant.pop('role')
82-
self.assertEqual(a_grant.role, role)
83-
self.assertEqual(len(r_grant), 1)
84-
entity_type, entity_id = list(r_grant.items())[0]
85-
self.assertEqual(a_grant.entity_type, entity_type)
86-
self.assertEqual(a_grant.entity_id, entity_id)
87+
self.assertEqual(a_grant.role, r_grant['role'])
88+
self.assertEqual(a_grant.entity_type, r_grant['entity_type'])
89+
self.assertEqual(a_grant.entity_id, r_grant['entity_id'])
8790

8891
def _verifyReadonlyResourceProperties(self, dataset, resource):
8992

@@ -260,6 +263,26 @@ def test__parse_access_grants_w_unknown_entity_type(self):
260263
grants = dataset._parse_access_grants(RESOURCE['access'])
261264
self._verifyAccessGrants(grants, RESOURCE)
262265

266+
def test__parse_access_grants_w_multiple_entity_types(self):
267+
# Hypothetical case: we don't know that the back-end will ever
268+
# return such structures, but they are logical. See:
269+
#https://github.com/GoogleCloudPlatform/gcloud-python/pull/1046#discussion_r36687769
270+
USER_EMAIL = 'phred@example.com'
271+
OTHER_EMAIL = 'bharney@example.com'
272+
GROUP_EMAIL = 'group-name@lists.example.com'
273+
RESOURCE = {
274+
'access': [
275+
{'role': 'OWNER', 'userByEmail': USER_EMAIL},
276+
{'role': 'WRITER', 'groupByEmail': GROUP_EMAIL},
277+
{'role': 'READER',
278+
'specialGroup': 'projectReaders',
279+
'userByEmail': OTHER_EMAIL}]
280+
}
281+
client = _Client(self.PROJECT)
282+
dataset = self._makeOne(self.DS_NAME, client=client)
283+
grants = dataset._parse_access_grants(RESOURCE['access'])
284+
self._verifyAccessGrants(grants, RESOURCE)
285+
263286
def test_create_w_bound_client(self):
264287
PATH = 'projects/%s/datasets' % self.PROJECT
265288
RESOURCE = self._makeResource()

0 commit comments

Comments
 (0)