Skip to content

Commit

Permalink
Only request docs if static_discovery=False
Browse files Browse the repository at this point in the history
  • Loading branch information
parthea committed Dec 18, 2020
1 parent a8b116a commit f816508
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 41 deletions.
11 changes: 1 addition & 10 deletions docs/start.md
Expand Up @@ -65,16 +65,7 @@ with build('drive', 'v3') as service:
# ...
```

**Note**: Under the hood, the `build()` function retrieves a discovery artifact in order to construct the service object. If the `cache_discovery` argument of `build()` is set to `True`, the library will attempt to retrieve the discovery artifact from the legacy cache which is only supported with `oauth2client<4.0`. If the artifact is not available in the legacy cache and the `static_discovery` argument of `build()` is set to `True`, the library will attempt to retieve the discovery artifact from the static copy of the discovery artifacts that are shipped with the library. As a last resort if the discovery artifact is not on disk, the discovery artifact will be retrieved from the internet. The maintainers recommend keeping `static_discovery=True`, which is the default, in order to avoid reliability issues related to transient network errors. The library currently does not detect breaking changes of discovery artifacts, and as a result, user code is not guaranteed to continue to succeed or fail with different versions of `google-api-python-client`. Users can set `static_discovery=False` as workaround if there is an incompatible discovery artifact shipped with the library. In addition, users may roll back the version of `google-api-python-client` if there is a breaking change in a discovery artifact. The maintainers of `google-api-python-client` encourage users to report issues with discovery artifacts so that the discovery artifacts can be corrected.

In the below example, the discovery artifact for `'drive'` version `'v3'` will only be retrieved from the internet if it is not available in the legacy cache and it is not one of the static discovery artifacts shipped with the library.

```python
from googleapiclient.discovery import build

with build('drive', 'v3', cache_discovery=True, static_discovery=True):
# ...
```
**Note**: Under the hood, the `build()` function retrieves a discovery artifact in order to construct the service object. If the `cache_discovery` argument of `build()` is set to `True`, the library will attempt to retrieve the discovery artifact from the legacy cache which is only supported with `oauth2client<4.0`. If the artifact is not available in the legacy cache and the `static_discovery` argument of `build()` is set to `True`, the library will attempt to retieve the discovery artifact from the static copy of the discovery artifacts that are shipped with the library. The maintainers recommend keeping `static_discovery=True`, which is the default, in order to avoid reliability issues related to transient network errors. The library currently does not detect breaking changes of discovery artifacts, and as a result, user code is not guaranteed to continue to succeed or fail with different versions of `google-api-python-client`. Users can set `static_discovery=False` as workaround if there is an incompatible discovery artifact shipped with the library. In addition, users may roll back the version of `google-api-python-client` if there is a breaking change in a discovery artifact. The maintainers of `google-api-python-client` encourage users to report issues with discovery artifacts so that the discovery artifacts can be corrected.

### Collections

Expand Down
49 changes: 22 additions & 27 deletions googleapiclient/discovery.py
Expand Up @@ -248,8 +248,7 @@ def build(
num_retries: Integer, number of times to retry discovery with
randomized exponential backoff in case of intermittent/connection issues.
static_discovery: Boolean, whether or not to use the static discovery docs
included in the package when the discovery doc is not available in the
cache.
included in the library.
Returns:
A Resource object with methods for interacting with the service.
Expand Down Expand Up @@ -363,16 +362,13 @@ def _retrieve_discovery_doc(
num_retries: Integer, number of times to retry discovery with
randomized exponential backoff in case of intermittent/connection issues.
static_discovery: Boolean, whether or not to use the static discovery docs
included in the package when the discovery doc is not available in the
cache.
included in the library.
Returns:
A unicode string representation of the discovery document.
"""
from . import discovery_cache

content = None

if cache_discovery:
if cache is None:
cache = discovery_cache.autodetect()
Expand All @@ -381,31 +377,30 @@ def _retrieve_discovery_doc(
if content:
return content

# At this point, the discovery document was not found in the cache so
# we can attempt to retreive the static discovery document from the library.
# When `static_discovery=True`, use static discovery artifacts included
# with the library
if static_discovery:
content = discovery_cache.get_static_doc(serviceName, version)
if content:
return content

# If the content is None, retrieve the discovery doc from the internet
# because it is not in the cache or the static doc directory.
if content is None:
actual_url = url
# REMOTE_ADDR is defined by the CGI spec [RFC3875] as the environment
# variable that contains the network address of the client sending the
# request. If it exists then add that to the request for the discovery
# document to avoid exceeding the quota on discovery requests.
if "REMOTE_ADDR" in os.environ:
actual_url = _add_query_parameter(url, "userIp", os.environ["REMOTE_ADDR"])
if developerKey:
actual_url = _add_query_parameter(url, "key", developerKey)
logger.debug("URL being requested: GET %s", actual_url)

# Execute this request with retries build into HttpRequest
# Note that it will already raise an error if we don't get a 2xx response
req = HttpRequest(http, HttpRequest.null_postproc, actual_url)
resp, content = req.execute(num_retries=num_retries)
else:
raise UnknownApiNameOrVersion("name: %s version: %s" % (serviceName, version))

actual_url = url
# REMOTE_ADDR is defined by the CGI spec [RFC3875] as the environment
# variable that contains the network address of the client sending the
# request. If it exists then add that to the request for the discovery
# document to avoid exceeding the quota on discovery requests.
if "REMOTE_ADDR" in os.environ:
actual_url = _add_query_parameter(url, "userIp", os.environ["REMOTE_ADDR"])
if developerKey:
actual_url = _add_query_parameter(url, "key", developerKey)
logger.debug("URL being requested: GET %s", actual_url)

# Execute this request with retries build into HttpRequest
# Note that it will already raise an error if we don't get a 2xx response
req = HttpRequest(http, HttpRequest.null_postproc, actual_url)
resp, content = req.execute(num_retries=num_retries)

try:
content = content.decode("utf-8")
Expand Down
7 changes: 3 additions & 4 deletions tests/test_discovery.py
Expand Up @@ -1162,10 +1162,9 @@ def test_retrieve_from_internet_when_static_discovery_false(self):
build("drive", "v3", http=http, cache_discovery=False,
static_discovery=False)

def test_retrieve_from_internet_when_static_doc_does_not_exist(self):
http = HttpMockSequence([({"status": "400"}, "")])
with self.assertRaises(HttpError):
build("doesnotexist", "v3", http=http, cache_discovery=False,
def test_unknown_api_when_static_discovery_true(self):
with self.assertRaises(UnknownApiNameOrVersion):
build("doesnotexist", "v3", cache_discovery=False,
static_discovery=True)


Expand Down

0 comments on commit f816508

Please sign in to comment.