Skip to content

Commit

Permalink
refactor: split 'with_quota_project' into separate base class (#561)
Browse files Browse the repository at this point in the history
Co-authored-by: Tres Seaver <tseaver@palladion.com>
  • Loading branch information
busunkim96 and tseaver committed Sep 2, 2020
1 parent 6269643 commit 41599ae
Show file tree
Hide file tree
Showing 9 changed files with 34 additions and 33 deletions.
6 changes: 4 additions & 2 deletions google/auth/app_engine.py
Expand Up @@ -77,7 +77,9 @@ def get_project_id():
return app_identity.get_application_id()


class Credentials(credentials.Scoped, credentials.Signing, credentials.Credentials):
class Credentials(
credentials.Scoped, credentials.Signing, credentials.CredentialsWithQuotaProject
):
"""App Engine standard environment credentials.
These credentials use the App Engine App Identity API to obtain access
Expand Down Expand Up @@ -145,7 +147,7 @@ def with_scopes(self, scopes):
quota_project_id=self.quota_project_id,
)

@_helpers.copy_docstring(credentials.Credentials)
@_helpers.copy_docstring(credentials.CredentialsWithQuotaProject)
def with_quota_project(self, quota_project_id):
return self.__class__(
scopes=self._scopes,
Expand Down
8 changes: 4 additions & 4 deletions google/auth/compute_engine/credentials.py
Expand Up @@ -32,7 +32,7 @@
from google.oauth2 import _client


class Credentials(credentials.ReadOnlyScoped, credentials.Credentials):
class Credentials(credentials.ReadOnlyScoped, credentials.CredentialsWithQuotaProject):
"""Compute Engine Credentials.
These credentials use the Google Compute Engine metadata server to obtain
Expand Down Expand Up @@ -118,7 +118,7 @@ def requires_scopes(self):
"""False: Compute Engine credentials can not be scoped."""
return False

@_helpers.copy_docstring(credentials.Credentials)
@_helpers.copy_docstring(credentials.CredentialsWithQuotaProject)
def with_quota_project(self, quota_project_id):
return self.__class__(
service_account_email=self._service_account_email,
Expand All @@ -130,7 +130,7 @@ def with_quota_project(self, quota_project_id):
_DEFAULT_TOKEN_URI = "https://www.googleapis.com/oauth2/v4/token"


class IDTokenCredentials(credentials.Credentials, credentials.Signing):
class IDTokenCredentials(credentials.CredentialsWithQuotaProject, credentials.Signing):
"""Open ID Connect ID Token-based service account credentials.
These credentials relies on the default service account of a GCE instance.
Expand Down Expand Up @@ -254,7 +254,7 @@ def with_target_audience(self, target_audience):
quota_project_id=self._quota_project_id,
)

@_helpers.copy_docstring(credentials.Credentials)
@_helpers.copy_docstring(credentials.CredentialsWithQuotaProject)
def with_quota_project(self, quota_project_id):

# since the signer is already instantiated,
Expand Down
9 changes: 5 additions & 4 deletions google/auth/credentials.py
Expand Up @@ -133,6 +133,10 @@ def before_request(self, request, method, url, headers):
self.refresh(request)
self.apply(headers)


class CredentialsWithQuotaProject(Credentials):
"""Abstract base for credentials supporting ``with_quota_project`` factory"""

def with_quota_project(self, quota_project_id):
"""Returns a copy of these credentials with a modified quota project
Expand All @@ -143,7 +147,7 @@ def with_quota_project(self, quota_project_id):
Returns:
google.oauth2.credentials.Credentials: A new credentials instance.
"""
raise NotImplementedError("This class does not support quota project.")
raise NotImplementedError("This credential does not support quota project.")


class AnonymousCredentials(Credentials):
Expand Down Expand Up @@ -182,9 +186,6 @@ def apply(self, headers, token=None):
def before_request(self, request, method, url, headers):
"""Anonymous credentials do nothing to the request."""

def with_quota_project(self, quota_project_id):
raise ValueError("Anonymous credentials don't support quota project.")


@six.add_metaclass(abc.ABCMeta)
class ReadOnlyScoped(object):
Expand Down
8 changes: 4 additions & 4 deletions google/auth/impersonated_credentials.py
Expand Up @@ -115,7 +115,7 @@ def _make_iam_token_request(request, principal, headers, body):
six.raise_from(new_exc, caught_exc)


class Credentials(credentials.Credentials, credentials.Signing):
class Credentials(credentials.CredentialsWithQuotaProject, credentials.Signing):
"""This module defines impersonated credentials which are essentially
impersonated identities.
Expand Down Expand Up @@ -293,7 +293,7 @@ def service_account_email(self):
def signer(self):
return self

@_helpers.copy_docstring(credentials.Credentials)
@_helpers.copy_docstring(credentials.CredentialsWithQuotaProject)
def with_quota_project(self, quota_project_id):
return self.__class__(
self._source_credentials,
Expand All @@ -305,7 +305,7 @@ def with_quota_project(self, quota_project_id):
)


class IDTokenCredentials(credentials.Credentials):
class IDTokenCredentials(credentials.CredentialsWithQuotaProject):
"""Open ID Connect ID Token-based service account credentials.
"""
Expand Down Expand Up @@ -359,7 +359,7 @@ def with_include_email(self, include_email):
quota_project_id=self._quota_project_id,
)

@_helpers.copy_docstring(credentials.Credentials)
@_helpers.copy_docstring(credentials.CredentialsWithQuotaProject)
def with_quota_project(self, quota_project_id):
return self.__class__(
target_credentials=self._target_credentials,
Expand Down
10 changes: 6 additions & 4 deletions google/auth/jwt.py
Expand Up @@ -288,7 +288,9 @@ def decode(token, certs=None, verify=True, audience=None):
return payload


class Credentials(google.auth.credentials.Signing, google.auth.credentials.Credentials):
class Credentials(
google.auth.credentials.Signing, google.auth.credentials.CredentialsWithQuotaProject
):
"""Credentials that use a JWT as the bearer token.
These credentials require an "audience" claim. This claim identifies the
Expand Down Expand Up @@ -493,7 +495,7 @@ def with_claims(
quota_project_id=self._quota_project_id,
)

@_helpers.copy_docstring(google.auth.credentials.Credentials)
@_helpers.copy_docstring(google.auth.credentials.CredentialsWithQuotaProject)
def with_quota_project(self, quota_project_id):
return self.__class__(
self._signer,
Expand Down Expand Up @@ -554,7 +556,7 @@ def signer(self):


class OnDemandCredentials(
google.auth.credentials.Signing, google.auth.credentials.Credentials
google.auth.credentials.Signing, google.auth.credentials.CredentialsWithQuotaProject
):
"""On-demand JWT credentials.
Expand Down Expand Up @@ -721,7 +723,7 @@ def with_claims(self, issuer=None, subject=None, additional_claims=None):
quota_project_id=self._quota_project_id,
)

@_helpers.copy_docstring(google.auth.credentials.Credentials)
@_helpers.copy_docstring(google.auth.credentials.CredentialsWithQuotaProject)
def with_quota_project(self, quota_project_id):

return self.__class__(
Expand Down
8 changes: 4 additions & 4 deletions google/oauth2/credentials.py
Expand Up @@ -47,7 +47,7 @@
_GOOGLE_OAUTH2_TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token"


class Credentials(credentials.ReadOnlyScoped, credentials.Credentials):
class Credentials(credentials.ReadOnlyScoped, credentials.CredentialsWithQuotaProject):
"""Credentials using OAuth 2.0 access and refresh tokens.
The credentials are considered immutable. If you want to modify the
Expand Down Expand Up @@ -161,7 +161,7 @@ def requires_scopes(self):
the initial token is requested and can not be changed."""
return False

@_helpers.copy_docstring(credentials.Credentials)
@_helpers.copy_docstring(credentials.CredentialsWithQuotaProject)
def with_quota_project(self, quota_project_id):

return self.__class__(
Expand Down Expand Up @@ -305,7 +305,7 @@ def to_json(self, strip=None):
return json.dumps(prep)


class UserAccessTokenCredentials(credentials.Credentials):
class UserAccessTokenCredentials(credentials.CredentialsWithQuotaProject):
"""Access token credentials for user account.
Obtain the access token for a given user account or the current active
Expand Down Expand Up @@ -336,7 +336,7 @@ def with_account(self, account):
"""
return self.__class__(account=account, quota_project_id=self._quota_project_id)

@_helpers.copy_docstring(credentials.Credentials)
@_helpers.copy_docstring(credentials.CredentialsWithQuotaProject)
def with_quota_project(self, quota_project_id):
return self.__class__(account=self._account, quota_project_id=quota_project_id)

Expand Down
10 changes: 6 additions & 4 deletions google/oauth2/service_account.py
Expand Up @@ -82,7 +82,9 @@
_DEFAULT_TOKEN_LIFETIME_SECS = 3600 # 1 hour in seconds


class Credentials(credentials.Signing, credentials.Scoped, credentials.Credentials):
class Credentials(
credentials.Signing, credentials.Scoped, credentials.CredentialsWithQuotaProject
):
"""Service account credentials
Usually, you'll create these credentials with one of the helper
Expand Down Expand Up @@ -306,7 +308,7 @@ def with_claims(self, additional_claims):
additional_claims=new_additional_claims,
)

@_helpers.copy_docstring(credentials.Credentials)
@_helpers.copy_docstring(credentials.CredentialsWithQuotaProject)
def with_quota_project(self, quota_project_id):

return self.__class__(
Expand Down Expand Up @@ -375,7 +377,7 @@ def signer_email(self):
return self._service_account_email


class IDTokenCredentials(credentials.Signing, credentials.Credentials):
class IDTokenCredentials(credentials.Signing, credentials.CredentialsWithQuotaProject):
"""Open ID Connect ID Token-based service account credentials.
These credentials are largely similar to :class:`.Credentials`, but instead
Expand Down Expand Up @@ -533,7 +535,7 @@ def with_target_audience(self, target_audience):
quota_project_id=self.quota_project_id,
)

@_helpers.copy_docstring(credentials.Credentials)
@_helpers.copy_docstring(credentials.CredentialsWithQuotaProject)
def with_quota_project(self, quota_project_id):
return self.__class__(
self._signer,
Expand Down
2 changes: 1 addition & 1 deletion tests/test__default.py
Expand Up @@ -49,7 +49,7 @@
with open(SERVICE_ACCOUNT_FILE) as fh:
SERVICE_ACCOUNT_FILE_DATA = json.load(fh)

MOCK_CREDENTIALS = mock.Mock(spec=credentials.Credentials)
MOCK_CREDENTIALS = mock.Mock(spec=credentials.CredentialsWithQuotaProject)
MOCK_CREDENTIALS.with_quota_project.return_value = MOCK_CREDENTIALS

LOAD_FILE_PATCH = mock.patch(
Expand Down
6 changes: 0 additions & 6 deletions tests/test_credentials.py
Expand Up @@ -115,12 +115,6 @@ def test_anonymous_credentials_before_request():
assert headers == {}


def test_anonymous_credentials_with_quota_project():
with pytest.raises(ValueError):
anon = credentials.AnonymousCredentials()
anon.with_quota_project("project-foo")


class ReadOnlyScopedCredentialsImpl(credentials.ReadOnlyScoped, CredentialsImpl):
@property
def requires_scopes(self):
Expand Down

0 comments on commit 41599ae

Please sign in to comment.