diff --git a/rest_framework/exceptions.py b/rest_framework/exceptions.py index 1f381e4ef..710da96b8 100644 --- a/rest_framework/exceptions.py +++ b/rest_framework/exceptions.py @@ -145,3 +145,7 @@ class Throttled(APIException): self.detail += ' ' + force_text( self.extra_detail % {'wait': self.wait} ) + + +class RESTFrameworkSettingHasUnexpectedClassWarning(Warning): + pass diff --git a/rest_framework/settings.py b/rest_framework/settings.py index 33f848138..3396635d8 100644 --- a/rest_framework/settings.py +++ b/rest_framework/settings.py @@ -18,9 +18,11 @@ REST framework settings, checking for user settings first, then falling back to the defaults. """ from __future__ import unicode_literals +import warnings from django.conf import settings from django.utils import importlib, six from rest_framework import ISO_8601 +from rest_framework.exceptions import RESTFrameworkSettingHasUnexpectedClassWarning USER_SETTINGS = getattr(settings, 'REST_FRAMEWORK', None) @@ -187,6 +189,17 @@ class APISettings(object): except KeyError: # Fall back to defaults val = self.defaults[attr] + else: + expected_class = self.defaults[attr].__class__ + if val.__class__ != expected_class: + warnings.warn( + "The `{val}` setting has the class {val.__class__}, " + "but the expected class was {expected_class}".format( + **locals() + ), + RESTFrameworkSettingHasUnexpectedClassWarning, + stacklevel=3 + ) # Coerce import strings into classes if val and attr in self.import_strings: diff --git a/tests/test_settings.py b/tests/test_settings.py index f2ff4ca14..f5bde4b06 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -1,5 +1,8 @@ from __future__ import unicode_literals +import warnings from django.test import TestCase +from rest_framework.exceptions import \ + RESTFrameworkSettingHasUnexpectedClassWarning from rest_framework.settings import APISettings @@ -15,3 +18,20 @@ class TestSettings(TestCase): }) with self.assertRaises(ImportError): settings.DEFAULT_RENDERER_CLASSES + + def test_bad_setting_class_raises_warning(self): + """ + Make sure warnings are emitted when settings have an unexpected class. + """ + settings = APISettings({ + 'DEFAULT_RENDERER_CLASSES': 'rest_framework.renderers.JSONRenderer' + }) + + with warnings.catch_warnings(record=True) as w: + # Trigger a warning. + settings.DEFAULT_RENDERER_CLASSES + # Verify that a warning is thrown + assert len(w) == 1 + assert issubclass( + w[-1].category, RESTFrameworkSettingHasUnexpectedClassWarning + )