summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/core/handlers/wsgi.py10
-rw-r--r--django/http/request.py17
-rw-r--r--django/http/response.py2
-rw-r--r--docs/releases/4.2.1.txt4
-rw-r--r--tests/requests_tests/tests.py29
5 files changed, 22 insertions, 40 deletions
diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py
index c2b7cc2b6f..9324af083e 100644
--- a/django/core/handlers/wsgi.py
+++ b/django/core/handlers/wsgi.py
@@ -54,9 +54,6 @@ class LimitedStream(IOBase):
class WSGIRequest(HttpRequest):
- non_picklable_attrs = HttpRequest.non_picklable_attrs | frozenset(["environ"])
- meta_non_picklable_attrs = frozenset(["wsgi.errors", "wsgi.input"])
-
def __init__(self, environ):
script_name = get_script_name(environ)
# If PATH_INFO is empty (e.g. accessing the SCRIPT_NAME URL without a
@@ -82,13 +79,6 @@ class WSGIRequest(HttpRequest):
self._read_started = False
self.resolver_match = None
- def __getstate__(self):
- state = super().__getstate__()
- for attr in self.meta_non_picklable_attrs:
- if attr in state["META"]:
- del state["META"][attr]
- return state
-
def _get_scheme(self):
return self.environ.get("wsgi.url_scheme")
diff --git a/django/http/request.py b/django/http/request.py
index 2ef9dfd649..be6823cacb 100644
--- a/django/http/request.py
+++ b/django/http/request.py
@@ -55,8 +55,6 @@ class HttpRequest:
_encoding = None
_upload_handlers = []
- non_picklable_attrs = frozenset(["resolver_match", "_stream"])
-
def __init__(self):
# WARNING: The `WSGIRequest` subclass doesn't call `super`.
# Any variable assignment made here should also happen in
@@ -84,21 +82,6 @@ class HttpRequest:
self.get_full_path(),
)
- 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 __deepcopy__(self, memo):
- obj = copy.copy(self)
- for attr in self.non_picklable_attrs:
- if hasattr(self, attr):
- setattr(obj, attr, copy.deepcopy(getattr(self, attr), memo))
- memo[id(self)] = obj
- return obj
-
@cached_property
def headers(self):
return HttpHeaders(self.META)
diff --git a/django/http/response.py b/django/http/response.py
index 3b611e78f5..58993801e1 100644
--- a/django/http/response.py
+++ b/django/http/response.py
@@ -373,10 +373,12 @@ class HttpResponse(HttpResponseBase):
[
"resolver_match",
# Non-picklable attributes added by test clients.
+ "asgi_request",
"client",
"context",
"json",
"templates",
+ "wsgi_request",
]
)
diff --git a/docs/releases/4.2.1.txt b/docs/releases/4.2.1.txt
index 525830a01b..621fc3ec30 100644
--- a/docs/releases/4.2.1.txt
+++ b/docs/releases/4.2.1.txt
@@ -29,3 +29,7 @@ Bugfixes
* Fixed a regression in Django 4.2 where ``i18n_patterns()`` didn't respect the
``prefix_default_language`` argument when a fallback language of the default
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`).
diff --git a/tests/requests_tests/tests.py b/tests/requests_tests/tests.py
index ef218afe2f..d3e9e66224 100644
--- a/tests/requests_tests/tests.py
+++ b/tests/requests_tests/tests.py
@@ -1,4 +1,4 @@
-import pickle
+import copy
from io import BytesIO
from itertools import chain
from urllib.parse import urlencode
@@ -233,6 +233,11 @@ class RequestsTests(SimpleTestCase):
# left percent-encoded in the path.
self.assertEqual(request.path, "/caf%E9/")
+ def test_wsgirequest_copy(self):
+ request = WSGIRequest({"REQUEST_METHOD": "get", "wsgi.input": BytesIO(b"")})
+ request_copy = copy.copy(request)
+ self.assertIs(request_copy.environ, request.environ)
+
def test_limited_stream(self):
# Read all of a limited stream
stream = LimitedStream(BytesIO(b"test"), 2)
@@ -687,19 +692,17 @@ class RequestsTests(SimpleTestCase):
with self.assertRaises(UnreadablePostError):
request.FILES
- def test_pickling_request(self):
+ def test_copy(self):
request = HttpRequest()
- request.method = "GET"
- request.path = "/testpath/"
- request.META = {
- "QUERY_STRING": ";some=query&+query=string",
- "SERVER_NAME": "example.com",
- "SERVER_PORT": 80,
- }
- request.COOKIES = {"post-key": "post-value"}
- dump = pickle.dumps(request)
- request_from_pickle = pickle.loads(dump)
- self.assertEqual(repr(request), repr(request_from_pickle))
+ request_copy = copy.copy(request)
+ self.assertIs(request_copy.resolver_match, request.resolver_match)
+
+ def test_deepcopy(self):
+ request = RequestFactory().get("/")
+ request.session = {}
+ request_copy = copy.deepcopy(request)
+ request.session["key"] = "value"
+ self.assertEqual(request_copy.session, {})
class HostValidationTests(SimpleTestCase):