diff --git a/src/googleapiclient/__init__.py b/src/googleapiclient/__init__.py index 26442ace..b911ff05 100644 --- a/src/googleapiclient/__init__.py +++ b/src/googleapiclient/__init__.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "1.5.1" +__version__ = "1.5.2" # Set default logging handler to avoid "No handler found" warnings. import logging diff --git a/src/googleapiclient/channel.py b/src/googleapiclient/channel.py index 702186b6..7d0feb94 100644 --- a/src/googleapiclient/channel.py +++ b/src/googleapiclient/channel.py @@ -64,6 +64,13 @@ from googleapiclient import errors from oauth2client import util import six +# Oauth2client < 3 has the positional helper in 'util', >= 3 has it +# in '_helpers'. +try: + from oauth2client import util +except ImportError: + from oauth2client import _helpers as util + # The unix time epoch starts at midnight 1970. EPOCH = datetime.datetime.utcfromtimestamp(0) diff --git a/src/googleapiclient/discovery.py b/src/googleapiclient/discovery.py index ecb75fa4..598b222c 100644 --- a/src/googleapiclient/discovery.py +++ b/src/googleapiclient/discovery.py @@ -69,8 +69,15 @@ from googleapiclient.model import MediaModel from googleapiclient.model import RawModel from googleapiclient.schema import Schemas from oauth2client.client import GoogleCredentials -from oauth2client.util import _add_query_parameter -from oauth2client.util import positional + +# Oauth2client < 3 has the positional helper in 'util', >= 3 has it +# in '_helpers'. +try: + from oauth2client.util import _add_query_parameter + from oauth2client.util import positional +except ImportError: + from oauth2client._helpers import _add_query_parameter + from oauth2client._helpers import positional # The client library requires a version of httplib2 that supports RETRIES. @@ -315,6 +322,15 @@ def build_from_document( if isinstance(service, six.string_types): service = json.loads(service) + + if 'rootUrl' not in service and (isinstance(http, (HttpMock, + HttpMockSequence))): + logger.error("You are using HttpMock or HttpMockSequence without" + + "having the service discovery doc in cache. Try calling " + + "build() without mocking once first to populate the " + + "cache.") + raise InvalidJsonError() + base = urljoin(service['rootUrl'], service['servicePath']) schema = Schemas(service) diff --git a/src/googleapiclient/errors.py b/src/googleapiclient/errors.py index 3d44de70..1b79d2fe 100644 --- a/src/googleapiclient/errors.py +++ b/src/googleapiclient/errors.py @@ -23,7 +23,12 @@ __author__ = 'jcgregorio@google.com (Joe Gregorio)' import json -from oauth2client import util +# Oauth2client < 3 has the positional helper in 'util', >= 3 has it +# in '_helpers'. +try: + from oauth2client import util +except ImportError: + from oauth2client import _helpers as util class Error(Exception): diff --git a/src/googleapiclient/http.py b/src/googleapiclient/http.py index 5181badb..14580f0c 100644 --- a/src/googleapiclient/http.py +++ b/src/googleapiclient/http.py @@ -55,6 +55,13 @@ from email.mime.multipart import MIMEMultipart from email.mime.nonmultipart import MIMENonMultipart from email.parser import FeedParser +# Oauth2client < 3 has the positional helper in 'util', >= 3 has it +# in '_helpers'. +try: + from oauth2client import util +except ImportError: + from oauth2client import _helpers as util + from googleapiclient import mimeparse from googleapiclient.errors import BatchError from googleapiclient.errors import HttpError @@ -63,7 +70,6 @@ from googleapiclient.errors import ResumableUploadError from googleapiclient.errors import UnexpectedBodyError from googleapiclient.errors import UnexpectedMethodError from googleapiclient.model import JsonModel -from oauth2client import util LOGGER = logging.getLogger(__name__) @@ -639,7 +645,7 @@ class MediaIoBaseDownload(object): """Get the next chunk of the download. Args: - num_retries: Integer, number of times to retry 500's with randomized + num_retries: Integer, number of times to retry with randomized exponential backoff. If all retries fail, the raised HttpError represents the last request. If zero (default), we attempt the request only once. @@ -782,7 +788,7 @@ class HttpRequest(object): Args: http: httplib2.Http, an http object to be used in place of the one the HttpRequest request object was constructed with. - num_retries: Integer, number of times to retry 500's with randomized + num_retries: Integer, number of times to retry with randomized exponential backoff. If all retries fail, the raised HttpError represents the last request. If zero (default), we attempt the request only once. @@ -870,7 +876,7 @@ class HttpRequest(object): Args: http: httplib2.Http, an http object to be used in place of the one the HttpRequest request object was constructed with. - num_retries: Integer, number of times to retry 500's with randomized + num_retries: Integer, number of times to retry with randomized exponential backoff. If all retries fail, the raised HttpError represents the last request. If zero (default), we attempt the request only once. @@ -965,7 +971,7 @@ class HttpRequest(object): except: self._in_error_state = True raise - if resp.status < 500: + if not _should_retry_response(resp.status, content): break return self._process_response(resp, content) @@ -1394,6 +1400,14 @@ class BatchHttpRequest(object): if http is None: raise ValueError("Missing a valid http object.") + # Special case for OAuth2Credentials-style objects which have not yet been + # refreshed with an initial access_token. + if getattr(http.request, 'credentials', None) is not None: + creds = http.request.credentials + if not getattr(creds, 'access_token', None): + LOGGER.info('Attempting refresh to obtain initial access_token') + creds.refresh(http) + self._execute(http, self._order, self._requests) # Loop over all the requests and check for 401s. For each 401 request the diff --git a/src/googleapiclient/schema.py b/src/googleapiclient/schema.py index ecb3f8bf..9feaf28a 100644 --- a/src/googleapiclient/schema.py +++ b/src/googleapiclient/schema.py @@ -65,7 +65,12 @@ __author__ = 'jcgregorio@google.com (Joe Gregorio)' import copy -from oauth2client import util +# Oauth2client < 3 has the positional helper in 'util', >= 3 has it +# in '_helpers'. +try: + from oauth2client import util +except ImportError: + from oauth2client import _helpers as util class Schemas(object):