From c88fccd6ec09cb64ff3ee80e314734ed80dea482 Mon Sep 17 00:00:00 2001 From: Diego Garcia Date: Tue, 1 Oct 2019 18:45:01 -0300 Subject: [PATCH] Change import dynamic reader mechanism to simplify to custom dynamic readers --- README.rst | 39 ++++++++++++++++++ simple_settings/dynamic_settings/__init__.py | 40 +++++++++++++++---- .../dynamic_settings/test_dynamic_settings.py | 2 +- 3 files changed, 72 insertions(+), 9 deletions(-) diff --git a/README.rst b/README.rst index e97213e..cf2a972 100644 --- a/README.rst +++ b/README.rst @@ -541,6 +541,45 @@ the ``DYNAMIC_SETTINGS`` special setting with the ``memcached`` backend To install with memcached dependencies use: ``pip install simple-settings[memcached]`` +Custom +^^^^^^ +You can easily create your own dynamic settings reader. To do that you need to +create a class than inherit from ``simple_settings.dynamic_settings.base.BaseReader`` +and implement ``_get`` and ``_set`` methods, f.ex: + +.. code:: python + + from simple_settings.dynamic_settings.base import BaseReader + + + class Reader(BaseReader): + + def __init__(self, conf): + super(Reader, self).__init__(conf) + self._dict = {} + + def _get(self, key): + return self._dict.get(key) + + def _set(self, key, value): + self._dict[key] = value + +.. + +To use it, just configure ``SIMPLE_SETINGS`` special setting with the full path +of the reader, f.ex: + +.. code:: python + + 'SIMPLE_SETTINGS': { + 'DYNAMIC_SETTINGS': { + 'backend': 'path.of.module.ClassName' + } + } +.. + +Any other config of dynamic settings will be pass to reader backend on argument ``config`` + Utils ----- diff --git a/simple_settings/dynamic_settings/__init__.py b/simple_settings/dynamic_settings/__init__.py index 1bb458d..d610d42 100644 --- a/simple_settings/dynamic_settings/__init__.py +++ b/simple_settings/dynamic_settings/__init__.py @@ -7,14 +7,26 @@ ) DYNAMIC_SETTINGS_MAPPING = { - 'consul': 'simple_settings.dynamic_settings.consul_reader', - 'database': 'simple_settings.dynamic_settings.database_reader', - 'memcached': 'simple_settings.dynamic_settings.memcached_reader', - 'redis': 'simple_settings.dynamic_settings.redis_reader', - 's3': 'simple_settings.dynamic_settings.s3_reader' + 'consul': 'simple_settings.dynamic_settings.consul_reader.Reader', + 'database': 'simple_settings.dynamic_settings.database_reader.Reader', + 'memcached': 'simple_settings.dynamic_settings.memcached_reader.Reader', + 'redis': 'simple_settings.dynamic_settings.redis_reader.Reader', + 's3': 'simple_settings.dynamic_settings.s3_reader.Reader' } +class InvalidDynamicSettingsReaderPath(RuntimeError): + + def __init__(self, path): + super(InvalidDynamicSettingsReaderPath, self).__init__(self) + self.path = path + + def __str__(self): + return 'The path of dynamic settings reader [{}] are invalid'.format( + self.path + ) + + def get_dynamic_reader(settings_dict): dynamic_settings_conf = ( settings_dict.get(SPECIAL_SETTINGS_KEY, {}).get(DYNAMIC_SETTINGS_KEY) @@ -26,7 +38,19 @@ def get_dynamic_reader(settings_dict): if reader_backend in DYNAMIC_SETTINGS_MAPPING: reader_backend = DYNAMIC_SETTINGS_MAPPING[reader_backend] - reader_module = importlib.import_module(reader_backend) - reader = reader_module.Reader(dynamic_settings_conf) + reader_class = get_dynamic_reader_class(reader_backend) + return reader_class(dynamic_settings_conf) + + +def get_dynamic_reader_class(reader_backend_path): + try: + module_path, class_name = reader_backend_path.rsplit('.', 1) + except ValueError: + raise InvalidDynamicSettingsReaderPath(reader_backend_path) + + reader_module = importlib.import_module(module_path) - return reader + try: + return getattr(reader_module, class_name) + except AttributeError: + raise InvalidDynamicSettingsReaderPath(reader_backend_path) diff --git a/tests/dynamic_settings/test_dynamic_settings.py b/tests/dynamic_settings/test_dynamic_settings.py index 30ce7ad..b2e8065 100644 --- a/tests/dynamic_settings/test_dynamic_settings.py +++ b/tests/dynamic_settings/test_dynamic_settings.py @@ -25,7 +25,7 @@ class TestDynamicSettings(object): def settings_dict(self): return { 'SIMPLE_SETTINGS': { - 'DYNAMIC_SETTINGS': {'backend': __name__} + 'DYNAMIC_SETTINGS': {'backend': '{}.Reader'.format(__name__)} } }