summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2023-04-12 09:46:18 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2023-04-12 18:52:43 +0200
commit173034b00589c083793d495e8b07e35be2cb1cf0 (patch)
treeb242f05f2c5118a0986f1ffb088341b6909f47fb
parent280ca147af9cdfce1ca9cb14cc3c5527ff6c7a02 (diff)
downloaddjango-173034b00589c083793d495e8b07e35be2cb1cf0.tar.gz
Refs #34482 -- Reverted "Fixed #32969 -- Fixed pickling HttpResponse and subclasses."
This reverts commit d7f5bfd241666c0a76e90208da1e9ef81aec44db. Thanks Márton Salomváry for the report.
-rw-r--r--django/http/response.py19
-rw-r--r--django/template/response.py15
-rw-r--r--docs/releases/4.2.1.txt4
-rw-r--r--docs/releases/4.2.txt3
-rw-r--r--tests/test_client/tests.py22
5 files changed, 23 insertions, 40 deletions
diff --git a/django/http/response.py b/django/http/response.py
index 58993801e1..eecd972cd6 100644
--- a/django/http/response.py
+++ b/django/http/response.py
@@ -369,31 +369,12 @@ class HttpResponse(HttpResponseBase):
"""
streaming = False
- non_picklable_attrs = frozenset(
- [
- "resolver_match",
- # Non-picklable attributes added by test clients.
- "asgi_request",
- "client",
- "context",
- "json",
- "templates",
- "wsgi_request",
- ]
- )
def __init__(self, content=b"", *args, **kwargs):
super().__init__(*args, **kwargs)
# Content is a bytestring. See the `content` property methods.
self.content = content
- def __getstate__(self):
- obj_dict = self.__dict__.copy()
- for attr in self.non_picklable_attrs:
- if attr in obj_dict:
- del obj_dict[attr]
- return obj_dict
-
def __repr__(self):
return "<%(cls)s status_code=%(status_code)d%(content_type)s>" % {
"cls": self.__class__.__name__,
diff --git a/django/template/response.py b/django/template/response.py
index b4f0e171f1..c38b95e9de 100644
--- a/django/template/response.py
+++ b/django/template/response.py
@@ -8,9 +8,7 @@ class ContentNotRenderedError(Exception):
class SimpleTemplateResponse(HttpResponse):
- non_picklable_attrs = HttpResponse.non_picklable_attrs | frozenset(
- ["template_name", "context_data", "_post_render_callbacks"]
- )
+ rendering_attrs = ["template_name", "context_data", "_post_render_callbacks"]
def __init__(
self,
@@ -57,11 +55,16 @@ class SimpleTemplateResponse(HttpResponse):
Raise an exception if trying to pickle an unrendered response. Pickle
only rendered data, not the data used to construct the response.
"""
+ obj_dict = self.__dict__.copy()
if not self._is_rendered:
raise ContentNotRenderedError(
"The response content must be rendered before it can be pickled."
)
- return super().__getstate__()
+ for attr in self.rendering_attrs:
+ if attr in obj_dict:
+ del obj_dict[attr]
+
+ return obj_dict
def resolve_template(self, template):
"""Accept a template object, path-to-template, or list of paths."""
@@ -142,9 +145,7 @@ class SimpleTemplateResponse(HttpResponse):
class TemplateResponse(SimpleTemplateResponse):
- non_picklable_attrs = SimpleTemplateResponse.non_picklable_attrs | frozenset(
- ["_request"]
- )
+ rendering_attrs = SimpleTemplateResponse.rendering_attrs + ["_request"]
def __init__(
self,
diff --git a/docs/releases/4.2.1.txt b/docs/releases/4.2.1.txt
index 621fc3ec30..2bfe21cd47 100644
--- a/docs/releases/4.2.1.txt
+++ b/docs/releases/4.2.1.txt
@@ -31,5 +31,5 @@ Bugfixes
language was used (:ticket:`34455`).
* Fixed a regression in Django 4.2 where creating copies and deep copies of
- ``HttpRequest`` and its subclasses didn't always work correctly
- (:ticket:`34482`, :ticket:`34484`).
+ ``HttpRequest``, ``HttpResponse``, and their subclasses didn't always work
+ correctly (:ticket:`34482`, :ticket:`34484`).
diff --git a/docs/releases/4.2.txt b/docs/releases/4.2.txt
index a7c20a7d6d..17d0dc956d 100644
--- a/docs/releases/4.2.txt
+++ b/docs/releases/4.2.txt
@@ -416,9 +416,6 @@ fields modified in the custom ``save()`` methods should be added to the
Miscellaneous
-------------
-* The undocumented ``SimpleTemplateResponse.rendering_attrs`` and
- ``TemplateResponse.rendering_attrs`` are renamed to ``non_picklable_attrs``.
-
* The undocumented ``django.http.multipartparser.parse_header()`` function is
removed. Use ``django.utils.http.parse_header_parameters()`` instead.
diff --git a/tests/test_client/tests.py b/tests/test_client/tests.py
index 127cc61606..a5e980f3d0 100644
--- a/tests/test_client/tests.py
+++ b/tests/test_client/tests.py
@@ -19,8 +19,8 @@ testing against the contexts and templates produced by a view,
rather than the HTML rendered to the end-user.
"""
+import copy
import itertools
-import pickle
import tempfile
from unittest import mock
@@ -81,20 +81,24 @@ class ClientTest(TestCase):
self.assertEqual(response.context["var"], "\xf2")
self.assertEqual(response.templates[0].name, "GET Template")
- def test_pickling_response(self):
+ def test_copy_response(self):
tests = ["/cbv_view/", "/get_view/"]
for url in tests:
with self.subTest(url=url):
response = self.client.get(url)
- dump = pickle.dumps(response)
- response_from_pickle = pickle.loads(dump)
- self.assertEqual(repr(response), repr(response_from_pickle))
+ response_copy = copy.copy(response)
+ self.assertEqual(repr(response), repr(response_copy))
+ self.assertIs(response_copy.client, response.client)
+ self.assertIs(response_copy.resolver_match, response.resolver_match)
+ self.assertIs(response_copy.wsgi_request, response.wsgi_request)
- async def test_pickling_response_async(self):
+ async def test_copy_response_async(self):
response = await self.async_client.get("/async_get_view/")
- dump = pickle.dumps(response)
- response_from_pickle = pickle.loads(dump)
- self.assertEqual(repr(response), repr(response_from_pickle))
+ response_copy = copy.copy(response)
+ self.assertEqual(repr(response), repr(response_copy))
+ self.assertIs(response_copy.client, response.client)
+ self.assertIs(response_copy.resolver_match, response.resolver_match)
+ self.assertIs(response_copy.asgi_request, response.asgi_request)
def test_query_string_encoding(self):
# WSGI requires latin-1 encoded strings.