Skip to content

Commit fca7e6b

Browse files
author
James Riley McHugh
committed
Removed safe property decorator
Signed-off-by: James Riley McHugh <[email protected]>
1 parent eb61fa5 commit fca7e6b

File tree

2 files changed

+40
-44
lines changed

2 files changed

+40
-44
lines changed

rest_framework/request.py

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
9481
class 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):

tests/test_request.py

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,25 @@ def test_standard_behaviour_determines_non_form_content_PUT(self):
126126
request.parsers = (PlainTextParser(), )
127127
assert request.data == content
128128

129+
def test_calling_data_fails_when_attribute_error_is_raised(self):
130+
"""
131+
Ensure attribute errors raised when parsing are properly re-raised.
132+
"""
133+
expected_message = "Internal error"
134+
135+
class BrokenParser:
136+
media_type = "application/json"
137+
138+
def parse(self, *args, **kwargs):
139+
raise AttributeError(expected_message)
140+
141+
http_request = factory.post('/', data={}, format="json")
142+
request = Request(http_request)
143+
request.parsers = (BrokenParser,)
144+
145+
with self.assertRaisesMessage(WrappedAttributeError, expected_message):
146+
request.data
147+
129148

130149
class MockView(APIView):
131150
authentication_classes = (SessionAuthentication,)
@@ -347,22 +366,6 @@ def test_duplicate_request_form_data_access(self):
347366
assert request.content_type.startswith('multipart/form-data')
348367
assert response.data == {'a': ['b']}
349368

350-
def test_parser_attribute_error(self):
351-
"""Ensure attribute errors raised when parsing are properly re-raised"""
352-
expected_message = "Internal error"
353-
354-
class BrokenParser:
355-
media_type = "application/json"
356-
357-
def parse(self, *args, **kwargs):
358-
raise AttributeError(expected_message)
359-
360-
http_request = factory.post('/', data={}, format="json")
361-
request = Request(http_request, parsers=[BrokenParser()])
362-
363-
with self.assertRaisesMessage(WrappedAttributeError, expected_message):
364-
request.data
365-
366369

367370
class TestDeepcopy(TestCase):
368371

0 commit comments

Comments
 (0)