diff --git a/googleapiclient/discovery.py b/googleapiclient/discovery.py index 7d895bbed97..a77364b3712 100644 --- a/googleapiclient/discovery.py +++ b/googleapiclient/discovery.py @@ -51,6 +51,7 @@ # Third-party imports import httplib2 import uritemplate +import google.api_core.client_options # Local imports from googleapiclient import _auth @@ -176,7 +177,8 @@ def build(serviceName, requestBuilder=HttpRequest, credentials=None, cache_discovery=True, - cache=None): + cache=None, + client_options=None): """Construct a Resource for interacting with an API. Construct a Resource object for interacting with an API. The serviceName and @@ -202,6 +204,8 @@ def build(serviceName, cache_discovery: Boolean, whether or not to cache the discovery doc. cache: googleapiclient.discovery_cache.base.CacheBase, an optional cache object for the discovery documents. + client_options: google.api_core.client_options, Client options to set user + options on the client. API endpoint should be set through client_options. Returns: A Resource object with methods for interacting with the service. @@ -224,7 +228,7 @@ def build(serviceName, requested_url, discovery_http, cache_discovery, cache, developerKey) return build_from_document(content, base=discovery_url, http=http, developerKey=developerKey, model=model, requestBuilder=requestBuilder, - credentials=credentials) + credentials=credentials, client_options=client_options) except HttpError as e: if e.resp.status == http_client.NOT_FOUND: continue @@ -300,7 +304,8 @@ def build_from_document( developerKey=None, model=None, requestBuilder=HttpRequest, - credentials=None): + credentials=None, + client_options=None): """Create a Resource for interacting with an API. Same as `build()`, but constructs the Resource object from a discovery @@ -324,6 +329,8 @@ def build_from_document( credentials: oauth2client.Credentials or google.auth.credentials.Credentials, credentials to be used for authentication. + client_options: google.api_core.client_options, Client options used to set user options on the client. + API Endpoint (previously called base) should be set through client_options. Returns: A Resource object with methods for interacting with the service. @@ -342,8 +349,13 @@ def build_from_document( "build() without mocking once first to populate the " + "cache.") raise InvalidJsonError() + + # If an API Endpoint is provided on the client options object, use that URL + api_endpoint = service['rootUrl'] + if client_options.api_endpoint: + api_endpoint = service['rootUrl'] - base = urljoin(service['rootUrl'], service['servicePath']) + base = urljoin(api_endpoint, service['servicePath']) schema = Schemas(service) # If the http client is not specified, then we must construct an http client diff --git a/setup.py b/setup.py index 89c32a94e07..33570adcd2c 100644 --- a/setup.py +++ b/setup.py @@ -42,6 +42,7 @@ 'httplib2>=0.9.2,<1dev', 'google-auth>=1.4.1', 'google-auth-httplib2>=0.0.3', + 'google-api-core>=1.13.0,<2dev', 'six>=1.6.1,<2dev', 'uritemplate>=3.0.0,<4dev', ] diff --git a/tests/test_discovery.py b/tests/test_discovery.py index a6635a35235..33bd9c56725 100644 --- a/tests/test_discovery.py +++ b/tests/test_discovery.py @@ -471,6 +471,15 @@ def test_building_with_developer_key_skips_adc(self): # application default credentials were used. self.assertNotIsInstance(plus._http, google_auth_httplib2.AuthorizedHttp) + def test_api_endpoint_override(self): + discovery = open(datafile('plus.json')).read() + api_endpoint = "foo.googleapis.com" + options = google.api_core.client_options.ClientOptions(api_endpoint=api_endpoint) + plus = build_from_document( + discovery, client_options=options) + + self.assertEquals(plus._baseUrl, api_endpoint) + class DiscoveryFromHttp(unittest.TestCase): def setUp(self): @@ -527,6 +536,16 @@ def test_discovery_loading_from_v2_discovery_uri(self): zoo = build('zoo', 'v1', http=http, cache_discovery=False) self.assertTrue(hasattr(zoo, 'animals')) + def test_api_endpoint_override(self): + http = HttpMockSequence([ + ({'status': '404'}, 'Not found'), + ({'status': '200'}, open(datafile('zoo.json'), 'rb').read()), + ]) + api_endpoint = "foo.googleapis.com" + options = google.api_core.client_options.ClientOptions(api_endpoint=api_endpoint) + zoo = build('zoo', 'v1', http=http, cache_discovery=False, client_options=options) + self.assertEquals(zoo._baseUrl, api_endpoint) + class DiscoveryFromAppEngineCache(unittest.TestCase): def test_appengine_memcache(self): # Hack module import