From 8e304e1adbb0f99f91a15ed3abd379104bba3b89 Mon Sep 17 00:00:00 2001 From: James McHugh Date: Wed, 17 Jul 2024 12:51:39 -0400 Subject: [PATCH] Fixed AttributeError raised by data property being silently ignored (#9455) Signed-off-by: James Riley McHugh Co-authored-by: James Riley McHugh --- rest_framework/request.py | 11 +++++++---- tests/test_request.py | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/rest_framework/request.py b/rest_framework/request.py index b29e64d16..1527e435b 100644 --- a/rest_framework/request.py +++ b/rest_framework/request.py @@ -217,7 +217,8 @@ class Request: @property def data(self): if not _hasattr(self, '_full_data'): - self._load_data_and_files() + with wrap_attributeerrors(): + self._load_data_and_files() return self._full_data @property @@ -420,13 +421,14 @@ class Request: _request = self.__getattribute__("_request") return getattr(_request, attr) except AttributeError: - return self.__getattribute__(attr) + raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{attr}'") @property def POST(self): # Ensure that request.POST uses our request parsing. if not _hasattr(self, '_data'): - self._load_data_and_files() + with wrap_attributeerrors(): + self._load_data_and_files() if is_form_media_type(self.content_type): return self._data return QueryDict('', encoding=self._request._encoding) @@ -437,7 +439,8 @@ class Request: # Different from the other two cases, which are not valid property # names on the WSGIRequest class. if not _hasattr(self, '_files'): - self._load_data_and_files() + with wrap_attributeerrors(): + self._load_data_and_files() return self._files def force_plaintext_errors(self, value): diff --git a/tests/test_request.py b/tests/test_request.py index e37aa7dda..4263f2682 100644 --- a/tests/test_request.py +++ b/tests/test_request.py @@ -126,6 +126,25 @@ class TestContentParsing(TestCase): request.parsers = (PlainTextParser(), ) assert request.data == content + def test_calling_data_fails_when_attribute_error_is_raised(self): + """ + Ensure attribute errors raised when parsing are properly re-raised. + """ + expected_message = "Internal error" + + class BrokenParser: + media_type = "application/json" + + def parse(self, *args, **kwargs): + raise AttributeError(expected_message) + + http_request = factory.post('/', data={}, format="json") + request = Request(http_request) + request.parsers = (BrokenParser,) + + with self.assertRaisesMessage(WrappedAttributeError, expected_message): + request.data + class MockView(APIView): authentication_classes = (SessionAuthentication,)