Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions googleapiclient/discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,17 @@
'key2param',
]

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

# Standard library imports
import copy
from email.generator import Generator
try:
from email.generator import BytesGenerator
except ImportError:
from email.generator import Generator as BytesGenerator
from email.mime.multipart import MIMEMultipart
from email.mime.nonmultipart import MIMENonMultipart
import json
Expand Down Expand Up @@ -102,6 +105,10 @@
# Library-specific reserved words beyond Python keywords.
RESERVED_WORDS = frozenset(['body'])

# patch _write_lines to avoid munging '\r' into '\n'
# ( https://bugs.python.org/issue18886 https://bugs.python.org/issue19003 )
class _BytesGenerator(BytesGenerator):
_write_lines = BytesGenerator.write

def fix_method_name(name):
"""Fix method names to avoid reserved word conflicts.
Expand Down Expand Up @@ -797,8 +804,8 @@ 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()
g = Generator(fp, mangle_from_=False)
fp = BytesIO()
g = _BytesGenerator(fp, mangle_from_=False)
g.flatten(msgRoot, unixfrom=False)

This comment was marked as spam.

body = fp.getvalue()

Expand Down
17 changes: 16 additions & 1 deletion tests/test_discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import json
import os
import pickle
import re
import sys
import unittest2 as unittest

Expand Down Expand Up @@ -787,7 +788,21 @@ def test_multipart_media_good_upload(self):
request = zoo.animals().insert(media_body=datafile('small.png'), body={})
self.assertTrue(request.headers['content-type'].startswith(
'multipart/related'))
self.assertEquals('--==', request.body[0:4])
with open(datafile('small.png'), 'rb') as f:
contents = f.read()
boundary = re.match(b'--=+([^=]+)', request.body).group(1)
self.assertEqual(
request.body.rstrip(b"\n"), # Python 2.6 does not add a trailing \n
b'--===============' + boundary + b'==\n' +
b'Content-Type: application/json\n' +
b'MIME-Version: 1.0\n\n' +
b'{"data": {}}\n' +
b'--===============' + boundary + b'==\n' +
b'Content-Type: image/png\n' +
b'MIME-Version: 1.0\n' +
b'Content-Transfer-Encoding: binary\n\n' +
contents +
b'\n--===============' + boundary + b'==--')
assertUrisEqual(self,
'https://www.googleapis.com/upload/zoo/v1/animals?uploadType=multipart&alt=json',
request.uri)
Expand Down