Skip to content

Commit

Permalink
Merge pull request #64 from pferate/python3-module_updates
Browse files Browse the repository at this point in the history
Python 3 support.
  • Loading branch information
nathanielmanistaatgoogle committed Mar 10, 2015
2 parents 4e7e6d4 + 846befc commit cf939a3
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 220 deletions.
4 changes: 3 additions & 1 deletion apiclient/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Retain apiclient as an alias for googleapiclient."""

from six import iteritems

import googleapiclient

try:
Expand Down Expand Up @@ -36,5 +38,5 @@
}

import sys
for module_name, module in _SUBMODULES.iteritems():
for module_name, module in iteritems(_SUBMODULES):
sys.modules['apiclient.%s' % module_name] = module
32 changes: 16 additions & 16 deletions googleapiclient/discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@
'key2param',
]

from six import StringIO
from six.moves.urllib.parse import urlencode, urlparse, urljoin, \
urlunparse, parse_qsl

# Standard library imports
import StringIO
import copy
from email.generator import Generator
from email.mime.multipart import MIMEMultipart
Expand All @@ -41,20 +43,13 @@
import mimetypes
import os
import re
import urllib
import urlparse

try:
from urlparse import parse_qsl
except ImportError:
from cgi import parse_qsl

# Third-party imports
import httplib2
from . import mimeparse
import uritemplate

# Local imports
from googleapiclient import mimeparse
from googleapiclient.errors import HttpError
from googleapiclient.errors import InvalidJsonError
from googleapiclient.errors import MediaUploadSizeError
Expand Down Expand Up @@ -206,6 +201,11 @@ def build(serviceName,
if resp.status >= 400:
raise HttpError(resp, content, uri=requested_url)

try:
content = content.decode('utf-8')
except AttributeError:
pass

try:
service = json.loads(content)
except ValueError as e:
Expand Down Expand Up @@ -258,7 +258,7 @@ def build_from_document(

if isinstance(service, six.string_types):
service = json.loads(service)
base = urlparse.urljoin(service['rootUrl'], service['servicePath'])
base = urljoin(service['rootUrl'], service['servicePath'])
schema = Schemas(service)

if credentials:
Expand Down Expand Up @@ -505,7 +505,7 @@ def _urljoin(base, url):
# exception here is the case of media uploads, where url will be an
# absolute url.
if url.startswith('http://') or url.startswith('https://'):
return urlparse.urljoin(base, url)
return urljoin(base, url)
new_base = base if base.endswith('/') else base + '/'
new_url = url[1:] if url.startswith('/') else url
return new_base + new_url
Expand Down Expand Up @@ -712,7 +712,7 @@ def method(self, **kwargs):
raise TypeError('media_filename must be str or MediaUpload.')

# Check the maxSize
if maxSize > 0 and media_upload.size() > maxSize:
if media_upload.size() is not None and media_upload.size() > maxSize > 0:
raise MediaUploadSizeError("Media larger than: %s" % maxSize)

# Use the media path uri for media uploads
Expand Down Expand Up @@ -752,7 +752,7 @@ def method(self, **kwargs):
msgRoot.attach(msg)
# encode the body: note that we can't use `as_string`, because
# it plays games with `From ` lines.
fp = StringIO.StringIO()
fp = StringIO()
g = Generator(fp, mangle_from_=False)
g.flatten(msgRoot, unixfrom=False)
body = fp.getvalue()
Expand Down Expand Up @@ -859,14 +859,14 @@ def methodNext(self, previous_request, previous_response):
request = copy.copy(previous_request)

pageToken = previous_response['nextPageToken']
parsed = list(urlparse.urlparse(request.uri))
parsed = list(urlparse(request.uri))
q = parse_qsl(parsed[4])

# Find and remove old 'pageToken' value from URI
newq = [(key, value) for (key, value) in q if key != 'pageToken']
newq.append(('pageToken', pageToken))
parsed[4] = urllib.urlencode(newq)
uri = urlparse.urlunparse(parsed)
parsed[4] = urlencode(newq)
uri = urlunparse(parsed)

request.uri = uri

Expand Down
47 changes: 24 additions & 23 deletions googleapiclient/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,34 +24,35 @@

__author__ = '[email protected] (Joe Gregorio)'

import StringIO
from six import BytesIO, StringIO
from six.moves.urllib.parse import urlparse, urlunparse, quote, unquote

import base64
import copy
import gzip
import httplib2
import json
import logging
from . import mimeparse
import mimetypes
import os
import random
import sys
import time
import urllib
import urlparse
import uuid

from email.generator import Generator
from email.mime.multipart import MIMEMultipart
from email.mime.nonmultipart import MIMENonMultipart
from email.parser import FeedParser
from .errors import BatchError
from .errors import HttpError
from .errors import InvalidChunkSizeError
from .errors import ResumableUploadError
from .errors import UnexpectedBodyError
from .errors import UnexpectedMethodError
from .model import JsonModel

from googleapiclient import mimeparse
from googleapiclient.errors import BatchError
from googleapiclient.errors import HttpError
from googleapiclient.errors import InvalidChunkSizeError
from googleapiclient.errors import ResumableUploadError
from googleapiclient.errors import UnexpectedBodyError
from googleapiclient.errors import UnexpectedMethodError
from googleapiclient.model import JsonModel
from oauth2client import util


Expand Down Expand Up @@ -262,7 +263,7 @@ class MediaIoBaseUpload(MediaUpload):
Note that the Python file object is compatible with io.Base and can be used
with this class also.
fh = io.BytesIO('...Some data to upload...')
fh = BytesIO('...Some data to upload...')
media = MediaIoBaseUpload(fh, mimetype='image/png',
chunksize=1024*1024, resumable=True)
farm.animals().insert(
Expand Down Expand Up @@ -468,7 +469,7 @@ def __init__(self, body, mimetype='application/octet-stream',
resumable: bool, True if this is a resumable upload. False means upload
in a single request.
"""
fd = StringIO.StringIO(body)
fd = BytesIO(body)
super(MediaInMemoryUpload, self).__init__(fd, mimetype, chunksize=chunksize,
resumable=resumable)

