Skip to content

Commit

Permalink
Reimplement request attribute access w/ __getattr__ (encode#5617)
Browse files Browse the repository at this point in the history
* Add tests for proxying WSGIRequest attributes in Request.

* Add request attribute exception test

* Reimplement request attribute access
  • Loading branch information
Ryan P Kilby authored and Pierre Chiquet committed Mar 24, 2020
1 parent 1ca6cd3 commit 9eeaf97
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 9 deletions.
12 changes: 3 additions & 9 deletions rest_framework/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
"""
from __future__ import unicode_literals

import sys

from django.conf import settings
from django.http import QueryDict
from django.http.multipartparser import parse_header
Expand Down Expand Up @@ -373,19 +371,15 @@ def _not_authenticated(self):
else:
self.auth = None

def __getattribute__(self, attr):
def __getattr__(self, attr):
"""
If an attribute does not exist on this instance, then we also attempt
to proxy it to the underlying HttpRequest object.
"""
try:
return super(Request, self).__getattribute__(attr)
return getattr(self._request, attr)
except AttributeError:
info = sys.exc_info()
try:
return getattr(self._request, attr)
except AttributeError:
six.reraise(info[0], info[1], info[2].tb_next)
return self.__getattribute__(attr)

@property
def DATA(self):
Expand Down
23 changes: 23 additions & 0 deletions tests/test_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,3 +249,26 @@ def test_default_secure_false(self):
def test_default_secure_true(self):
request = Request(factory.get('/', secure=True))
assert request.scheme == 'https'


class TestWSGIRequestProxy(TestCase):
def test_attribute_access(self):
wsgi_request = factory.get('/')
request = Request(wsgi_request)

inner_sentinel = object()
wsgi_request.inner_property = inner_sentinel
assert request.inner_property is inner_sentinel

outer_sentinel = object()
request.inner_property = outer_sentinel
assert request.inner_property is outer_sentinel

def test_exception(self):
# ensure the exception message is not for the underlying WSGIRequest
wsgi_request = factory.get('/')
request = Request(wsgi_request)

message = "'Request' object has no attribute 'inner_property'"
with self.assertRaisesMessage(AttributeError, message):
request.inner_property

0 comments on commit 9eeaf97

Please sign in to comment.