This commit is contained in:
Craig Blaszczyk 2015-01-26 14:38:09 +00:00
commit 4acde7f499
2 changed files with 71 additions and 0 deletions

View File

@ -18,6 +18,8 @@ REST framework settings, checking for user settings first, then falling
back to the defaults.
"""
from __future__ import unicode_literals
from collections import Iterable
from django.core.exceptions import ImproperlyConfigured
from django.conf import settings
from django.utils import importlib, six
from rest_framework import ISO_8601
@ -187,6 +189,29 @@ class APISettings(object):
except KeyError:
# Fall back to defaults
val = self.defaults[attr]
else:
# Verify that the user hasn't accidentally given a string instead
# of an iterable, or vice-versa
default = self.defaults[attr]
if issubclass(val.__class__, Iterable) \
and (not issubclass(default.__class__, Iterable)
or isinstance(val, six.string_types)):
raise ImproperlyConfigured(
'The "{settings_key}" setting must be a list or tuple, but '
'got type "{type_name}" with value "{value}".'.format(
settings_key=attr, type_name=val.__class__.__name__,
value=val
)
)
elif isinstance(default, six.string_types) and not \
isinstance(val, six.string_types):
raise ImproperlyConfigured(
'The "{settings_key}" setting must be a string, but '
'got type "{type_name}" with value "{value}".'.format(
settings_key=attr, type_name=val.__class__.__name__,
value=val
)
)
# Coerce import strings into classes
if val and attr in self.import_strings:

View File

@ -1,5 +1,8 @@
from __future__ import unicode_literals
from django.core.exceptions import ImproperlyConfigured
import pytest
from django.test import TestCase
from django.utils import six
from rest_framework.settings import APISettings
@ -15,3 +18,46 @@ class TestSettings(TestCase):
})
with self.assertRaises(ImportError):
settings.DEFAULT_RENDERER_CLASSES
def test_bad_iterable_setting_class_raises_warning(self):
"""
Make sure errors are raised when settings which should be iterable are
not.
"""
settings = APISettings({
'DEFAULT_RENDERER_CLASSES': 'rest_framework.renderers.JSONRenderer'
})
# Trigger the exception
with pytest.raises(ImproperlyConfigured) as exc_info:
settings.DEFAULT_RENDERER_CLASSES
# Construct the expected error message
text_type_name = str(six.text_type.__name__)
expected_error = (
'The "DEFAULT_RENDERER_CLASSES" setting must be a list or '
'tuple, but got type "{text_type_name}" with value '
'"rest_framework.renderers.JSONRenderer".'.format(
text_type_name=text_type_name
)
)
assert exc_info.value.args[0] == expected_error
def test_bad_string_setting_class_raises_warning(self):
"""
Make sure errors are raised when settings which should be strings are
not.
"""
settings = APISettings({
'DEFAULT_METADATA_CLASS': []
})
# Trigger the exception
with pytest.raises(ImproperlyConfigured) as exc_info:
settings.DEFAULT_METADATA_CLASS
expected_error = (
'The "DEFAULT_METADATA_CLASS" setting must be a string, but got '
'type "list" with value "[]".'
)
assert exc_info.value.args[0] == expected_error