Expand Down Expand Up @@ -702,8 +703,8 @@ def execute(self, http=None, num_retries=0):
self.method = 'POST'
self.headers['x-http-method-override'] = 'GET'
self.headers['content-type'] = 'application/x-www-form-urlencoded'
parsed = urlparse.urlparse(self.uri)
self.uri = urlparse.urlunparse(
parsed = urlparse(self.uri)
self.uri = urlunparse(
(parsed.scheme, parsed.netloc, parsed.path, parsed.params, None,
None)
)
Expand Down Expand Up @@ -1051,7 +1052,7 @@ def _id_to_header(self, id_):
if self._base_id is None:
self._base_id = uuid.uuid4()

return '<%s+%s>' % (self._base_id, urllib.quote(id_))
return '<%s+%s>' % (self._base_id, quote(id_))

def _header_to_id(self, header):
"""Convert a Content-ID header value to an id.
Expand All @@ -1074,7 +1075,7 @@ def _header_to_id(self, header):
raise BatchError("Invalid value for Content-ID: %s" % header)
base, id_ = header[1:-1].rsplit('+', 1)

return urllib.unquote(id_)
return unquote(id_)

def _serialize_request(self, request):
"""Convert an HttpRequest object into a string.
Expand All @@ -1086,9 +1087,9 @@ def _serialize_request(self, request):
The request as a string in application/http format.
"""
# Construct status line
parsed = urlparse.urlparse(request.uri)
request_line = urlparse.urlunparse(
(None, None, parsed.path, parsed.params, parsed.query, None)
parsed = urlparse(request.uri)
request_line = urlunparse(
('', '', parsed.path, parsed.params, parsed.query, '')
)
status_line = request.method + ' ' + request_line + ' HTTP/1.1\n'
major, minor = request.headers.get('content-type', 'application/json').split('/')
Expand All @@ -1113,7 +1114,7 @@ def _serialize_request(self, request):
msg['content-length'] = str(len(request.body))

# Serialize the mime message.
fp = StringIO.StringIO()
fp = StringIO()
# maxheaderlen=0 means don't line wrap headers.
g = Generator(fp, maxheaderlen=0)
g.flatten(msg, unixfrom=False)
Expand All @@ -1123,7 +1124,7 @@ def _serialize_request(self, request):
if request.body is None:
body = body[:-2]

return status_line.encode('utf-8') + body
return status_line + body

def _deserialize_response(self, payload):
"""Convert string into httplib2 response and content.
Expand Down Expand Up @@ -1236,7 +1237,7 @@ def _execute(self, http, order, requests):

# encode the body: note that we can't use `as_string`, because
# it plays games with `From ` lines.
fp = StringIO.StringIO()
fp = StringIO()
g = Generator(fp, mangle_from_=False)
g.flatten(message, unixfrom=False)
body = fp.getvalue()
Expand Down
12 changes: 8 additions & 4 deletions googleapiclient/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@

import json
import logging
import urllib

from six.moves.urllib.parse import urlencode

from googleapiclient import __version__
from .errors import HttpError
from googleapiclient.errors import HttpError


dump_request_response = False
Expand Down Expand Up @@ -170,7 +171,7 @@ def _build_query(self, params):
if isinstance(value, six.text_type) and callable(value.encode):
value = value.encode('utf-8')
astuples.append((key, value))
return '?' + urllib.urlencode(astuples)
return '?' + urlencode(astuples)

def _log_response(self, resp, content):
"""Logs debugging information about the response if requested."""
Expand Down Expand Up @@ -257,7 +258,10 @@ def serialize(self, body_value):
return json.dumps(body_value)

def deserialize(self, content):
content = content.decode('utf-8')
try:
content = content.decode('utf-8')
except AttributeError:
pass
body = json.loads(content)
if self._data_wrapper and isinstance(body, dict) and 'data' in body:
body = body['data']
Expand Down
10 changes: 5 additions & 5 deletions googleapiclient/sample_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ def init(argv, name, version, doc, filename, scope=None, parents=[], discovery_f
service = discovery.build(name, version, http=http)
else:
# Construct a service object using a local discovery document file.
with open(discovery_filename) as discovery_file:
service = discovery.build_from_document(
discovery_file.read(),
base='https://www.googleapis.com/',
http=http)
with open(discovery_filename) as discovery_file:
service = discovery.build_from_document(
discovery_file.read(),
base='https://www.googleapis.com/',
http=http)
return (service, flags)
Loading

0 comments on commit cf939a3

Please sign in to comment.