From caa6dc0341fd6cae920f1dab85269e849d783bd2 Mon Sep 17 00:00:00 2001 From: p1c2u Date: Sat, 15 Sep 2018 17:02:34 +0100 Subject: [PATCH] config interface with env config --- kore/components/base.py | 18 +++++ kore/components/plugins/base.py | 20 +----- kore/components/registrars.py | 2 +- kore/configs/base.py | 27 +++++++ kore/configs/dict.py | 9 +++ kore/configs/env.py | 71 ++++++++++++++++++ kore/configs/models.py | 10 --- kore/configs/plugins/base.py | 19 +---- kore/configs/plugins/dict.py | 9 --- setup.py | 3 +- tests/integration/conftest.py | 4 +- tests/integration/test_env_config.py | 72 +++++++++++++++++++ .../configs/{test_models.py => test_base.py} | 2 +- 13 files changed, 209 insertions(+), 57 deletions(-) create mode 100644 kore/components/base.py create mode 100644 kore/configs/base.py create mode 100644 kore/configs/dict.py create mode 100644 kore/configs/env.py delete mode 100644 kore/configs/models.py delete mode 100644 kore/configs/plugins/dict.py create mode 100644 tests/integration/test_env_config.py rename tests/unit/configs/{test_models.py => test_base.py} (95%) diff --git a/kore/components/base.py b/kore/components/base.py new file mode 100644 index 0000000..410721e --- /dev/null +++ b/kore/components/base.py @@ -0,0 +1,18 @@ +import logging + +log = logging.getLogger(__name__) + + +class BaseComponent(object): + + factories = () + services = () + + def __init__(self, namespace=None): + self.namespace = namespace + + def get_factories(self): + return self.factories + + def get_services(self): + return self.services diff --git a/kore/components/plugins/base.py b/kore/components/plugins/base.py index 5eacea8..b8b39a9 100644 --- a/kore/components/plugins/base.py +++ b/kore/components/plugins/base.py @@ -1,18 +1,4 @@ -import logging +# backward compatibility +from kore.components.base import BaseComponent as BasePluginComponent -log = logging.getLogger(__name__) - - -class BasePluginComponent(object): - - factories = () - services = () - - def __init__(self, namespace=None): - self.namespace = namespace - - def get_factories(self): - return self.factories - - def get_services(self): - return self.services +__all__ = ['BasePluginComponent', ] diff --git a/kore/components/registrars.py b/kore/components/registrars.py index 187af41..481879d 100644 --- a/kore/components/registrars.py +++ b/kore/components/registrars.py @@ -40,7 +40,7 @@ def bind(self, container): if hasattr(component, 'post_hook'): warnings.warn( "post_hook method is deprecated. " - "Use container_prepared signal instead.", + "Use post_register signal instead.", DeprecationWarning, ) component.post_hook(container) diff --git a/kore/configs/base.py b/kore/configs/base.py new file mode 100644 index 0000000..bf42bcc --- /dev/null +++ b/kore/configs/base.py @@ -0,0 +1,27 @@ +class BaseConfigSection(object): + + @property + def __dict__(self, key): + raise NotImplementedError + + def __iter__(self): + raise NotImplementedError + + def __getitem__(self, key): + raise NotImplementedError + + def keys(self): + raise NotImplementedError + + def get(self, key, default=None): + try: + return self[key] + except KeyError: + return default + + def get_section(self, name): + raise NotImplementedError + + +class BaseConfig(BaseConfigSection): + pass diff --git a/kore/configs/dict.py b/kore/configs/dict.py new file mode 100644 index 0000000..735bd94 --- /dev/null +++ b/kore/configs/dict.py @@ -0,0 +1,9 @@ +from collections import defaultdict + +from kore.configs.base import BaseConfig + + +class DictConfig(defaultdict, BaseConfig): + + def __missing__(self, key): + return defaultdict() diff --git a/kore/configs/env.py b/kore/configs/env.py new file mode 100644 index 0000000..1fd9e0a --- /dev/null +++ b/kore/configs/env.py @@ -0,0 +1,71 @@ +import os + +from six import iteritems +from kore.configs.base import BaseConfigSection, BaseConfig + + +class BaseEnv(object): + + prefix = NotImplemented + + def __iter__(self): + for key in self._iter_envvars(): + yield key.replace(self.prefix, "").lower() + + def __getitem__(self, key): + envvar = self._get_envvar(key) + return os.environ[envvar] + + @property + def __dict__(self): + data = {} + for key in self._iter_envvars(): + subkey = key.replace(self.prefix, "").lower() + data[subkey] = os.environ[key] + return data + + def get(self, key, default=None): + envvar = self._get_envvar(key) + try: + return os.environ[envvar] + except KeyError: + return default + + def keys(self): + return list(self) + + def _get_envvar(self, key): + return ''.join([self.prefix, key]).upper() + + def _iter_envvars(self): + for key, value in iteritems(os.environ): + if key.startswith(self.prefix): + yield key + + +class EnvSection(BaseEnv, BaseConfigSection): + + separator = '_' + + def __init__(self, name): + self.name = name + + @property + def prefix(self): + return ''.join([self.name, self.separator]) + + def get_section(self, name): + envvar = self._get_envvar(name) + return EnvSection(envvar) + + +class EnvConfig(BaseEnv, BaseConfig): + + def __init__(self, *args, **kwargs): + prefix = kwargs.get('env_prefix', '') + + self.prefix = prefix + + def get_section(self, name): + envvar = self._get_envvar(name) + return EnvSection(envvar) diff --git a/kore/configs/models.py b/kore/configs/models.py deleted file mode 100644 index d2439e3..0000000 --- a/kore/configs/models.py +++ /dev/null @@ -1,10 +0,0 @@ -class BaseConfig(object): - - def __getitem__(self, key): - raise NotImplementedError - - def get(self, key, default=None): - try: - return self[key] - except KeyError: - return default diff --git a/kore/configs/plugins/base.py b/kore/configs/plugins/base.py index bd3767d..a442b43 100644 --- a/kore/configs/plugins/base.py +++ b/kore/configs/plugins/base.py @@ -1,17 +1,4 @@ -import logging +# backeward compativility +from kore.configs.base import BaseConfig as BasePluginConfig -from kore.configs.models import BaseConfig - -log = logging.getLogger(__name__) - - -class BasePluginConfig(BaseConfig): - - def __getitem__(self, key): - raise NotImplementedError - - def get(self, key, default=None): - try: - return self[key] - except KeyError: - return default +__all__ = ['BasePluginConfig', ] diff --git a/kore/configs/plugins/dict.py b/kore/configs/plugins/dict.py deleted file mode 100644 index ef83f42..0000000 --- a/kore/configs/plugins/dict.py +++ /dev/null @@ -1,9 +0,0 @@ -from collections import defaultdict - -from kore.configs.plugins.base import BasePluginConfig - - -class DictConfig(defaultdict, BasePluginConfig): - - def __missing__(self, key): - return defaultdict() diff --git a/setup.py b/setup.py index 1fd4009..4924bd4 100644 --- a/setup.py +++ b/setup.py @@ -53,7 +53,8 @@ def run_tests(self): entry_points = """\ [kore.configs] -dict = kore.configs.plugins.dict:DictConfig +dict = kore.configs.dict:DictConfig +env = kore.configs.env:EnvConfig """ diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 36f9fc2..0a681d7 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -4,8 +4,8 @@ from kore.components.factories import ComponentFactory from kore.components.plugins.base import BasePluginComponent -from kore.configs.models import BaseConfig -from kore.configs.plugins.dict import DictConfig +from kore.configs.base import BaseConfig +from kore.configs.dict import DictConfig from kore.containers.factories import ContainerFactory from kore.plugins.models import Plugin from kore.plugins.providers import PluginsProvider diff --git a/tests/integration/test_env_config.py b/tests/integration/test_env_config.py new file mode 100644 index 0000000..9690a5b --- /dev/null +++ b/tests/integration/test_env_config.py @@ -0,0 +1,72 @@ +from kore import config_factory + +from kore.configs.env import EnvSection + + +class TestEnvConfig(object): + + def test_get_section(self): + config_type = 'env' + config_opt = { + 'bar': 'baz', + } + + config = config_factory.create(config_type, **config_opt) + + result = config.get_section('UNDEFINED') + + assert result.__class__ is EnvSection + + def test_get_section_default_value(self): + config_type = 'env' + config_opt = { + 'bar': 'baz', + } + + config = config_factory.create(config_type, **config_opt) + + section = config.get_section('UNDEFINED') + + result = section.get('UNDEFINED', 'undefined') + + assert result == 'undefined' + + def test_section_option(self, monkeypatch): + monkeypatch.setenv('TESTING_KEY', 'value') + config_type = 'env' + config_opt = { + 'bar': 'baz', + } + config = config_factory.create(config_type, **config_opt) + section = config.get_section('TESTING') + + result = section['key'] + + assert result == 'value' + + def test_section_option_upper(self, monkeypatch): + monkeypatch.setenv('TESTING_KEY', 'value') + config_type = 'env' + config_opt = { + 'bar': 'baz', + } + config = config_factory.create(config_type, **config_opt) + section = config.get_section('TESTING') + + result = dict(section) + + assert result == { + 'key': 'value', + } + + def test_get_value(self, monkeypatch): + monkeypatch.setenv('TESTING_KEY', 'value') + config_type = 'env' + config_opt = { + 'bar': 'baz', + } + config = config_factory.create(config_type, **config_opt) + + result = config.get('key2', 'undefined') + + assert result == 'undefined' diff --git a/tests/unit/configs/test_models.py b/tests/unit/configs/test_base.py similarity index 95% rename from tests/unit/configs/test_models.py rename to tests/unit/configs/test_base.py index 4f6a3b8..59af914 100644 --- a/tests/unit/configs/test_models.py +++ b/tests/unit/configs/test_base.py @@ -1,7 +1,7 @@ import mock import pytest -from kore.configs.models import BaseConfig +from kore.configs.base import BaseConfig class TestBaseConfigGet(object):