From 36fe656b510ab49fbf93d2563bb41a40cdc037eb Mon Sep 17 00:00:00 2001 From: Adam Grant Date: Fri, 10 Oct 2014 18:19:44 -0700 Subject: [PATCH 1/2] Added test to simulate an error I had where an imported reference failed and the python property swallowed the exception raised in my authenticator. --- tests/test_request.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/test_request.py b/tests/test_request.py index 8ddaf0a70..3b72bd22d 100644 --- a/tests/test_request.py +++ b/tests/test_request.py @@ -333,6 +333,25 @@ class TestUserSetter(TestCase): login(self.request, self.user) self.assertEqual(self.request.user, self.user) + def test_calling_user_fails_when_exception_is_raised(self): + class AuthRaisesError(object): + def authenticate(self, request): + raise AttributeError('We should see this error!') + # import rest_framework + # rest_framework.MISSPELLED_NAME_THAT_DOESNT_EXIST + + self.request = Request(factory.get('/'), authenticators=(AuthRaisesError(),)) + SessionMiddleware().process_request(self.request) + + login(self.request, self.user) + error_seen = None + try: + self.request.user + except AttributeError as error: + error_seen = error + + self.assertEqual('We should see this error!', error_seen.message) + def test_user_can_logout(self): self.request.user = self.user self.assertFalse(self.request.user.is_anonymous()) From 75d755a8fc9b7fc2355f22dcf4e4ec59d05af1b7 Mon Sep 17 00:00:00 2001 From: Adam Grant Date: Wed, 5 Nov 2014 10:22:55 -0500 Subject: [PATCH 2/2] Add error handling for a raised AttributeError inside of a property call for "request.user". --- rest_framework/request.py | 5 ++++- tests/test_request.py | 19 +++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/rest_framework/request.py b/rest_framework/request.py index 275326614..84ac9183c 100644 --- a/rest_framework/request.py +++ b/rest_framework/request.py @@ -223,7 +223,10 @@ class Request(object): by the authentication classes provided to the request. """ if not hasattr(self, '_user'): - self._authenticate() + try: + self._authenticate() + except AttributeError as error: + raise RuntimeError("AttributeError: " + error.message) return self._user @user.setter diff --git a/tests/test_request.py b/tests/test_request.py index 3b72bd22d..75fc120db 100644 --- a/tests/test_request.py +++ b/tests/test_request.py @@ -333,24 +333,27 @@ class TestUserSetter(TestCase): login(self.request, self.user) self.assertEqual(self.request.user, self.user) - def test_calling_user_fails_when_exception_is_raised(self): - class AuthRaisesError(object): + def test_calling_user_fails_when_attribute_error_is_raised(self): + """ + This proves that when an AttributeError is raised inside of the request.user + property, that we can handle this and report the true, underlying error. + """ + class AuthRaisesAttributeError(object): def authenticate(self, request): - raise AttributeError('We should see this error!') - # import rest_framework - # rest_framework.MISSPELLED_NAME_THAT_DOESNT_EXIST + import rest_framework + rest_framework.MISSPELLED_NAME_THAT_DOESNT_EXIST - self.request = Request(factory.get('/'), authenticators=(AuthRaisesError(),)) + self.request = Request(factory.get('/'), authenticators=(AuthRaisesAttributeError(),)) SessionMiddleware().process_request(self.request) login(self.request, self.user) error_seen = None try: self.request.user - except AttributeError as error: + except RuntimeError as error: error_seen = error - self.assertEqual('We should see this error!', error_seen.message) + self.assertEqual("AttributeError: 'module' object has no attribute 'MISSPELLED_NAME_THAT_DOESNT_EXIST'", error_seen.message) def test_user_can_logout(self): self.request.user = self.user