summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAymeric Augustin <aymeric.augustin@m4x.org>2012-10-24 11:33:56 +0200
committerAymeric Augustin <aymeric.augustin@m4x.org>2012-10-24 17:19:56 +0200
commit82b3e6ffcb9d810cc0e3ec27d25f89ce1fd525e0 (patch)
tree3246bfe94e5ba9930e883890bac553c1121220b9
parent495a8b8107dbd4fb511954bcd2322d125addd94e (diff)
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.
-rw-r--r--django/http/response.py5
-rw-r--r--django/test/testcases.py6
-rw-r--r--tests/regressiontests/httpwrappers/tests.py23
3 files changed, 30 insertions, 4 deletions
diff --git a/django/http/response.py b/django/http/response.py
index e9cc3f70a9..6bbadd7e2b 100644
--- a/django/http/response.py
+++ b/django/http/response.py
@@ -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):
diff --git a/django/test/testcases.py b/django/test/testcases.py
index cfa2cde643..1239275264 100644
--- a/django/test/testcases.py
+++ b/django/test/testcases.py
@@ -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:
diff --git a/tests/regressiontests/httpwrappers/tests.py b/tests/regressiontests/httpwrappers/tests.py
index 7f61a3074f..8e20c80de3 100644
--- a/tests/regressiontests/httpwrappers/tests.py
+++ b/tests/regressiontests/httpwrappers/tests.py
@@ -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()