diff --git a/django/conf/__init__.py b/django/conf/__init__.py index 608ad256dc..3337fd6f13 100644 --- a/django/conf/__init__.py +++ b/django/conf/__init__.py @@ -104,6 +104,8 @@ class LazySettings(LazyObject): raise RuntimeError('Settings already configured.') holder = UserSettingsHolder(default_settings) for name, value in options.items(): + if not name.isupper(): + raise TypeError('Setting %r must be uppercase.' % name) setattr(holder, name, value) self._wrapped = holder @@ -198,7 +200,7 @@ class UserSettingsHolder: self.default_settings = default_settings def __getattr__(self, name): - if name in self._deleted: + if not name.isupper() or name in self._deleted: raise AttributeError return getattr(self.default_settings, name) diff --git a/tests/settings_tests/tests.py b/tests/settings_tests/tests.py index bfd580b600..280f46f2aa 100644 --- a/tests/settings_tests/tests.py +++ b/tests/settings_tests/tests.py @@ -1,7 +1,7 @@ import os import sys import unittest -from types import ModuleType +from types import ModuleType, SimpleNamespace from unittest import mock from django.conf import ENVIRONMENT_VARIABLE, LazySettings, Settings, settings @@ -318,6 +318,17 @@ class SettingsTests(SimpleTestCase): with self.assertRaisesMessage(RuntimeError, 'Settings already configured.'): settings.configure() + def test_nonupper_settings_prohibited_in_configure(self): + s = LazySettings() + with self.assertRaisesMessage(TypeError, "Setting 'foo' must be uppercase."): + s.configure(foo='bar') + + def test_nonupper_settings_ignored_in_default_settings(self): + s = LazySettings() + s.configure(SimpleNamespace(foo='bar')) + with self.assertRaises(AttributeError): + getattr(s, 'foo') + @requires_tz_support @mock.patch('django.conf.global_settings.TIME_ZONE', 'test') def test_incorrect_timezone(self):