Skip to content

Commit 1a667f4

Browse files
Ryan P Kilbycarltongibson
Ryan P Kilby
authored andcommitted
Reimplement request attribute access w/ __getattr__ (#5617)
* Add tests for proxying WSGIRequest attributes in Request. * Add request attribute exception test * Reimplement request attribute access
1 parent ae88f5c commit 1a667f4

File tree

2 files changed

+26
-9
lines changed

2 files changed

+26
-9
lines changed

rest_framework/request.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
"""
1111
from __future__ import unicode_literals
1212

13-
import sys
14-
1513
from django.conf import settings
1614
from django.http import QueryDict
1715
from django.http.multipartparser import parse_header
@@ -373,19 +371,15 @@ def _not_authenticated(self):
373371
else:
374372
self.auth = None
375373

376-
def __getattribute__(self, attr):
374+
def __getattr__(self, attr):
377375
"""
378376
If an attribute does not exist on this instance, then we also attempt
379377
to proxy it to the underlying HttpRequest object.
380378
"""
381379
try:
382-
return super(Request, self).__getattribute__(attr)
380+
return getattr(self._request, attr)
383381
except AttributeError:
384-
info = sys.exc_info()
385-
try:
386-
return getattr(self._request, attr)
387-
except AttributeError:
388-
six.reraise(info[0], info[1], info[2].tb_next)
382+
return self.__getattribute__(attr)
389383

390384
@property
391385
def DATA(self):

tests/test_request.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,3 +249,26 @@ def test_default_secure_false(self):
249249
def test_default_secure_true(self):
250250
request = Request(factory.get('/', secure=True))
251251
assert request.scheme == 'https'
252+
253+
254+
class TestWSGIRequestProxy(TestCase):
255+
def test_attribute_access(self):
256+
wsgi_request = factory.get('/')
257+
request = Request(wsgi_request)
258+
259+
inner_sentinel = object()
260+
wsgi_request.inner_property = inner_sentinel
261+
assert request.inner_property is inner_sentinel
262+
263+
outer_sentinel = object()
264+
request.inner_property = outer_sentinel
265+
assert request.inner_property is outer_sentinel
266+
267+
def test_exception(self):
268+
# ensure the exception message is not for the underlying WSGIRequest
269+
wsgi_request = factory.get('/')
270+
request = Request(wsgi_request)
271+
272+
message = "'Request' object has no attribute 'inner_property'"
273+
with self.assertRaisesMessage(AttributeError, message):
274+
request.inner_property

0 commit comments

Comments
 (0)