Reimplement request attribute access w/ __getattr__ (#5617)

* Add tests for proxying WSGIRequest attributes in Request.

* Add request attribute exception test

* Reimplement request attribute access
This commit is contained in:
Ryan P Kilby 2017-11-22 05:42:59 -05:00 committed by Carlton Gibson
parent ae88f5c55b
commit 1a667f420d
2 changed files with 26 additions and 9 deletions

View File

@ -10,8 +10,6 @@ The wrapped request then offers a richer API, in particular :
"""
from __future__ import unicode_literals
import sys
from django.conf import settings
from django.http import QueryDict
from django.http.multipartparser import parse_header
@ -373,19 +371,15 @@ class Request(object):
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)
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):

View File

@ -249,3 +249,26 @@ class TestSecure(TestCase):
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