Skip to content

Commit

Permalink
Add support for Google Default Credentials.
Browse files Browse the repository at this point in the history
  • Loading branch information
Orest Bolohan committed May 30, 2014
1 parent 56557e2 commit e92c900
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 3 deletions.
33 changes: 30 additions & 3 deletions googleapiclient/discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ def build(serviceName,
discoveryServiceUrl=DISCOVERY_URI,
developerKey=None,
model=None,
requestBuilder=HttpRequest):
requestBuilder=HttpRequest,
credentials=None):
"""Construct a Resource for interacting with an API.
Construct a Resource object for interacting with an API. The serviceName and
Expand All @@ -166,6 +167,8 @@ def build(serviceName,
model: googleapiclient.Model, converts to and from the wire format.
requestBuilder: googleapiclient.http.HttpRequest, encapsulator for an HTTP
request.
credentials: oauth2client.Credentials, credentials to be used for
authentication.
Returns:
A Resource object with methods for interacting with the service.
Expand Down Expand Up @@ -204,7 +207,8 @@ def build(serviceName,
raise InvalidJsonError()

return build_from_document(content, base=discoveryServiceUrl, http=http,
developerKey=developerKey, model=model, requestBuilder=requestBuilder)
developerKey=developerKey, model=model, requestBuilder=requestBuilder,
credentials=credentials)


@positional(1)
Expand All @@ -215,7 +219,8 @@ def build_from_document(
http=None,
developerKey=None,
model=None,
requestBuilder=HttpRequest):
requestBuilder=HttpRequest,
credentials=None):
"""Create a Resource for interacting with an API.
Same as `build()`, but constructs the Resource object from a discovery
Expand All @@ -236,6 +241,7 @@ def build_from_document(
model: Model class instance that serializes and de-serializes requests and
responses.
requestBuilder: Takes an http request and packages it up to be executed.
credentials: object, credentials to be used for authentication.
Returns:
A Resource object with methods for interacting with the service.
Expand All @@ -249,6 +255,27 @@ def build_from_document(
base = urlparse.urljoin(service['rootUrl'], service['servicePath'])
schema = Schemas(service)

if credentials:
# If credentials were passed in, we could have two cases:
# 1. the scopes were specified, in which case the given credentials
# are used for authorizing the http;
# 2. the scopes were not provided (meaning the Default Credentials are
# to be used). In this case, the Default Credentials are built and
# used instead of the original credentials. If there are no scopes
# found (meaning the given service requires no authentication), there is
# no authorization of the http.
if credentials.create_scoped_required():
scopes = service.get('auth', {}).get('oauth2', {}).get('scopes', {})
if scopes:
credentials = credentials.create_scoped(scopes.keys())
else:
# No need to authorize the http object
# if the service does not require authentication.
credentials = None

if credentials:
http = credentials.authorize(http)

if model is None:
features = service.get('features', [])
model = JsonModel('dataWrapper' in features)
Expand Down
14 changes: 14 additions & 0 deletions tests/test_discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,20 @@ def test_plus_resources(self):
self.assertTrue(getattr(plus, 'activities'))
self.assertTrue(getattr(plus, 'people'))

def test_credentials(self):
class CredentialsMock:
def create_scoped_required(self):
return False

def authorize(self, http):
http.orest = True

self.http = HttpMock(datafile('plus.json'), {'status': '200'})
build('plus', 'v1', http=self.http, credentials=None)
self.assertFalse(hasattr(self.http, 'orest'))
build('plus', 'v1', http=self.http, credentials=CredentialsMock())
self.assertTrue(hasattr(self.http, 'orest'))

def test_full_featured(self):
# Zoo should exercise all discovery facets
# and should also have no future.json file.
Expand Down

0 comments on commit e92c900

Please sign in to comment.