mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-03 20:10:10 +03:00
Re-raise/wrap auth attribute errors
This commit is contained in:
parent
0d5d11b277
commit
fba2a8ab0f
|
@ -10,6 +10,9 @@ The wrapped request then offers a richer API, in particular :
|
|||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import sys
|
||||
from contextlib import contextmanager
|
||||
|
||||
from django.conf import settings
|
||||
from django.http import QueryDict
|
||||
from django.http.multipartparser import parse_header
|
||||
|
@ -59,6 +62,24 @@ class override_method(object):
|
|||
self.view.action = self.action
|
||||
|
||||
|
||||
class WrappedAttributeError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
@contextmanager
|
||||
def wrap_attributeerrors():
|
||||
"""
|
||||
Used to re-raise AttributeErrors caught during authentication, preventing
|
||||
these errors from otherwise being handled by the attribute access protocol.
|
||||
"""
|
||||
try:
|
||||
yield
|
||||
except AttributeError:
|
||||
info = sys.exc_info()
|
||||
exc = WrappedAttributeError(str(info[1]))
|
||||
six.reraise(type(exc), exc, info[2])
|
||||
|
||||
|
||||
class Empty(object):
|
||||
"""
|
||||
Placeholder for unset attributes.
|
||||
|
@ -191,7 +212,8 @@ class Request(object):
|
|||
by the authentication classes provided to the request.
|
||||
"""
|
||||
if not hasattr(self, '_user'):
|
||||
self._authenticate()
|
||||
with wrap_attributeerrors():
|
||||
self._authenticate()
|
||||
return self._user
|
||||
|
||||
@user.setter
|
||||
|
@ -214,7 +236,8 @@ class Request(object):
|
|||
request, such as an authentication token.
|
||||
"""
|
||||
if not hasattr(self, '_auth'):
|
||||
self._authenticate()
|
||||
with wrap_attributeerrors():
|
||||
self._authenticate()
|
||||
return self._auth
|
||||
|
||||
@auth.setter
|
||||
|
@ -233,7 +256,8 @@ class Request(object):
|
|||
to authenticate the request, or `None`.
|
||||
"""
|
||||
if not hasattr(self, '_authenticator'):
|
||||
self._authenticate()
|
||||
with wrap_attributeerrors():
|
||||
self._authenticate()
|
||||
return self._authenticator
|
||||
|
||||
def _load_data_and_files(self):
|
||||
|
@ -316,7 +340,7 @@ class Request(object):
|
|||
|
||||
try:
|
||||
parsed = parser.parse(stream, media_type, self.parser_context)
|
||||
except:
|
||||
except Exception:
|
||||
# If we get an exception during parsing, fill in empty data and
|
||||
# re-raise. Ensures we don't simply repeat the error when
|
||||
# attempting to render the browsable renderer response, or when
|
||||
|
|
|
@ -19,7 +19,7 @@ from django.utils import six
|
|||
from rest_framework import status
|
||||
from rest_framework.authentication import SessionAuthentication
|
||||
from rest_framework.parsers import BaseParser, FormParser, MultiPartParser
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.request import Request, WrappedAttributeError
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.test import APIClient, APIRequestFactory
|
||||
from rest_framework.views import APIView
|
||||
|
@ -227,10 +227,10 @@ class TestUserSetter(TestCase):
|
|||
|
||||
# The DRF request object does not have a user and should run authenticators
|
||||
expected = r"no attribute 'MISSPELLED_NAME_THAT_DOESNT_EXIST'"
|
||||
with pytest.raises(AttributeError, match=expected):
|
||||
with pytest.raises(WrappedAttributeError, match=expected):
|
||||
request.user
|
||||
|
||||
with pytest.raises(AttributeError, match=expected):
|
||||
with pytest.raises(WrappedAttributeError, match=expected):
|
||||
login(request, self.user)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user