Loading django/http/__init__.py +4 −4 Original line number Diff line number Diff line Loading @@ -2,9 +2,9 @@ from django.http.cookie import SimpleCookie, parse_cookie from django.http.request import (HttpRequest, QueryDict, UnreadablePostError, build_request_repr) from django.http.response import (HttpResponse, StreamingHttpResponse, CompatibleStreamingHttpResponse, HttpResponsePermanentRedirect, HttpResponseRedirect, HttpResponseNotModified, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseNotFound, HttpResponseNotAllowed, HttpResponseGone, HttpResponseServerError, Http404, BadHeaderError) HttpResponseRedirect, HttpResponsePermanentRedirect, HttpResponseNotModified, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseNotFound, HttpResponseNotAllowed, HttpResponseGone, HttpResponseServerError, Http404, BadHeaderError) from django.http.utils import (fix_location_header, conditional_content_removal, fix_IE_for_attach, fix_IE_for_vary) django/http/response.py +2 −59 Original line number Diff line number Diff line Loading @@ -2,7 +2,6 @@ from __future__ import absolute_import, unicode_literals import datetime import time import warnings from email.header import Header try: from urllib.parse import urlparse Loading Loading @@ -332,53 +331,27 @@ class HttpResponse(HttpResponseBase): else: __str__ = serialize def _consume_content(self): # If the response was instantiated with an iterator, when its content # is accessed, the iterator is going be exhausted and the content # loaded in memory. At this point, it's better to abandon the original # iterator and save the content for later reuse. This is a temporary # solution. See the comment in __iter__ below for the long term plan. if self._base_content_is_iter: self.content = b''.join(self.make_bytes(e) for e in self._container) @property def content(self): self._consume_content() return b''.join(self.make_bytes(e) for e in self._container) @content.setter def content(self, value): if hasattr(value, '__iter__') and not isinstance(value, (bytes, six.string_types)): self._container = value self._base_content_is_iter = True if hasattr(value, 'close'): self._closable_objects.append(value) else: value = b''.join(self.make_bytes(e) for e in value) self._container = [value] self._base_content_is_iter = False def __iter__(self): # Raise a deprecation warning only if the content wasn't consumed yet, # because the response may be intended to be streamed. # Once the deprecation completes, iterators should be consumed upon # assignment rather than upon access. The _consume_content method # should be removed. See #6527. if self._base_content_is_iter: warnings.warn( 'Creating streaming responses with `HttpResponse` is ' 'deprecated. Use `StreamingHttpResponse` instead ' 'if you need the streaming behavior.', DeprecationWarning, stacklevel=2) if not hasattr(self, '_iterator'): self._iterator = iter(self._container) return self def write(self, content): self._consume_content() self._container.append(content) def tell(self): self._consume_content() return len(self.content) Loading Loading @@ -416,35 +389,6 @@ class StreamingHttpResponse(HttpResponseBase): self._closable_objects.append(value) class CompatibleStreamingHttpResponse(StreamingHttpResponse): """ This class maintains compatibility with middleware that doesn't know how to handle the content of a streaming response by exposing a `content` attribute that will consume and cache the content iterator when accessed. These responses will stream only if no middleware attempts to access the `content` attribute. Otherwise, they will behave like a regular response, and raise a `DeprecationWarning`. """ @property def content(self): warnings.warn( 'Accessing the `content` attribute on a streaming response is ' 'deprecated. Use the `streaming_content` attribute instead.', DeprecationWarning, stacklevel=2) content = b''.join(self) self.streaming_content = [content] return content @content.setter def content(self, content): warnings.warn( 'Accessing the `content` attribute on a streaming response is ' 'deprecated. Use the `streaming_content` attribute instead.', DeprecationWarning, stacklevel=2) self.streaming_content = [content] class HttpResponseRedirectBase(HttpResponse): allowed_schemes = ['http', 'https', 'ftp'] Loading Loading @@ -478,7 +422,6 @@ class HttpResponseNotModified(HttpResponse): if value: raise AttributeError("You cannot set content to a 304 (Not Modified) response") self._container = [] self._base_content_is_iter = False class HttpResponseBadRequest(HttpResponse): Loading django/views/static.py +4 −4 Original line number Diff line number Diff line Loading @@ -14,8 +14,8 @@ try: except ImportError: # Python 2 from urllib import unquote from django.http import (CompatibleStreamingHttpResponse, Http404, HttpResponse, HttpResponseRedirect, HttpResponseNotModified) from django.http import (Http404, HttpResponse, HttpResponseRedirect, HttpResponseNotModified, StreamingHttpResponse) from django.template import loader, Template, Context, TemplateDoesNotExist from django.utils.http import http_date, parse_http_date from django.utils.translation import ugettext as _, ugettext_noop Loading Loading @@ -63,7 +63,7 @@ def serve(request, path, document_root=None, show_indexes=False): return HttpResponseNotModified() content_type, encoding = mimetypes.guess_type(fullpath) content_type = content_type or 'application/octet-stream' response = CompatibleStreamingHttpResponse(open(fullpath, 'rb'), response = StreamingHttpResponse(open(fullpath, 'rb'), content_type=content_type) response["Last-Modified"] = http_date(statobj.st_mtime) if stat.S_ISREG(statobj.st_mode): Loading tests/httpwrappers/tests.py +6 −19 Original line number Diff line number Diff line Loading @@ -324,19 +324,10 @@ class HttpResponseTests(unittest.TestCase): r.content = [1, 2, 3] self.assertEqual(r.content, b'123') #test retrieval explicitly using iter (deprecated) and odd inputs #test odd inputs r = HttpResponse() r.content = ['1', '2', 3, '\u079e'] with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always", DeprecationWarning) my_iter = iter(r) self.assertEqual(w[0].category, DeprecationWarning) with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always", DeprecationWarning) result = list(my_iter) self.assertEqual(w[0].category, DeprecationWarning) #'\xde\x9e' == unichr(1950).encode('utf-8') self.assertEqual(result, [b'1', b'2', b'3', b'\xde\x9e']) self.assertEqual(r.content, b'123\xde\x9e') #with Content-Encoding header Loading @@ -344,9 +335,8 @@ class HttpResponseTests(unittest.TestCase): r['Content-Encoding'] = 'winning' r.content = [b'abc', b'def'] self.assertEqual(r.content, b'abcdef') r.content = ['\u079e'] self.assertRaises(TypeError if six.PY3 else UnicodeEncodeError, getattr, r, 'content') setattr, r, 'content', ['\u079e']) # .content can safely be accessed multiple times. r = HttpResponse(iter(['hello', 'world'])) Loading @@ -358,15 +348,12 @@ class HttpResponseTests(unittest.TestCase): # 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 # Accessing .content also works if the response was iterated first. r = HttpResponse(iter(['hello', 'world'])) with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) self.assertEqual(b''.join(r), b'helloworld') self.assertEqual(r.content, b'') # not the expected result! self.assertEqual(r.content, b'helloworld') # additional content can be written to the response. # Additional content can be written to the response. r = HttpResponse(iter(['hello', 'world'])) self.assertEqual(r.content, b'helloworld') r.write('!') Loading Loading
django/http/__init__.py +4 −4 Original line number Diff line number Diff line Loading @@ -2,9 +2,9 @@ from django.http.cookie import SimpleCookie, parse_cookie from django.http.request import (HttpRequest, QueryDict, UnreadablePostError, build_request_repr) from django.http.response import (HttpResponse, StreamingHttpResponse, CompatibleStreamingHttpResponse, HttpResponsePermanentRedirect, HttpResponseRedirect, HttpResponseNotModified, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseNotFound, HttpResponseNotAllowed, HttpResponseGone, HttpResponseServerError, Http404, BadHeaderError) HttpResponseRedirect, HttpResponsePermanentRedirect, HttpResponseNotModified, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseNotFound, HttpResponseNotAllowed, HttpResponseGone, HttpResponseServerError, Http404, BadHeaderError) from django.http.utils import (fix_location_header, conditional_content_removal, fix_IE_for_attach, fix_IE_for_vary)
django/http/response.py +2 −59 Original line number Diff line number Diff line Loading @@ -2,7 +2,6 @@ from __future__ import absolute_import, unicode_literals import datetime import time import warnings from email.header import Header try: from urllib.parse import urlparse Loading Loading @@ -332,53 +331,27 @@ class HttpResponse(HttpResponseBase): else: __str__ = serialize def _consume_content(self): # If the response was instantiated with an iterator, when its content # is accessed, the iterator is going be exhausted and the content # loaded in memory. At this point, it's better to abandon the original # iterator and save the content for later reuse. This is a temporary # solution. See the comment in __iter__ below for the long term plan. if self._base_content_is_iter: self.content = b''.join(self.make_bytes(e) for e in self._container) @property def content(self): self._consume_content() return b''.join(self.make_bytes(e) for e in self._container) @content.setter def content(self, value): if hasattr(value, '__iter__') and not isinstance(value, (bytes, six.string_types)): self._container = value self._base_content_is_iter = True if hasattr(value, 'close'): self._closable_objects.append(value) else: value = b''.join(self.make_bytes(e) for e in value) self._container = [value] self._base_content_is_iter = False def __iter__(self): # Raise a deprecation warning only if the content wasn't consumed yet, # because the response may be intended to be streamed. # Once the deprecation completes, iterators should be consumed upon # assignment rather than upon access. The _consume_content method # should be removed. See #6527. if self._base_content_is_iter: warnings.warn( 'Creating streaming responses with `HttpResponse` is ' 'deprecated. Use `StreamingHttpResponse` instead ' 'if you need the streaming behavior.', DeprecationWarning, stacklevel=2) if not hasattr(self, '_iterator'): self._iterator = iter(self._container) return self def write(self, content): self._consume_content() self._container.append(content) def tell(self): self._consume_content() return len(self.content) Loading Loading @@ -416,35 +389,6 @@ class StreamingHttpResponse(HttpResponseBase): self._closable_objects.append(value) class CompatibleStreamingHttpResponse(StreamingHttpResponse): """ This class maintains compatibility with middleware that doesn't know how to handle the content of a streaming response by exposing a `content` attribute that will consume and cache the content iterator when accessed. These responses will stream only if no middleware attempts to access the `content` attribute. Otherwise, they will behave like a regular response, and raise a `DeprecationWarning`. """ @property def content(self): warnings.warn( 'Accessing the `content` attribute on a streaming response is ' 'deprecated. Use the `streaming_content` attribute instead.', DeprecationWarning, stacklevel=2) content = b''.join(self) self.streaming_content = [content] return content @content.setter def content(self, content): warnings.warn( 'Accessing the `content` attribute on a streaming response is ' 'deprecated. Use the `streaming_content` attribute instead.', DeprecationWarning, stacklevel=2) self.streaming_content = [content] class HttpResponseRedirectBase(HttpResponse): allowed_schemes = ['http', 'https', 'ftp'] Loading Loading @@ -478,7 +422,6 @@ class HttpResponseNotModified(HttpResponse): if value: raise AttributeError("You cannot set content to a 304 (Not Modified) response") self._container = [] self._base_content_is_iter = False class HttpResponseBadRequest(HttpResponse): Loading
django/views/static.py +4 −4 Original line number Diff line number Diff line Loading @@ -14,8 +14,8 @@ try: except ImportError: # Python 2 from urllib import unquote from django.http import (CompatibleStreamingHttpResponse, Http404, HttpResponse, HttpResponseRedirect, HttpResponseNotModified) from django.http import (Http404, HttpResponse, HttpResponseRedirect, HttpResponseNotModified, StreamingHttpResponse) from django.template import loader, Template, Context, TemplateDoesNotExist from django.utils.http import http_date, parse_http_date from django.utils.translation import ugettext as _, ugettext_noop Loading Loading @@ -63,7 +63,7 @@ def serve(request, path, document_root=None, show_indexes=False): return HttpResponseNotModified() content_type, encoding = mimetypes.guess_type(fullpath) content_type = content_type or 'application/octet-stream' response = CompatibleStreamingHttpResponse(open(fullpath, 'rb'), response = StreamingHttpResponse(open(fullpath, 'rb'), content_type=content_type) response["Last-Modified"] = http_date(statobj.st_mtime) if stat.S_ISREG(statobj.st_mode): Loading
tests/httpwrappers/tests.py +6 −19 Original line number Diff line number Diff line Loading @@ -324,19 +324,10 @@ class HttpResponseTests(unittest.TestCase): r.content = [1, 2, 3] self.assertEqual(r.content, b'123') #test retrieval explicitly using iter (deprecated) and odd inputs #test odd inputs r = HttpResponse() r.content = ['1', '2', 3, '\u079e'] with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always", DeprecationWarning) my_iter = iter(r) self.assertEqual(w[0].category, DeprecationWarning) with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always", DeprecationWarning) result = list(my_iter) self.assertEqual(w[0].category, DeprecationWarning) #'\xde\x9e' == unichr(1950).encode('utf-8') self.assertEqual(result, [b'1', b'2', b'3', b'\xde\x9e']) self.assertEqual(r.content, b'123\xde\x9e') #with Content-Encoding header Loading @@ -344,9 +335,8 @@ class HttpResponseTests(unittest.TestCase): r['Content-Encoding'] = 'winning' r.content = [b'abc', b'def'] self.assertEqual(r.content, b'abcdef') r.content = ['\u079e'] self.assertRaises(TypeError if six.PY3 else UnicodeEncodeError, getattr, r, 'content') setattr, r, 'content', ['\u079e']) # .content can safely be accessed multiple times. r = HttpResponse(iter(['hello', 'world'])) Loading @@ -358,15 +348,12 @@ class HttpResponseTests(unittest.TestCase): # 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 # Accessing .content also works if the response was iterated first. r = HttpResponse(iter(['hello', 'world'])) with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) self.assertEqual(b''.join(r), b'helloworld') self.assertEqual(r.content, b'') # not the expected result! self.assertEqual(r.content, b'helloworld') # additional content can be written to the response. # Additional content can be written to the response. r = HttpResponse(iter(['hello', 'world'])) self.assertEqual(r.content, b'helloworld') r.write('!') Loading