emit a warning when a setting has an unexpected type

This commit is contained in:
Craig Blaszczyk 2014-12-29 13:15:54 +00:00
parent 88ea5d6bb0
commit eb04133bb9
2 changed files with 37 additions and 8 deletions

View File

@ -18,6 +18,7 @@ REST framework settings, checking for user settings first, then falling
back to the defaults. back to the defaults.
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
from collections import Iterable
import warnings import warnings
from django.conf import settings from django.conf import settings
from django.utils import importlib, six from django.utils import importlib, six
@ -190,13 +191,21 @@ class APISettings(object):
# Fall back to defaults # Fall back to defaults
val = self.defaults[attr] val = self.defaults[attr]
else: else:
expected_class = self.defaults[attr].__class__ # Verify that the user hasn't accidentally given a string instead
if val.__class__ != expected_class: # of an iterable, or vice-versa
default = self.defaults[attr]
if issubclass(val.__class__, Iterable) \
and (not issubclass(default.__class__, Iterable)
or isinstance(val, basestring)):
warnings.warn( warnings.warn(
"The `{val}` setting has the class {val.__class__}, " "The `{attr}` setting must be iterable".format(**locals()),
"but the expected class was {expected_class}".format( RESTFrameworkSettingHasUnexpectedClassWarning,
**locals() stacklevel=3
), )
elif isinstance(default, basestring) and not \
isinstance(val, basestring):
warnings.warn(
"The `{attr}` setting must be a string".format(**locals()),
RESTFrameworkSettingHasUnexpectedClassWarning, RESTFrameworkSettingHasUnexpectedClassWarning,
stacklevel=3 stacklevel=3
) )

View File

@ -19,9 +19,10 @@ class TestSettings(TestCase):
with self.assertRaises(ImportError): with self.assertRaises(ImportError):
settings.DEFAULT_RENDERER_CLASSES settings.DEFAULT_RENDERER_CLASSES
def test_bad_setting_class_raises_warning(self): def test_bad_iterable_setting_class_raises_warning(self):
""" """
Make sure warnings are emitted when settings have an unexpected class. Make sure warnings are emitted when settings which should be iterable
are not.
""" """
settings = APISettings({ settings = APISettings({
'DEFAULT_RENDERER_CLASSES': 'rest_framework.renderers.JSONRenderer' 'DEFAULT_RENDERER_CLASSES': 'rest_framework.renderers.JSONRenderer'
@ -35,3 +36,22 @@ class TestSettings(TestCase):
assert issubclass( assert issubclass(
w[-1].category, RESTFrameworkSettingHasUnexpectedClassWarning w[-1].category, RESTFrameworkSettingHasUnexpectedClassWarning
) )
def test_bad_string_setting_class_raises_warning(self):
"""
Make sure warnings are emitted when settings which should be strings are
not.
"""
settings = APISettings({
'DEFAULT_METADATA_CLASS': []
})
with warnings.catch_warnings(record=True) as w:
# Trigger a warning.
settings.DEFAULT_METADATA_CLASS
# Verify that a warning is thrown
assert len(w) == 1
assert issubclass(
w[-1].category, RESTFrameworkSettingHasUnexpectedClassWarning
)