diff --git a/.gitignore b/.gitignore index 2c8afb9..b7696c1 100644 --- a/.gitignore +++ b/.gitignore @@ -58,16 +58,6 @@ cover/ *.mo *.pot -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - # Scrapy stuff: .scrapy @@ -81,61 +71,6 @@ target/ # Jupyter Notebook .ipynb_checkpoints -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock # PEP 582; used by e.g. github.com/David-OConnor/pyflow __pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ diff --git a/configerus/contrib/dict/__init__.py b/configerus/contrib/dict/__init__.py index 49250a6..3f82732 100644 --- a/configerus/contrib/dict/__init__.py +++ b/configerus/contrib/dict/__init__.py @@ -12,6 +12,7 @@ CONFIGERUS_DICT_DATA_KEY = 'data' """ if you load paths from config, this is the key that should give the path """ + @SourceFactory(plugin_id=PLUGIN_ID_SOURCE_DICT) def plugin_factory_configsource_dict(config: Config, instance_id: str = ''): """ create an configsource dict plugin """ diff --git a/configerus/contrib/dict/source.py b/configerus/contrib/dict/source.py index cf203fd..91b2ffa 100644 --- a/configerus/contrib/dict/source.py +++ b/configerus/contrib/dict/source.py @@ -3,6 +3,7 @@ from configerus.config import Config + class ConfigSourceDictPlugin(): """ """ diff --git a/configerus/contrib/env/README.md b/configerus/contrib/env/README.md new file mode 100644 index 0000000..9a67c03 --- /dev/null +++ b/configerus/contrib/env/README.md @@ -0,0 +1 @@ +# Environment interactions diff --git a/configerus/contrib/env/__init__.py b/configerus/contrib/env/__init__.py new file mode 100644 index 0000000..39cc0b3 --- /dev/null +++ b/configerus/contrib/env/__init__.py @@ -0,0 +1,27 @@ +import logging + +from configerus.config import Config +from configerus.plugin import SourceFactory + +from .source import ConfigSourceEnvPlugin + +PLUGIN_ID_SOURCE_ENV = 'env' +""" ConfigSource plugin_id for the configerus env configsource plugin """ +CONFIGERUS_ENV_BASE_KEY = 'base' +""" Config key for retrieving an env plugin base value from config """ + + +@SourceFactory(plugin_id=PLUGIN_ID_SOURCE_ENV) +def plugin_factory_configsource_env(config: Config, instance_id: str = ''): + """ create an configsource env plugin """ + return ConfigSourceEnvPlugin(config, instance_id) + + +def configerus_bootstrap(config: Config): + """ Bootstrap a config object + + We don't actually do anything, so this bootstrapper is here only to ensure + that the above factory decorator is run + + """ + pass diff --git a/configerus/contrib/env/source.py b/configerus/contrib/env/source.py new file mode 100644 index 0000000..57a19c3 --- /dev/null +++ b/configerus/contrib/env/source.py @@ -0,0 +1,71 @@ +from typing import Dict, Any +import logging +import os + +from configerus.config import Config + +logger = logging.getLogger('configerus.contrib.env.source') + + +class ConfigSourceEnvPlugin(): + """ Get config from ENV variables + + if a base is provided, it is used as a root for all ENV variables + as "{base}_" + + string case for keys is a weird topic. We .lower() all keys as it seems a + decent convention. + + """ + + def __init__(self, config: Config, instance_id: str): + """ """ + self.config = config + self.instance_id = instance_id + + self.base = '' + """ keep the ENV base prefix that should limit what gets pulled in """ + + def set_base(self, base: str): + self.base = base + + def load(self, label: str): + """ Load a config label and return a Dict[str, Any] of config data + + Parameters: + + label (str) : label to load + + """ + + if self.base: + label_prefix = '{}_{}_'.format(self.base, label).upper() + else: + label_prefix = '{}_'.format(label).upper() + + filtered = {} + for env_key, env_value in os.environ.items(): + if env_key.upper().startswith(label_prefix): + filtered[env_key[len(label_prefix):].lower()] = env_value + + organized = {} + for (key, value) in filtered.items(): + if key.startswith('_'): + continue + + base = organized + key_steps = key.lower().split('_') + + last_step = key_steps.pop() + + for key_step in key_steps: + if not isinstance(base, dict): + base = {} + if not key_step in base: + base[key_step] = {} + base = base[key_step] + if not isinstance(base, dict): + base = {} + base[last_step] = value + + return organized diff --git a/configerus/contrib/files/__init__.py b/configerus/contrib/files/__init__.py index 60d1870..f671035 100644 --- a/configerus/contrib/files/__init__.py +++ b/configerus/contrib/files/__init__.py @@ -19,7 +19,7 @@ def plugin_factory_configsource_path(config: Config, instance_id: str = ''): return ConfigSourcePathPlugin(config, instance_id) -PLUGIN_ID_FORMAT_FILE = 'file' +PLUGIN_ID_FORMAT_FILE = 'configerus.plugin.formatter.file' """ Format plugin_id for the configerus filepath format plugin """ diff --git a/configerus/contrib/jsonschema/validate.py b/configerus/contrib/jsonschema/validate.py index 604b723..f717037 100644 --- a/configerus/contrib/jsonschema/validate.py +++ b/configerus/contrib/jsonschema/validate.py @@ -55,7 +55,9 @@ def validate(self, validate_target: Any, data): schema = schema_config.get(validate_key, exception_if_missing=True) except Exception as e: - raise NotImplementedError("Could not access jsonschema validation schema from config target '{}:{}'".format(PLUGIN_ID_VALIDATE_JSONSCHEMA_SCHEMA_CONFIG_LABEL, validate_key)) + raise NotImplementedError( + "Could not access jsonschema validation schema from config target '{}:{}'".format( + PLUGIN_ID_VALIDATE_JSONSCHEMA_SCHEMA_CONFIG_LABEL, validate_key)) elif isinstance(validate_target, dict): if not PLUGIN_ID_VALIDATE_JSONSCHEMA_SCHEMA_CONFIG_LABEL in validate_target: diff --git a/setup.cfg b/setup.cfg index 058ecdd..2002eda 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = configerus -version = 0.3.9 +version = 0.3.10 description = Configuration manager long_description = file: README.md long_description_content_type = text/markdown