summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Delaby <nicolas@noa.one>2017-11-23 17:18:03 +0100
committerTim Graham <timograham@gmail.com>2017-11-28 19:58:23 -0500
commitae4132a940486c86364bae71b92b7e95d62cc4a7 (patch)
treefd12b9de5ce06ec6cdc346b8fb850cade0f7eb2a
parentaba31aa86b0d4bcdede1034cade0e2054d6b4a5d (diff)
[2.0.x] Fixed #28837 -- Fixed test client crash if an exception with more than one arg is raised.
Also removed usage of the problematic pattern elsewhere. Regression in 6e55e1d88a5c4453e25f0caf7ffb68973de5c0ba. Backport of 746caf3ef821dbf7588797cb2600fa81b9df9d1d from master
-rw-r--r--django/db/models/query.py6
-rw-r--r--django/test/client.py4
-rw-r--r--django/utils/autoreload.py2
-rw-r--r--tests/test_client/tests.py7
-rw-r--r--tests/test_client/urls.py1
-rw-r--r--tests/test_client/views.py9
6 files changed, 21 insertions, 8 deletions
diff --git a/django/db/models/query.py b/django/db/models/query.py
index 70aa42097c..8c22eb5d4f 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -4,7 +4,6 @@ The main QuerySet implementation. This provides the public API for the ORM.
import copy
import operator
-import sys
import warnings
from collections import OrderedDict, namedtuple
from functools import lru_cache
@@ -521,13 +520,12 @@ class QuerySet:
params = {k: v() if callable(v) else v for k, v in params.items()}
obj = self.create(**params)
return obj, True
- except IntegrityError:
- exc_info = sys.exc_info()
+ except IntegrityError as e:
try:
return self.get(**lookup), False
except self.model.DoesNotExist:
pass
- raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])
+ raise e
def _extract_model_params(self, defaults, **kwargs):
"""
diff --git a/django/test/client.py b/django/test/client.py
index d47cb087b8..6406f8309e 100644
--- a/django/test/client.py
+++ b/django/test/client.py
@@ -480,9 +480,9 @@ class Client(RequestFactory):
# Also make sure that the signalled exception is cleared from
# the local cache!
if self.exc_info:
- exc_info = self.exc_info
+ _, exc_value, _ = self.exc_info
self.exc_info = None
- raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])
+ raise exc_value
# Save the client and request that stimulated the response.
response.client = self
diff --git a/django/utils/autoreload.py b/django/utils/autoreload.py
index 2784a89aeb..0081b502fe 100644
--- a/django/utils/autoreload.py
+++ b/django/utils/autoreload.py
@@ -245,7 +245,7 @@ def check_errors(fn):
def raise_last_exception():
global _exception
if _exception is not None:
- raise _exception[0](_exception[1]).with_traceback(_exception[2])
+ raise _exception[1]
def ensure_echo_on():
diff --git a/tests/test_client/tests.py b/tests/test_client/tests.py
index 5981ca319e..f7d32aa9cd 100644
--- a/tests/test_client/tests.py
+++ b/tests/test_client/tests.py
@@ -29,7 +29,7 @@ from django.test import (
)
from django.urls import reverse_lazy
-from .views import get_view, post_view, trace_view
+from .views import TwoArgException, get_view, post_view, trace_view
@override_settings(ROOT_URLCONF='test_client.urls')
@@ -713,6 +713,11 @@ class ClientTest(TestCase):
with self.assertRaisesMessage(Exception, 'exception message'):
self.client.get('/nesting_exception_view/')
+ def test_response_raises_multi_arg_exception(self):
+ """A request may raise an exception with more than one required arg."""
+ with self.assertRaises(TwoArgException):
+ self.client.get('/two_arg_exception/')
+
def test_uploading_temp_file(self):
with tempfile.TemporaryFile() as test_file:
response = self.client.post('/upload_view/', data={'temp_file': test_file})
diff --git a/tests/test_client/urls.py b/tests/test_client/urls.py
index 9f8d09218e..40ca384751 100644
--- a/tests/test_client/urls.py
+++ b/tests/test_client/urls.py
@@ -34,6 +34,7 @@ urlpatterns = [
url(r'^mass_mail_sending_view/$', views.mass_mail_sending_view),
url(r'^nesting_exception_view/$', views.nesting_exception_view),
url(r'^django_project_redirect/$', views.django_project_redirect),
+ url(r'^two_arg_exception/$', views.two_arg_exception),
url(r'^accounts/$', RedirectView.as_view(url='login/')),
url(r'^accounts/no_trailing_slash$', RedirectView.as_view(url='login/')),
diff --git a/tests/test_client/views.py b/tests/test_client/views.py
index 41a5f8518b..3387008d66 100644
--- a/tests/test_client/views.py
+++ b/tests/test_client/views.py
@@ -331,3 +331,12 @@ def django_project_redirect(request):
def upload_view(request):
"""Prints keys of request.FILES to the response."""
return HttpResponse(', '.join(request.FILES))
+
+
+class TwoArgException(Exception):
+ def __init__(self, one, two):
+ pass
+
+
+def two_arg_exception(request):
+ raise TwoArgException('one', 'two')