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 from __future__ import unicode_literals
import sys
from django.conf import settings from django.conf import settings
from django.http import QueryDict from django.http import QueryDict
from django.http.multipartparser import parse_header from django.http.multipartparser import parse_header
@ -373,19 +371,15 @@ class Request(object):
else: else:
self.auth = None self.auth = None
def __getattribute__(self, attr): def __getattr__(self, attr):
""" """
If an attribute does not exist on this instance, then we also attempt If an attribute does not exist on this instance, then we also attempt
to proxy it to the underlying HttpRequest object. to proxy it to the underlying HttpRequest object.
""" """
try: try:
return super(Request, self).__getattribute__(attr) return getattr(self._request, attr)
except AttributeError: except AttributeError:
info = sys.exc_info() return self.__getattribute__(attr)
try:
return getattr(self._request, attr)
except AttributeError:
six.reraise(info[0], info[1], info[2].tb_next)
@property @property
def DATA(self): def DATA(self):

View File

@ -249,3 +249,26 @@ class TestSecure(TestCase):
def test_default_secure_true(self): def test_default_secure_true(self):
request = Request(factory.get('/', secure=True)) request = Request(factory.get('/', secure=True))
assert request.scheme == 'https' 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