From 746caf3ef821dbf7588797cb2600fa81b9df9d1d Mon Sep 17 00:00:00 2001 From: Nicolas Delaby Date: Thu, 23 Nov 2017 17:18:03 +0100 Subject: [PATCH] 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. --- django/db/models/query.py | 6 ++---- django/test/client.py | 4 ++-- django/utils/autoreload.py | 2 +- tests/test_client/tests.py | 7 ++++++- tests/test_client/urls.py | 1 + tests/test_client/views.py | 9 +++++++++ 6 files changed, 21 insertions(+), 8 deletions(-) diff --git a/django/db/models/query.py b/django/db/models/query.py index c1d57e4c615f..17dfa6d1363e 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -4,7 +4,6 @@ import copy import operator -import sys import warnings from collections import OrderedDict, namedtuple from functools import lru_cache @@ -521,13 +520,12 @@ def _create_object_from_params(self, lookup, params): 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 d47cb087b85e..6406f8309e7e 100644 --- a/django/test/client.py +++ b/django/test/client.py @@ -480,9 +480,9 @@ def request(self, **request): # 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 d3124e875113..ec144c5a175e 100644 --- a/django/utils/autoreload.py +++ b/django/utils/autoreload.py @@ -245,7 +245,7 @@ def wrapper(*args, **kwargs): 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 5981ca319e0b..f7d32aa9cd3d 100644 --- a/tests/test_client/tests.py +++ b/tests/test_client/tests.py @@ -29,7 +29,7 @@ ) 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 @@ def test_exception_following_nested_client_request(self): 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 9f8d09218e78..40ca3847518b 100644 --- a/tests/test_client/urls.py +++ b/tests/test_client/urls.py @@ -34,6 +34,7 @@ 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 41a5f8518bb3..3387008d66f0 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')