Skip to content

Commit 44783ca

Browse files
committed
Merge pull request #10 from orestica/compacted
Add support for Google Default Credentials.
2 parents 56557e2 + e92c900 commit 44783ca

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

googleapiclient/discovery.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@ def build(serviceName,
146146
discoveryServiceUrl=DISCOVERY_URI,
147147
developerKey=None,
148148
model=None,
149-
requestBuilder=HttpRequest):
149+
requestBuilder=HttpRequest,
150+
credentials=None):
150151
"""Construct a Resource for interacting with an API.
151152
152153
Construct a Resource object for interacting with an API. The serviceName and
@@ -166,6 +167,8 @@ def build(serviceName,
166167
model: googleapiclient.Model, converts to and from the wire format.
167168
requestBuilder: googleapiclient.http.HttpRequest, encapsulator for an HTTP
168169
request.
170+
credentials: oauth2client.Credentials, credentials to be used for
171+
authentication.
169172
170173
Returns:
171174
A Resource object with methods for interacting with the service.
@@ -204,7 +207,8 @@ def build(serviceName,
204207
raise InvalidJsonError()
205208

206209
return build_from_document(content, base=discoveryServiceUrl, http=http,
207-
developerKey=developerKey, model=model, requestBuilder=requestBuilder)
210+
developerKey=developerKey, model=model, requestBuilder=requestBuilder,
211+
credentials=credentials)
208212

209213

210214
@positional(1)
@@ -215,7 +219,8 @@ def build_from_document(
215219
http=None,
216220
developerKey=None,
217221
model=None,
218-
requestBuilder=HttpRequest):
222+
requestBuilder=HttpRequest,
223+
credentials=None):
219224
"""Create a Resource for interacting with an API.
220225
221226
Same as `build()`, but constructs the Resource object from a discovery
@@ -236,6 +241,7 @@ def build_from_document(
236241
model: Model class instance that serializes and de-serializes requests and
237242
responses.
238243
requestBuilder: Takes an http request and packages it up to be executed.
244+
credentials: object, credentials to be used for authentication.
239245
240246
Returns:
241247
A Resource object with methods for interacting with the service.
@@ -249,6 +255,27 @@ def build_from_document(
249255
base = urlparse.urljoin(service['rootUrl'], service['servicePath'])
250256
schema = Schemas(service)
251257

258+
if credentials:
259+
# If credentials were passed in, we could have two cases:
260+
# 1. the scopes were specified, in which case the given credentials
261+
# are used for authorizing the http;
262+
# 2. the scopes were not provided (meaning the Default Credentials are
263+
# to be used). In this case, the Default Credentials are built and
264+
# used instead of the original credentials. If there are no scopes
265+
# found (meaning the given service requires no authentication), there is
266+
# no authorization of the http.
267+
if credentials.create_scoped_required():
268+
scopes = service.get('auth', {}).get('oauth2', {}).get('scopes', {})
269+
if scopes:
270+
credentials = credentials.create_scoped(scopes.keys())
271+
else:
272+
# No need to authorize the http object
273+
# if the service does not require authentication.
274+
credentials = None
275+
276+
if credentials:
277+
http = credentials.authorize(http)
278+
252279
if model is None:
253280
features = service.get('features', [])
254281
model = JsonModel('dataWrapper' in features)

tests/test_discovery.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,20 @@ def test_plus_resources(self):
516516
self.assertTrue(getattr(plus, 'activities'))
517517
self.assertTrue(getattr(plus, 'people'))
518518

519+
def test_credentials(self):
520+
class CredentialsMock:
521+
def create_scoped_required(self):
522+
return False
523+
524+
def authorize(self, http):
525+
http.orest = True
526+
527+
self.http = HttpMock(datafile('plus.json'), {'status': '200'})
528+
build('plus', 'v1', http=self.http, credentials=None)
529+
self.assertFalse(hasattr(self.http, 'orest'))
530+
build('plus', 'v1', http=self.http, credentials=CredentialsMock())
531+
self.assertTrue(hasattr(self.http, 'orest'))
532+
519533
def test_full_featured(self):
520534
# Zoo should exercise all discovery facets
521535
# and should also have no future.json file.

0 commit comments

Comments
 (0)