Add derived/derived_dict_entry/derive_settings and tests.
- Enables a method of deriving Django settings from other Django settings after all other Django settings are stable.
This commit is contained in:
69
openedx/core/lib/derived.py
Normal file
69
openedx/core/lib/derived.py
Normal file
@@ -0,0 +1,69 @@
|
||||
"""
|
||||
Allows the registration of Django/Python settings that are derived from other settings
|
||||
via callable methods/lambdas. The derivation time can be controlled to happen after all
|
||||
other settings have been set. The derived setting can also be overridden by setting the
|
||||
derived setting to an actual value.
|
||||
"""
|
||||
import six
|
||||
import sys
|
||||
|
||||
# Global list holding all settings which will be derived.
|
||||
__DERIVED = []
|
||||
|
||||
|
||||
def derived(*settings):
|
||||
"""
|
||||
Registers settings which are derived from other settings.
|
||||
Can be called multiple times to add more derived settings.
|
||||
|
||||
Args:
|
||||
settings (list): List of setting names to register.
|
||||
"""
|
||||
__DERIVED.extend(settings)
|
||||
|
||||
|
||||
def derived_dict_entry(setting_dict, key):
|
||||
"""
|
||||
Registers a setting which is a dictionary and needs a derived value for a particular key.
|
||||
Can be called multiple times to add more derived settings.
|
||||
|
||||
Args:
|
||||
setting_dict (str): Name of setting which contains a dictionary.
|
||||
key (str): Name of key in the setting dictionary which will be derived.
|
||||
"""
|
||||
__DERIVED.append((setting_dict, key))
|
||||
|
||||
|
||||
def derive_settings(module_name):
|
||||
"""
|
||||
Derives all registered settings and sets them onto a particular module.
|
||||
Skips deriving settings that are set to a value.
|
||||
|
||||
Args:
|
||||
module_name (str): Name of module to which the derived settings will be added.
|
||||
"""
|
||||
module = sys.modules[module_name]
|
||||
for derived in __DERIVED:
|
||||
if isinstance(derived, six.string_types):
|
||||
setting = getattr(module, derived)
|
||||
if callable(setting):
|
||||
setting_val = setting(module)
|
||||
setattr(module, derived, setting_val)
|
||||
elif isinstance(derived, tuple):
|
||||
# If a tuple, two elements are expected - else ignore.
|
||||
if len(derived) == 2:
|
||||
# Both elements are expected to be strings.
|
||||
# The first string is the attribute which is expected to be a dictionary.
|
||||
# The second string is a key in that dictionary containing a derived setting.
|
||||
setting = getattr(module, derived[0])[derived[1]]
|
||||
if callable(setting):
|
||||
setting_val = setting(module)
|
||||
getattr(module, derived[0]).update({derived[1]: setting_val})
|
||||
|
||||
|
||||
def clear_for_tests():
|
||||
"""
|
||||
Clears all settings to be derived. For tests only.
|
||||
"""
|
||||
global __DERIVED
|
||||
__DERIVED = []
|
||||
44
openedx/core/lib/tests/test_derived.py
Normal file
44
openedx/core/lib/tests/test_derived.py
Normal file
@@ -0,0 +1,44 @@
|
||||
"""
|
||||
Tests for derived.py
|
||||
"""
|
||||
|
||||
import sys
|
||||
from unittest import TestCase
|
||||
from openedx.core.lib.derived import derived, derive_settings, clear_for_tests
|
||||
|
||||
|
||||
class TestDerivedSettings(TestCase):
|
||||
"""
|
||||
Test settings that are derived from other settings.
|
||||
"""
|
||||
def setUp(self):
|
||||
super(TestDerivedSettings, self).setUp()
|
||||
clear_for_tests()
|
||||
self.module = sys.modules[__name__]
|
||||
self.module.SIMPLE_VALUE = 'paneer'
|
||||
self.module.DERIVED_VALUE = lambda settings: 'mutter ' + settings.SIMPLE_VALUE
|
||||
self.module.ANOTHER_DERIVED_VALUE = lambda settings: settings.DERIVED_VALUE + ' with naan'
|
||||
self.module.UNREGISTERED_DERIVED_VALUE = lambda settings: settings.SIMPLE_VALUE + ' is cheese'
|
||||
derived('DERIVED_VALUE', 'ANOTHER_DERIVED_VALUE')
|
||||
self.module.DICT_VALUE = {}
|
||||
self.module.DICT_VALUE['test_key'] = lambda settings: settings.DERIVED_VALUE * 3
|
||||
derived(('DICT_VALUE', 'test_key'))
|
||||
|
||||
def test_derived_settings_are_derived(self):
|
||||
derive_settings(__name__)
|
||||
self.assertEqual(self.module.DERIVED_VALUE, 'mutter paneer')
|
||||
self.assertEqual(self.module.ANOTHER_DERIVED_VALUE, 'mutter paneer with naan')
|
||||
|
||||
def test_unregistered_derived_settings(self):
|
||||
derive_settings(__name__)
|
||||
self.assertTrue(callable(self.module.UNREGISTERED_DERIVED_VALUE))
|
||||
|
||||
def test_derived_settings_overridden(self):
|
||||
self.module.DERIVED_VALUE = 'aloo gobi'
|
||||
derive_settings(__name__)
|
||||
self.assertEqual(self.module.DERIVED_VALUE, 'aloo gobi')
|
||||
self.assertEqual(self.module.ANOTHER_DERIVED_VALUE, 'aloo gobi with naan')
|
||||
|
||||
def test_derived_dict_settings(self):
|
||||
derive_settings(__name__)
|
||||
self.assertEqual(self.module.DICT_VALUE['test_key'], 'mutter paneermutter paneermutter paneer')
|
||||
Reference in New Issue
Block a user