From 9aa56cb0d5dede7fc176a46c745dfd3dacdad773 Mon Sep 17 00:00:00 2001 From: sage Date: Wed, 27 Mar 2019 11:40:10 +0700 Subject: [PATCH] Fixed #30294 -- Allowed HttpResponse to accept memoryview content. --- django/http/response.py | 2 +- docs/ref/request-response.txt | 21 +++++++++++++++------ docs/releases/3.0.txt | 3 ++- tests/httpwrappers/tests.py | 4 ++++ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/django/http/response.py b/django/http/response.py index 6a84e193ba..a9ede09dd9 100644 --- a/django/http/response.py +++ b/django/http/response.py @@ -229,7 +229,7 @@ class HttpResponseBase: # Handle string types -- we can't rely on force_bytes here because: # - Python attempts str conversion first # - when self._charset != 'utf-8' it re-encodes the content - if isinstance(value, bytes): + if isinstance(value, (bytes, memoryview)): return bytes(value) if isinstance(value, str): return bytes(value.encode(self.charset)) diff --git a/docs/ref/request-response.txt b/docs/ref/request-response.txt index 4adc20bb25..d6a336178e 100644 --- a/docs/ref/request-response.txt +++ b/docs/ref/request-response.txt @@ -631,13 +631,18 @@ Usage Passing strings ~~~~~~~~~~~~~~~ -Typical usage is to pass the contents of the page, as a string or bytestring, -to the :class:`HttpResponse` constructor:: +Typical usage is to pass the contents of the page, as a string, bytestring, +or :class:`memoryview`, to the :class:`HttpResponse` constructor:: >>> from django.http import HttpResponse >>> response = HttpResponse("Here's the text of the Web page.") >>> response = HttpResponse("Text only, please.", content_type="text/plain") >>> response = HttpResponse(b'Bytestrings are also accepted.') + >>> response = HttpResponse(memoryview(b'Memoryview as well.')) + +.. versionchanged:: 3.0 + + Support for :class:`memoryview` was added. But if you want to add content incrementally, you can use ``response`` as a file-like object:: @@ -741,10 +746,10 @@ Methods Instantiates an ``HttpResponse`` object with the given page content and content type. - ``content`` is most commonly an iterator, bytestring, or string. Other - types will be converted to a bytestring by encoding their string - representation. Iterators should return strings or bytestrings and those - will be joined together to form the content of the response. + ``content`` is most commonly an iterator, bytestring, :class:`memoryview`, + or string. Other types will be converted to a bytestring by encoding their + string representation. Iterators should return strings or bytestrings and + those will be joined together to form the content of the response. ``content_type`` is the MIME type optionally completed by a character set encoding and is used to fill the HTTP ``Content-Type`` header. If not @@ -760,6 +765,10 @@ Methods given it will be extracted from ``content_type``, and if that is unsuccessful, the :setting:`DEFAULT_CHARSET` setting will be used. + .. versionchanged:: 3.0 + + Support for :class:`memoryview` ``content`` was added. + .. method:: HttpResponse.__setitem__(header, value) Sets the given header name to the given value. Both ``header`` and diff --git a/docs/releases/3.0.txt b/docs/releases/3.0.txt index 33fa6ddfe0..11257b70be 100644 --- a/docs/releases/3.0.txt +++ b/docs/releases/3.0.txt @@ -188,7 +188,8 @@ Models Requests and Responses ~~~~~~~~~~~~~~~~~~~~~~ -* ... +* Allowed :class:`~django.http.HttpResponse` to be initialized with + :class:`memoryview` content. Serialization ~~~~~~~~~~~~~ diff --git a/tests/httpwrappers/tests.py b/tests/httpwrappers/tests.py index e6c6297898..0c81cd0341 100644 --- a/tests/httpwrappers/tests.py +++ b/tests/httpwrappers/tests.py @@ -366,6 +366,10 @@ class HttpResponseTests(unittest.TestCase): r.content = 12345 self.assertEqual(r.content, b'12345') + def test_memoryview_content(self): + r = HttpResponse(memoryview(b'memoryview')) + self.assertEqual(r.content, b'memoryview') + def test_iter_content(self): r = HttpResponse(['abc', 'def', 'ghi']) self.assertEqual(r.content, b'abcdefghi')