Skip to content

Commit f89a3cf

Browse files
author
Jon Wayne Parrott
authored
Add with_scopes_if_required helper (#65)
1 parent ac3f975 commit f89a3cf

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

google/auth/credentials.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,30 @@ def has_scopes(self, scopes):
186186
return set(scopes).issubset(set(self._scopes or []))
187187

188188

189+
def with_scopes_if_required(credentials, scopes):
190+
"""Creates a copy of the credentials with scopes if scoping is required.
191+
192+
This helper function is useful when you do not know (or care to know) the
193+
specific type of credentials you are using (such as when you use
194+
:func:`google.auth.default`). This function will call
195+
:meth:`Scoped.with_scopes` if the credentials are scoped credentials and if
196+
the credentials require scoping. Otherwise, it will return the credentials
197+
as-is.
198+
199+
Args:
200+
credentials (Credentials): The credentials to scope if necessary.
201+
scopes (Sequence[str]): The list of scopes to use.
202+
203+
Returns:
204+
Credentials: Either a new set of scoped credentials, or the passed in
205+
credentials instance if no scoping was required.
206+
"""
207+
if isinstance(credentials, Scoped) and credentials.requires_scopes:
208+
return credentials.with_scopes(scopes)
209+
else:
210+
return credentials
211+
212+
189213
@six.add_metaclass(abc.ABCMeta)
190214
class Signing(object):
191215
"""Interface for credentials that can cryptographically sign messages."""

tests/test_credentials.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,34 @@ def test_scoped_credentials_scopes():
9292
def test_scoped_credentials_requires_scopes():
9393
credentials = ScopedCredentialsImpl()
9494
assert not credentials.requires_scopes
95+
96+
97+
class RequiresScopedCredentialsImpl(credentials.Scoped, CredentialsImpl):
98+
def __init__(self, scopes=None):
99+
super(RequiresScopedCredentialsImpl, self).__init__()
100+
self._scopes = scopes
101+
102+
@property
103+
def requires_scopes(self):
104+
return not self.scopes
105+
106+
def with_scopes(self, scopes):
107+
return RequiresScopedCredentialsImpl(scopes=scopes)
108+
109+
110+
def test_create_scoped_if_required_scoped():
111+
unscoped_credentials = RequiresScopedCredentialsImpl()
112+
scoped_credentials = credentials.with_scopes_if_required(
113+
unscoped_credentials, ['one', 'two'])
114+
115+
assert scoped_credentials is not unscoped_credentials
116+
assert not scoped_credentials.requires_scopes
117+
assert scoped_credentials.has_scopes(['one', 'two'])
118+
119+
120+
def test_create_scoped_if_required_not_scopes():
121+
unscoped_credentials = CredentialsImpl()
122+
scoped_credentials = credentials.with_scopes_if_required(
123+
unscoped_credentials, ['one', 'two'])
124+
125+
assert scoped_credentials is unscoped_credentials

0 commit comments

Comments
 (0)