I'm currently writing a web framework and I wanted to add a configuration module for reading environment variables and a configuration toml file.
Here is the code. The comment in the Config
class should explain it all.
import os
import sys
import toml
BASEPATH = os.path.dirname(sys.modules['__main__'].__file__)
print(BASEPATH)
FILEPATH = os.path.abspath(os.path.join(BASEPATH, 'config.toml'))
print(FILEPATH)
class ConfigError(KeyError):
""" Raised when a requested configuration can not be found """
class ConfigBase:
def __init__(self):
self.basename = ''
self.default_options = {}
raise TypeError('Should not use ConfigBase directly')
def __getitem__(self, item):
""" called when access like a dictionary
config['database']['username']
"""
default = self.default_options.get(item)
if isinstance(default, dict):
return ConfigSection(self.basename + '.' + item, default)
# Check for env var
envvar_string = '_'.join(self.basename.split('.') + [item]).upper()
env = os.getenv(envvar_string)
if env is None:
if default is None:
raise ConfigError(
'No configuration found for {}. '
'Add the environment variable {} or add'
' the key to your config.toml file'.format(
'.'.join((self.basename, item)),
envvar_string
))
return default
return env
class Config(ConfigBase):
""" load configuration from envvar or config file
You can get settings from environment variables or a config.toml file
Environment variables have a higher precedence over the config file
Use `config['section']['subsection']['key']` to get the value
SECTION_SUBSECTION_KEY from environment variables or
section.subsection.key from a toml file
(usually written:
[section.subsection]
key = value
in a toml file)
"""
def __init__(self):
self.default_options = self.load_config()
self.basename = ''
def load_config(self):
with open(FILEPATH, 'r') as f:
config = toml.load(f)
return config
class ConfigSection(ConfigBase):
def __init__(self, basename, defaults):
self.basename = basename.lstrip('.')
self.default_options = defaults