Source code for openscm_runner.settings
"""
Settings handling
Rather than hard-coding constants, configuration can be source from 2 different
sources:
* Environment variables
* dotenv files
Environment variables are always used in preference to the values in dotenv
files.
"""
import os
from dotenv import dotenv_values, find_dotenv
[docs]class ConfigLoader:
"""
Configuration container
Loads a local dotenv file containing configuration. An example of a
configuration file is provided in root of the project.
A combination of environment variables and dotenv files can be used as
configuration with an existing environment variables overriding a value
specified in a dotenv file.
All configuration is case-insensitive.
.. code:: python
>>> config = ConfigLoader()
>>> config["VALUE"]
Traceback (most recent call last):
...
KeyError: 'VALUE'
>>> config.get("VALUE", "some_default")
'some_default'
"""
def __init__(self):
self._config = {}
self.is_loaded = False
[docs] def load_config(self):
"""
Load configuration from disk
A dotenv file is attempted to be loaded. The first file named .env
in the current directory or any of its parents will read in.
If no dotenv files are found, then
"""
dotenv_cfg = dotenv_values(find_dotenv(usecwd=True), verbose=True)
self.update(dotenv_cfg)
# Add any extra files here
self.is_loaded = True
[docs] def get(self, key, default=None):
"""
Get value for a given key, falling back to a default value if not present.
Parameters
----------
key : str
Key
default: Any
Default value returned if no configuration for ``key`` is present.
Returns
-------
Any
Value with key ``item``. If not value is present ``default``
is returned.
"""
try:
return self[key]
except KeyError:
return default
def __getitem__(self, key):
"""
Get a config value for a given key
Parameters
----------
key: str
Key
Returns
-------
Any
Value with key ``item``
Raises
------
KeyError
No configuration values for the key were found
"""
if not self.is_loaded:
# Lazy loaded
self.load_config()
key = key.upper()
# Always preference environment variable
if key in os.environ:
return os.environ[key]
# Fall back to loaded config
# Preference determined by load order
if key in self._config:
return self._config[key]
# Raise KeyError if not found
raise KeyError(key)
[docs] def update(self, conf):
"""
Update the configuration
If configuration with duplicate keys already exists, then these values
will overwrite the existing values.
Parameters
----------
conf: dict
Configuration to use to update the config
"""
conf = {k.upper(): v for k, v in conf.items()}
self._config.update(conf)
config = ConfigLoader()