Skip to content

Commit b6084b1

Browse files
author
James Riley McHugh
committed
Removed safe property decorator
Signed-off-by: James Riley McHugh <mchugh_james@bah.com>
1 parent eb61fa5 commit b6084b1

File tree

2 files changed

+39
-30
lines changed

2 files changed

+39
-30
lines changed

rest_framework/request.py

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ def content_type(self):
211211
meta = self._request.META
212212
return meta.get('CONTENT_TYPE', meta.get('HTTP_CONTENT_TYPE', ''))
213213

214-
@safe_property
214+
@property
215215
def stream(self):
216216
"""
217217
Returns an object that may be used to stream the request content.
@@ -220,27 +220,29 @@ def stream(self):
220220
self._load_stream()
221221
return self._stream
222222

223-
@safe_property
223+
@property
224224
def query_params(self):
225225
"""
226226
More semantically correct name for request.GET.
227227
"""
228228
return self._request.GET
229229

230-
@safe_property
230+
@property
231231
def data(self):
232232
if not _hasattr(self, '_full_data'):
233-
self._load_data_and_files()
233+
with wrap_attributeerrors():
234+
self._load_data_and_files()
234235
return self._full_data
235236

236-
@safe_property
237+
@property
237238
def user(self):
238239
"""
239240
Returns the user associated with the current request, as authenticated
240241
by the authentication classes provided to the request.
241242
"""
242243
if not hasattr(self, '_user'):
243-
self._authenticate()
244+
with wrap_attributeerrors():
245+
self._authenticate()
244246
return self._user
245247

246248
@user.setter
@@ -256,14 +258,15 @@ def user(self, value):
256258
self._user = value
257259
self._request.user = value
258260

259-
@safe_property
261+
@property
260262
def auth(self):
261263
"""
262264
Returns any non-user authentication information associated with the
263265
request, such as an authentication token.
264266
"""
265267
if not hasattr(self, '_auth'):
266-
self._authenticate()
268+
with wrap_attributeerrors():
269+
self._authenticate()
267270
return self._auth
268271

269272
@auth.setter
@@ -275,14 +278,15 @@ def auth(self, value):
275278
self._auth = value
276279
self._request.auth = value
277280

278-
@safe_property
281+
@property
279282
def successful_authenticator(self):
280283
"""
281284
Return the instance of the authentication instance class that was used
282285
to authenticate the request, or `None`.
283286
"""
284287
if not hasattr(self, '_authenticator'):
285-
self._authenticate()
288+
with wrap_attributeerrors():
289+
self._authenticate()
286290
return self._authenticator
287291

288292
def _load_data_and_files(self):
@@ -432,22 +436,24 @@ def __getattr__(self, attr):
432436
except AttributeError:
433437
raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{attr}'")
434438

435-
@safe_property
439+
@property
436440
def POST(self):
437441
# Ensure that request.POST uses our request parsing.
438442
if not _hasattr(self, '_data'):
439-
self._load_data_and_files()
443+
with wrap_attributeerrors():
444+
self._load_data_and_files()
440445
if is_form_media_type(self.content_type):
441446
return self._data
442447
return QueryDict('', encoding=self._request._encoding)
443448

444-
@safe_property
449+
@property
445450
def FILES(self):
446451
# Leave this one alone for backwards compat with Django's request.FILES
447452
# Different from the other two cases, which are not valid property
448453
# names on the WSGIRequest class.
449454
if not _hasattr(self, '_files'):
450-
self._load_data_and_files()
455+
with wrap_attributeerrors():
456+
self._load_data_and_files()
451457
return self._files
452458

453459
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)