1010"""
1111from __future__ import unicode_literals
1212
13+ import sys
14+ from contextlib import contextmanager
15+
1316from django .conf import settings
1417from django .http import QueryDict
1518from django .http .multipartparser import parse_header
@@ -59,6 +62,24 @@ def __exit__(self, *args, **kwarg):
5962 self .view .action = self .action
6063
6164
65+ class WrappedAttributeError (Exception ):
66+ pass
67+
68+
69+ @contextmanager
70+ def wrap_attributeerrors ():
71+ """
72+ Used to re-raise AttributeErrors caught during authentication, preventing
73+ these errors from otherwise being handled by the attribute access protocol.
74+ """
75+ try :
76+ yield
77+ except AttributeError :
78+ info = sys .exc_info ()
79+ exc = WrappedAttributeError (str (info [1 ]))
80+ six .reraise (type (exc ), exc , info [2 ])
81+
82+
6283class Empty (object ):
6384 """
6485 Placeholder for unset attributes.
@@ -191,7 +212,8 @@ def user(self):
191212 by the authentication classes provided to the request.
192213 """
193214 if not hasattr (self , '_user' ):
194- self ._authenticate ()
215+ with wrap_attributeerrors ():
216+ self ._authenticate ()
195217 return self ._user
196218
197219 @user .setter
@@ -214,7 +236,8 @@ def auth(self):
214236 request, such as an authentication token.
215237 """
216238 if not hasattr (self , '_auth' ):
217- self ._authenticate ()
239+ with wrap_attributeerrors ():
240+ self ._authenticate ()
218241 return self ._auth
219242
220243 @auth .setter
@@ -233,7 +256,8 @@ def successful_authenticator(self):
233256 to authenticate the request, or `None`.
234257 """
235258 if not hasattr (self , '_authenticator' ):
236- self ._authenticate ()
259+ with wrap_attributeerrors ():
260+ self ._authenticate ()
237261 return self ._authenticator
238262
239263 def _load_data_and_files (self ):
@@ -316,7 +340,7 @@ def _parse(self):
316340
317341 try :
318342 parsed = parser .parse (stream , media_type , self .parser_context )
319- except :
343+ except Exception :
320344 # If we get an exception during parsing, fill in empty data and
321345 # re-raise. Ensures we don't simply repeat the error when
322346 # attempting to render the browsable renderer response, or when
0 commit comments