@@ -78,19 +78,6 @@ def wrap_attributeerrors():
7878 raise exc .with_traceback (info [2 ])
7979
8080
81- def safe_property (func ):
82- """
83- Property decorator to ensure AttributeErrors raised in properties aren't lost
84- """
85-
86- @property
87- def new_func (self ):
88- with wrap_attributeerrors ():
89- return func (self )
90-
91- return new_func
92-
93-
9481class Empty :
9582 """
9683 Placeholder for unset attributes.
@@ -206,12 +193,12 @@ def __class_getitem__(cls, *args, **kwargs):
206193 def _default_negotiator (self ):
207194 return api_settings .DEFAULT_CONTENT_NEGOTIATION_CLASS ()
208195
209- @safe_property
196+ @property
210197 def content_type (self ):
211198 meta = self ._request .META
212199 return meta .get ('CONTENT_TYPE' , meta .get ('HTTP_CONTENT_TYPE' , '' ))
213200
214- @safe_property
201+ @property
215202 def stream (self ):
216203 """
217204 Returns an object that may be used to stream the request content.
@@ -220,27 +207,29 @@ def stream(self):
220207 self ._load_stream ()
221208 return self ._stream
222209
223- @safe_property
210+ @property
224211 def query_params (self ):
225212 """
226213 More semantically correct name for request.GET.
227214 """
228215 return self ._request .GET
229216
230- @safe_property
217+ @property
231218 def data (self ):
232219 if not _hasattr (self , '_full_data' ):
233- self ._load_data_and_files ()
220+ with wrap_attributeerrors ():
221+ self ._load_data_and_files ()
234222 return self ._full_data
235223
236- @safe_property
224+ @property
237225 def user (self ):
238226 """
239227 Returns the user associated with the current request, as authenticated
240228 by the authentication classes provided to the request.
241229 """
242230 if not hasattr (self , '_user' ):
243- self ._authenticate ()
231+ with wrap_attributeerrors ():
232+ self ._authenticate ()
244233 return self ._user
245234
246235 @user .setter
@@ -256,14 +245,15 @@ def user(self, value):
256245 self ._user = value
257246 self ._request .user = value
258247
259- @safe_property
248+ @property
260249 def auth (self ):
261250 """
262251 Returns any non-user authentication information associated with the
263252 request, such as an authentication token.
264253 """
265254 if not hasattr (self , '_auth' ):
266- self ._authenticate ()
255+ with wrap_attributeerrors ():
256+ self ._authenticate ()
267257 return self ._auth
268258
269259 @auth .setter
@@ -275,14 +265,15 @@ def auth(self, value):
275265 self ._auth = value
276266 self ._request .auth = value
277267
278- @safe_property
268+ @property
279269 def successful_authenticator (self ):
280270 """
281271 Return the instance of the authentication instance class that was used
282272 to authenticate the request, or `None`.
283273 """
284274 if not hasattr (self , '_authenticator' ):
285- self ._authenticate ()
275+ with wrap_attributeerrors ():
276+ self ._authenticate ()
286277 return self ._authenticator
287278
288279 def _load_data_and_files (self ):
@@ -432,22 +423,24 @@ def __getattr__(self, attr):
432423 except AttributeError :
433424 raise AttributeError (f"'{ self .__class__ .__name__ } ' object has no attribute '{ attr } '" )
434425
435- @safe_property
426+ @property
436427 def POST (self ):
437428 # Ensure that request.POST uses our request parsing.
438429 if not _hasattr (self , '_data' ):
439- self ._load_data_and_files ()
430+ with wrap_attributeerrors ():
431+ self ._load_data_and_files ()
440432 if is_form_media_type (self .content_type ):
441433 return self ._data
442434 return QueryDict ('' , encoding = self ._request ._encoding )
443435
444- @safe_property
436+ @property
445437 def FILES (self ):
446438 # Leave this one alone for backwards compat with Django's request.FILES
447439 # Different from the other two cases, which are not valid property
448440 # names on the WSGIRequest class.
449441 if not _hasattr (self , '_files' ):
450- self ._load_data_and_files ()
442+ with wrap_attributeerrors ():
443+ self ._load_data_and_files ()
451444 return self ._files
452445
453446 def force_plaintext_errors (self , value ):
0 commit comments