Skip to content

Commit 86d1342

Browse files
author
j.s@google.com
committed
Allows old service object to use the new mock_http_core HttpClient.
1 parent 3789c47 commit 86d1342

5 files changed

Lines changed: 54 additions & 30 deletions

File tree

src/atom/http.py

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,25 @@
4242
import atom.http_interface
4343
import socket
4444
import base64
45+
import atom.http_core
4546

4647

4748
class ProxyError(atom.http_interface.Error):
4849
pass
4950

5051

52+
class TestConfigurationError(Exception):
53+
pass
54+
55+
5156
DEFAULT_CONTENT_TYPE = 'application/atom+xml'
5257

5358

5459
class HttpClient(atom.http_interface.GenericHttpClient):
60+
# Added to allow old v1 HttpClient objects to use the new
61+
# http_code.HttpClient. Used in unit tests to inject a mock client.
62+
v2_http_client = None
63+
5564
def __init__(self, headers=None):
5665
self.debug = False
5766
self.headers = headers or {}
@@ -79,17 +88,39 @@ def request(self, operation, url, data=None, headers=None):
7988
headers: dict of strings. HTTP headers which should be sent
8089
in the request.
8190
"""
91+
all_headers = self.headers.copy()
92+
if headers:
93+
all_headers.update(headers)
94+
95+
# If the list of headers does not include a Content-Length, attempt to
96+
# calculate it based on the data object.
97+
if data and 'Content-Length' not in all_headers:
98+
if isinstance(data, types.StringTypes):
99+
all_headers['Content-Length'] = len(data)
100+
else:
101+
raise atom.http_interface.ContentLengthRequired('Unable to calculate '
102+
'the length of the data parameter. Specify a value for '
103+
'Content-Length')
104+
105+
# Set the content type to the default value if none was set.
106+
if 'Content-Type' not in all_headers:
107+
all_headers['Content-Type'] = DEFAULT_CONTENT_TYPE
108+
109+
if self.v2_http_client is not None:
110+
http_request = atom.http_core.HttpRequest(method=operation)
111+
atom.http_core.Uri.parse_uri(str(url)).modify_request(http_request)
112+
http_request.headers = all_headers
113+
if data:
114+
http_request._body_parts.append(data)
115+
return self.v2_http_client.request(http_request=http_request)
116+
82117
if not isinstance(url, atom.url.Url):
83118
if isinstance(url, types.StringTypes):
84119
url = atom.url.parse_url(url)
85120
else:
86121
raise atom.http_interface.UnparsableUrlObject('Unable to parse url '
87122
'parameter because it was not a string or atom.url.Url')
88123

89-
all_headers = self.headers.copy()
90-
if headers:
91-
all_headers.update(headers)
92-
93124
connection = self._prepare_connection(url, all_headers)
94125

95126
if self.debug:
@@ -115,20 +146,6 @@ def request(self, operation, url, data=None, headers=None):
115146
except ValueError: # header_line missing from connection._buffer
116147
pass
117148

118-
# If the list of headers does not include a Content-Length, attempt to
119-
# calculate it based on the data object.
120-
if data and 'Content-Length' not in all_headers:
121-
if isinstance(data, types.StringTypes):
122-
all_headers['Content-Length'] = len(data)
123-
else:
124-
raise atom.http_interface.ContentLengthRequired('Unable to calculate '
125-
'the length of the data parameter. Specify a value for '
126-
'Content-Length')
127-
128-
# Set the content type to the default value if none was set.
129-
if 'Content-Type' not in all_headers:
130-
all_headers['Content-Type'] = DEFAULT_CONTENT_TYPE
131-
132149
# Send the HTTP headers.
133150
for header_name in all_headers:
134151
connection.putheader(header_name, all_headers[header_name])

src/atom/mock_http_core.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,10 @@ def _scrub_request(http_request):
188188
http_request._body_parts = []
189189
http_request.add_form_inputs(
190190
{'form_data': 'client login request has been scrubbed'})
191+
else:
192+
# We can remove the body of the post from the recorded request, since
193+
# the request body is not used when finding a matching recording.
194+
http_request._body_parts = []
191195
return http_request
192196

193197

src/gdata/client.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,14 @@ class Unauthorized(Error):
7878
pass
7979

8080

81-
def v2_entry_from_response(response_body):
81+
def v2_entry_from_response(response):
8282
"""Experimental converter which gets an Atom entry from the response."""
83-
return gdata.data.entry_from_string(response_body, version=2)
83+
return gdata.data.entry_from_string(response.read(), version=2)
8484

8585

86-
def v2_feed_from_response(response_body):
86+
def v2_feed_from_response(response):
8787
"""Experimental converter which gets an Atom feed from the response."""
88-
return gdata.data.feed_from_string(response_body, version=2)
88+
return gdata.data.feed_from_string(response.read(), version=2)
8989

9090

9191
def create_converter(obj):
@@ -100,8 +100,8 @@ def create_converter(obj):
100100
A function which takes an XML string as the only parameter and returns an
101101
object of the same type as obj.
102102
"""
103-
return lambda response_body: atom.core.xml_element_from_string(
104-
response_body, obj.__class__, version=2, encoding='UTF-8')
103+
return lambda response: atom.core.xml_element_from_string(
104+
response.read(), obj.__class__, version=2, encoding='UTF-8')
105105

