Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 1.8k
Add Dataset access support#1046
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
ba3109de2fa8e4cc746f5786288de72948c9c5d6dcf7fdc6f09c1d146720b35File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -20,6 +20,29 @@ | ||
| from gcloud.bigquery.table import Table | ||
| class AccessGrant(object): | ||
| """Represent grant of an access role to an entity. | ||
| :type role: string (one of 'OWNER', 'WRITER', 'READER'). | ||
| :param role: role granted to the entity. | ||
| :type entity_type: string (one of 'specialGroup', 'groupByEmail', or | ||
| 'userByEmail') | ||
| :param entity_type: type of entity being granted the role. | ||
| :type entity_id: string | ||
| :param entity_id: ID of entity being granted the role. | ||
| """ | ||
| def __init__(self, role, entity_type, entity_id): | ||
| self.role = role | ||
| self.entity_type = entity_type | ||
| self.entity_id = entity_id | ||
| def __repr__(self): | ||
| return '<AccessGrant: role=%s, %s=%s>' % ( | ||
| self.role, self.entity_type, self.entity_id) | ||
| class Dataset(object): | ||
| """Datasets are containers for tables. | ||
| @@ -32,12 +55,16 @@ class Dataset(object): | ||
| :type client: :class:`gcloud.bigquery.client.Client` | ||
| :param client: A client which holds credentials and project configuration | ||
| for the dataset (which requires a project). | ||
| :type access_grants: list of :class:`AccessGrant` | ||
| :param access_grants: roles granted to entities for this dataset | ||
| """ | ||
| def __init__(self, name, client): | ||
| def __init__(self, name, client, access_grants=()): | ||
| self.name = name | ||
| self._client = client | ||
| self._properties = {} | ||
| self.access_grants = access_grants | ||
| @property | ||
| def project(self): | ||
| @@ -57,6 +84,29 @@ def path(self): | ||
| """ | ||
| return '/projects/%s/datasets/%s' % (self.project, self.name) | ||
| @property | ||
| def access_grants(self): | ||
| """Dataset's access grants. | ||
| :rtype: list of :class:`AccessGrant` | ||
| :returns: roles granted to entities for this dataset | ||
| """ | ||
| return list(self._access_grants) | ||
| @access_grants.setter | ||
| def access_grants(self, value): | ||
| """Update dataset's access grants | ||
| :type value: list of :class:`AccessGrant` | ||
| :param value: roles granted to entities for this dataset | ||
| :raises: TypeError if 'value' is not a sequence, or ValueError if | ||
| any item in the sequence is not an AccessGrant | ||
| """ | ||
| if not all(isinstance(field, AccessGrant) for field in value): | ||
| raise ValueError('Values must be AccessGrant instances') | ||
| self._access_grants = tuple(value) | ||
| @property | ||
| def created(self): | ||
| """Datetime at which the dataset was created. | ||
| @@ -227,6 +277,27 @@ def _require_client(self, client): | ||
| client = self._client | ||
| return client | ||
| def _parse_access_grants(self, access): | ||
| """Parse a resource fragment into a set of access grants. | ||
| :type access: list of mappings | ||
| :param access: each mapping represents a single access grant | ||
| :rtype: list of :class:`AccessGrant` | ||
| :returns: a list of parsed grants | ||
| """ | ||
| result = [] | ||
| for grant in access: | ||
| grant = grant.copy() | ||
| role = grant.pop('role') | ||
| # Hypothetical case: we don't know that the back-end will ever | ||
| # return such structures, but they are logical. See: | ||
| # https://github.com/GoogleCloudPlatform/gcloud-python/pull/1046#discussion_r36687769 | ||
| for entity_type, entity_id in sorted(grant.items()): | ||
| result.append( | ||
| AccessGrant(role, entity_type, entity_id)) | ||
| return result | ||
| def _set_properties(self, api_response): | ||
| """Update properties from resource in body of ``api_response`` | ||
| @@ -235,12 +306,22 @@ 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) | ||
| if 'creationTime' in cleaned: | ||
| cleaned['creationTime'] = float(cleaned['creationTime']) | ||
| if 'lastModifiedTime' in cleaned: | ||
| cleaned['lastModifiedTime'] = float(cleaned['lastModifiedTime']) | ||
| self._properties.update(cleaned) | ||
| def _build_access_resource(self): | ||
This comment was marked as spam.Sorry, something went wrong. Uh oh!There was an error while loading. Please reload this page.
This comment was marked as spam.Sorry, something went wrong. Uh oh!There was an error while loading. Please reload this page.
This comment was marked as spam.Sorry, something went wrong. Uh oh!There was an error while loading. Please reload this page. | ||
| """Generate a resource fragment for dataset's access grants.""" | ||
| result = [] | ||
| for grant in self.access_grants: | ||
| info = {'role': grant.role, grant.entity_type: grant.entity_id} | ||
| result.append(info) | ||
| return result | ||
| def _build_resource(self): | ||
| """Generate a resource for ``create`` or ``update``.""" | ||
| resource = { | ||
| @@ -260,6 +341,9 @@ def _build_resource(self): | ||
| if self.location is not None: | ||
| resource['location'] = self.location | ||
| if len(self.access_grants) > 0: | ||
| resource['access'] = self._build_access_resource() | ||
| return resource | ||
| def create(self, client=None): | ||
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.