Key-value pair based configuration for Python applications.
Implementation of key-value pair based configuration for Python applications.
Features:
This library is freely inspired by .NET Core Microsoft.Extensions.Configuration
namespace and its pleasant design (ref. MSDN documentation, Microsoft Extensions Configuration Deep Dive).
The main class is influenced by Luciano Ramalho`s example of
JSON structure explorer using attribute notation, in his book Fluent Python.
pip install roconfiguration
In this example, configuration will be comprised of anything inside a filesettings.yaml
and environmental variables. Settings are applied in order, so
environmental variables with matching name override values from the yaml
file.
from roconfiguration import Configuration
config = Configuration()
config.add_yaml_file("settings.yaml")
config.add_environmental_variables()
In this example, if an environmental variable with name APP_ENVIRONMENT
and
value dev
exists, and a configuration file with name settings.dev.yaml
is
present, it is read to override values configured in settings.yaml
file.
import os
from roconfiguration import Configuration
environment_name = os.environ["APP_ENVIRONMENT"]
config = Configuration()
config.add_yaml_file("settings.yaml")
config.add_yaml_file(f"settings.{environment_name}.yaml", optional=True)
config.add_environmental_variables()
import os
from roconfiguration import Configuration
config = Configuration()
# will read only environmental variables
# starting with "APP_", case insensitively
config.add_environmental_variables("APP_")
Ini files are parsed using the built-in configparser
module, therefore
support [DEFAULT]
section; all values are kept as strings.
from roconfiguration import Configuration
config = Configuration()
config.add_ini_file("settings.ini")
JSON files are parsed using the built-in json
module.
from roconfiguration import Configuration
config = Configuration()
config.add_json_file("settings.json")
from roconfiguration import Configuration
config = Configuration({"host": "localhost", "port": 8080})
config.add_map({"hello": "world", "example": [{"id": 1}, {"id": 2}]})
assert config.host == "localhost"
assert config.port == 8080
assert config.hello == "world"
assert config.example[0].id == 1
assert config.example[1].id == 2
from roconfiguration import Configuration
config = Configuration({"host": "localhost", "port": 8080})
config.add_value("port", 44555)
assert config.host == "localhost"
assert config.port == 44555
config = Configuration(
{
"a": {
"b": 1,
"c": 2,
"d": {
"e": 3,
"f": 4,
},
}
}
)
assert config.a.b == 1
assert config.a.d.e == 3
assert config.a.d.f == 4
config.add_value("a:d:e", 5)
assert config.a.d.e == 5
assert config.a.d.f == 4
config = Configuration(
{
"a": {
"b": 1,
"c": 2,
"d": {
"e": 3,
"f": 4,
},
}
}
)
assert config.a.b == 1
assert config.a.d.e == 3
assert config.a.d.f == 4
# NB: if an env variable such as:
# a:d:e=5
# or...
# a__d__e=5
#
# is defined, it overrides the value from the dictionary
config.add_environmental_variables()
assert config.a.d.e == 5
config = Configuration(
{
"b2c": [
{"tenant": "1"},
{"tenant": "2"},
{"tenant": "3"},
]
}
)
config.add_value("b2c:1:tenant", "4")
assert config.b2c[0].tenant == "1"
assert config.b2c[1].tenant == "4"
assert config.b2c[2].tenant == "3"
pip install -r requirements.txt
# run tests using automatic discovery:
pytest