Fixed #13222 -- Made HttpResponse iterable once

response.content can be accessed many times as desired, and always
returns the same result.

iter(response) works only once and consumes the iterator.
This commit is contained in:
Aymeric Augustin 2012-10-24 11:33:56 +02:00
parent 495a8b8107
commit 82b3e6ffcb
3 changed files with 30 additions and 4 deletions

View File

@ -283,7 +283,8 @@ class HttpResponse(HttpResponseBase):
'deprecated. Use `StreamingHttpResponse` instead '
'if you need the streaming behavior.',
PendingDeprecationWarning, stacklevel=2)
self._iterator = iter(self._container)
if not hasattr(self, '_iterator'):
self._iterator = iter(self._container)
return self
def __next__(self):
@ -303,7 +304,7 @@ class HttpResponse(HttpResponseBase):
def tell(self):
self._consume_content()
return sum(len(chunk) for chunk in self)
return len(self.content)
class StreamingHttpResponse(HttpResponseBase):

View File

@ -596,7 +596,11 @@ class TransactionTestCase(SimpleTestCase):
msg_prefix + "Couldn't retrieve content: Response code was %d"
" (expected %d)" % (response.status_code, status_code))
text = force_text(text, encoding=response._charset)
content = b''.join(response).decode(response._charset)
if response.streaming:
content = b''.join(response.streaming_content)
else:
content = response.content
content = content.decode(response._charset)
# Avoid ResourceWarning about unclosed files.
response.close()
if html:

View File

@ -337,15 +337,36 @@ class HttpResponseTests(unittest.TestCase):
self.assertRaises(UnicodeEncodeError,
getattr, r, 'content')
# content can safely be accessed multiple times.
# .content can safely be accessed multiple times.
r = HttpResponse(iter(['hello', 'world']))
self.assertEqual(r.content, r.content)
self.assertEqual(r.content, b'helloworld')
# accessing the iterator works (once) after accessing .content
self.assertEqual(b''.join(r), b'helloworld')
self.assertEqual(b''.join(r), b'')
# accessing .content still works
self.assertEqual(r.content, b'helloworld')
# XXX accessing .content doesn't work if the response was iterated first
# XXX change this when the deprecation completes in HttpResponse
r = HttpResponse(iter(['hello', 'world']))
with warnings.catch_warnings():
warnings.simplefilter("ignore", PendingDeprecationWarning)
self.assertEqual(b''.join(r), b'helloworld')
self.assertEqual(r.content, b'') # not the expected result!
# additional content can be written to the response.
r = HttpResponse(iter(['hello', 'world']))
self.assertEqual(r.content, b'helloworld')
r.write('!')
self.assertEqual(r.content, b'helloworld!')
def test_iterator_isnt_rewound(self):
# Regression test for #13222
r = HttpResponse('abc')
i = iter(r)
self.assertEqual(list(i), [b'abc'])
self.assertEqual(list(i), [])
def test_file_interface(self):
r = HttpResponse()