106106

107107
class GDClient(atom.client.AtomPubClient):
@@ -221,7 +221,7 @@ def request(self, method=None, uri=None, auth_token=None,
221221
return None
222222
if response.status == 200 or response.status == 201:
223223
if converter is not None:
224-
return converter(response.read())
224+
return converter(response)
225225
return response
226226
# TODO: move the redirect logic into the Google Calendar client once it
227227
# exists since the redirects are only used in the calendar API.

tests/gdata_tests/client_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ def test_create_converter(self):
211211
fake_response = StringIO.StringIO(
212212
'<entry xmlns="http://www.w3.org/2005/Atom"><title>x</title></entry>')
213213
converter_function = gdata.client.create_converter(e)
214-
entry = converter_function(fake_response.read())
214+
entry = converter_function(fake_response)
215215
self.assertTrue(isinstance(entry, gdata.data.GEntry))
216216
self.assertEqual(entry.get_elements('title')[0].text, 'x')
217217

tests/gdata_tests/live_client_test.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,13 @@ def test_create_update_delete(self):
5959
http_request = atom.http_core.HttpRequest()
6060
http_request.add_body_part(str(blog_post), 'application/atom+xml')
6161

62+
def entry_from_string_wrapper(response):
63+
return atom.EntryFromString(response.read())
64+
6265
entry = self.client.request('POST',
6366
'http://www.blogger.com/feeds/%s/posts/default' % (
6467
conf.settings.BloggerConfig.blog_id),
65-
converter=atom.EntryFromString, http_request=http_request)
68+
converter=entry_from_string_wrapper, http_request=http_request)
6669
self.assertEqual(entry.title.text, conf.settings.BloggerConfig.title)
6770
# TODO: uncomment once server bug is fixed
6871
#self.assertEqual(entry.content.text, conf.settings.BloggerConfig.content)
@@ -77,7 +80,7 @@ def test_create_update_delete(self):
7780
http_request = atom.http_core.HttpRequest()
7881
http_request.add_body_part(str(entry), 'application/atom+xml')
7982
edited_entry = self.client.request('PUT', edit_link,
80-
converter=atom.EntryFromString, http_request=http_request)
83+
converter=entry_from_string_wrapper, http_request=http_request)
8184
self.assertEqual(edited_entry.title.text, 'Edited')
8285
# TODO: uncomment once server bug is fixed
8386
#self.assertEqual(edited_entry.content.text, entry.content.text)
@@ -274,8 +277,8 @@ def create_element(tag, namespace=ATOM, text=None, attributes=None):
274277
return element
275278

276279

277-
def element_from_string(text):
278-
return atom.core.xml_element_from_string(text, atom.core.XmlElement)
280+
def element_from_string(response):
281+
return atom.core.xml_element_from_string(response.read(), atom.core.XmlElement)
279282

280283

281284
def suite():

0 commit comments

Comments
 (0)